إضافة المصادقة المتعدّدة العوامل (TOTP) إلى تطبيق iOS

إذا أجريت الترقية إلى Firebase Authentication with Identity Platform، يمكنك إضافة المصادقة المتعدّدة العوامل (MFA) باستخدام كلمة مرور صالحة لمرة واحدة مستندة إلى الوقت (TOTP) إلى تطبيقك.

يتيح لك Firebase Authentication with Identity Platform استخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) كعامل إضافي للمصادقة المتعدّدة العوامل (MFA). عند تفعيل هذه الميزة، سيظهر للمستخدمين الذين يحاولون تسجيل الدخول إلى تطبيقك طلب بإدخال كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP). لإنشاء هذا الرمز، يجب استخدام تطبيق مصادقة قادر على إنشاء رموز TOTP صالحة، مثل Google Authenticator.

قبل البدء

  1. فعِّل موفّرًا واحدًا على الأقل يتيح استخدام المصادقة المتعدّدة العوامل. يُرجى العِلم أنّ جميع مقدّمي الخدمات باستثناء ما يلي يتيحون المصادقة المتعدّدة العوامل:

    • المصادقة عبر الهاتف
    • المصادقة المجهولة الهوية
    • رموز المصادقة المخصّصة
    • Apple Game Center
  2. تأكَّد من أنّ تطبيقك يتحقّق من عناوين البريد الإلكتروني للمستخدمين. تتطلّب المصادقة المتعدّدة العوامل تأكيد عنوان البريد الإلكتروني. يمنع ذلك الجهات المسيئة من التسجيل في خدمة باستخدام عنوان بريد إلكتروني لا يملكونه، ثم منع المالك الفعلي من الوصول إلى عنوان البريد الإلكتروني من خلال إضافة عامل ثانٍ.

  3. ثبِّت حزمة تطوير البرامج (SDK) لمنصّة Firebase على أجهزة Apple إذا لم يسبق لك ذلك.

    لا تتوفّر ميزة المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) إلا في الإصدار 10.12.0 من حزمة تطوير البرامج (SDK) من Apple والإصدارات الأحدث، وعلى نظام التشغيل iOS فقط.

تفعيل المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)

لتفعيل TOTP كعامل ثانٍ، استخدِم Admin SDK أو اتصِل بنقطة نهاية REST لإعدادات المشروع.

لاستخدام Admin SDK، اتّبِع الخطوات التالية:

  1. ثبِّت حزمة تطوير البرامج (SDK) لمشرف Firebase في Node.js إذا لم يسبق لك تثبيتها.

    لا تتوفّر ميزة المصادقة المتعدّدة العوامل (MFA) باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) إلا في الإصدار 11.6.0 والإصدارات الأحدث من حزمة تطوير البرامج (SDK) الخاصة بـ Node.js في Firebase Admin.

  2. نفِّذ ما يلي:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: NUM_ADJ_INTERVALS
                  }
              }]
          }
    })
    

    غيِّر القيم في السلسلة على الشكل التالي:

    • ‫NUM_ADJ_INTERVALS: عدد الفواصل الزمنية المتجاورة التي يتم قبول كلمات المرور لمرة واحدة المستندة إلى الوقت (TOTP) منها، من صفر إلى عشرة القيمة التلقائية هي خمسة.

      تعمل كلمات المرور لمرة واحدة المستندة إلى الوقت (TOTP) من خلال ضمان أنّه عندما ينشئ طرفان (المُثبِت والمُدقِّق) كلمات مرور صالحة لمرة واحدة (OTP) خلال الفترة الزمنية نفسها (عادةً 30 ثانية)، فإنّهما ينشئان كلمة المرور نفسها. ومع ذلك، لاستيعاب انحراف الساعة بين الأطراف ووقت الاستجابة البشرية، يمكنك ضبط خدمة TOTP لقبول كلمات المرور لمرة واحدة المستندة إلى الوقت من النوافذ المجاورة أيضًا.

لتفعيل المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) من خلال REST API، نفِّذ ما يلي:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": NUM_ADJ_INTERVALS
            }
          }]
       }
    }'

غيِّر القيم في السلسلة على الشكل التالي:

  • ‫PROJECT_ID: رقم تعريف المشروع
  • ‫NUM_ADJ_INTERVALS: عدد الفواصل الزمنية، من صفر إلى عشرة العدد التلقائي هو خمسة.

    تعمل كلمات المرور لمرة واحدة المستندة إلى الوقت (TOTP) من خلال ضمان أنّه عندما ينشئ طرفان (المُثبِت والمُدقِّق) كلمات مرور صالحة لمرة واحدة (OTP) خلال الفترة الزمنية نفسها (عادةً 30 ثانية)، فإنّهما ينشئان كلمة المرور نفسها. ومع ذلك، لاستيعاب انحراف الساعة بين الأطراف ووقت الاستجابة البشرية، يمكنك ضبط خدمة TOTP لقبول كلمات المرور لمرة واحدة المستندة إلى الوقت من النوافذ المجاورة أيضًا.

اختيار نمط تسجيل

يمكنك اختيار ما إذا كان تطبيقك يتطلّب المصادقة المتعدّدة العوامل، وكيفية تسجيل المستخدمين ومتى. تشمل بعض الأنماط الشائعة ما يلي:

  • تسجيل العامل الثاني للمستخدم كجزء من عملية التسجيل استخدِم هذه الطريقة إذا كان تطبيقك يتطلّب مصادقة متعدّدة العوامل لجميع المستخدمين.

  • توفير خيار قابل للتخطّي لتسجيل عامل ثانٍ أثناء التسجيل إذا كنت تريد تشجيع المصادقة متعددة العوامل في تطبيقك ولكن لا تطلبها، فيمكنك استخدام هذا الأسلوب.

  • توفير إمكانية إضافة عامل ثانٍ من صفحة إدارة حساب المستخدم أو ملفه الشخصي، بدلاً من شاشة الاشتراك. يقلّل ذلك من المشاكل أثناء عملية التسجيل، مع إتاحة المصادقة المتعدّدة العوامل للمستخدمين الذين يهتمون بالأمان.

  • يجب إضافة عامل أمان ثانٍ بشكل تدريجي عندما يريد المستخدم الوصول إلى الميزات التي تتطلّب مستوى أمان أعلى.

تسجيل المستخدمين في ميزة "المصادقة المتعدّدة العوامل" باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)

بعد تفعيل ميزة TOTP MFA كعامل ثانٍ لتطبيقك، يمكنك تنفيذ منطق من جهة العميل لتسجيل المستخدمين في ميزة TOTP MFA:

  1. أعِد مصادقة المستخدم.

  2. أنشئ مفتاحًا سريًا لكلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) للمستخدم الذي تمت مصادقته:

    // Generate a TOTP secret.
    guard let mfaSession = try? await currentUser.multiFactor.session() else { return }
    guard let totpSecret = try? await TOTPMultiFactorGenerator.generateSecret(with: mfaSession) else { return }
    
    // Display the secret to the user and prompt them to enter it into their
    // authenticator app. (See the next step.)
    
  3. اعرض المفتاح السري للمستخدم واطلب منه إدخاله في تطبيق المصادقة:

    // Display this key:
    let secret = totpSecret.sharedSecretKey()
    

    بالإضافة إلى عرض المفتاح السري، يمكنك محاولة إضافته تلقائيًا إلى تطبيق المصادقة التلقائي على الجهاز. لإجراء ذلك، أنشئ معرّف موارد منتظم (URI) للمفتاح متوافق مع Google Authenticator، وأرسِله إلى openInOTPApp(withQRCodeURL:):

    let otpAuthUri = totpSecret.generateQRCodeURL(
        withAccountName: currentUser.email ?? "default account",
        issuer: "Your App Name")
    totpSecret.openInOTPApp(withQRCodeURL: otpAuthUri)
    

    بعد أن يضيف المستخدم مفتاحه السري إلى تطبيق المصادقة، سيبدأ التطبيق في إنشاء كلمات مرور لمرة واحدة مستندة إلى الوقت (TOTP).

  4. اطلب من المستخدم كتابة كلمة المرور لمرة واحدة المستندة إلى الوقت (TOTP) المعروضة في تطبيق المصادقة واستخدامها لإكمال عملية التسجيل في المصادقة المتعددة العوامل:

    // Ask the user for a verification code from the authenticator app.
    let verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    let multiFactorAssertion = TOTPMultiFactorGenerator.assertionForEnrollment(
        with: totpSecret,
        oneTimePassword: verificationCode)
    do {
        try await currentUser.multiFactor.enroll(
            with: multiFactorAssertion,
            displayName: "TOTP")
    } catch {
        // Wrong or expired OTP. Re-prompt the user.
    }
    

تسجيل دخول المستخدمين باستخدام عامل ثانٍ

لتسجيل دخول المستخدمين باستخدام TOTP MFA، استخدِم الرمز التالي:

  1. استدعِ إحدى طرق signIn(with...:)- كما لو كنت لا تستخدم المصادقة المتعدّدة العوامل (على سبيل المثال، signIn(withEmail:password:)). إذا عرضت الطريقة خطأً مع الرمز secondFactorRequired، ابدأ عملية المصادقة المتعدّدة العوامل في تطبيقك.

    do {
        let authResult = try await Auth.auth().signIn(withEmail: email, password: password)
    
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch let error as AuthErrorCode where error.code == .secondFactorRequired {
        // Initiate your second factor sign-in flow. (See next step.)
        // ...
    } catch {
        // Other auth error.
        throw error
    }
    
  2. يجب أن يطلب تدفق المصادقة المتعدّدة العوامل في تطبيقك أولاً من المستخدم اختيار العامل الثاني الذي يريد استخدامه. يمكنك الحصول على قائمة بعوامل المصادقة الثنائية المتوافقة من خلال فحص السمة hints لمثيل MultiFactorResolver:

    let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
    guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return }
    let enrolledFactors = resolver.hints.map(\.displayName)
    
  3. إذا اختار المستخدم استخدام TOTP، اطلب منه كتابة TOTP المعروض على تطبيق المصادقة واستخدامه لتسجيل الدخول:

    let multiFactorInfo = resolver.hints[selectedIndex]
    switch multiFactorInfo.factorID {
    case TOTPMultiFactorID:
        let otpFromAuthenticator = // OTP typed by the user.
        let assertion = TOTPMultiFactorGenerator.assertionForSignIn(
            withEnrollmentID: multiFactorInfo.uid,
            oneTimePassword: otpFromAuthenticator)
        do {
            let authResult = try await resolver.resolveSignIn(with: assertion)
        } catch {
            // Wrong or expired OTP. Re-prompt the user.
        }
    default:
        return
    }
    

إلغاء التسجيل في ميزة "المصادقة المتعدّدة العوامل" (MFA) باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)

يصف هذا القسم كيفية التعامل مع إلغاء تسجيل مستخدم من المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP).

إذا اشترك مستخدم في خيارات متعددة للمصادقة المتعددة العوامل، وألغى تسجيله من الخيار الذي تم تفعيله مؤخرًا، سيتلقّى auth/user-token-expired وسيتم تسجيل خروجه. على المستخدم تسجيل الدخول مرة أخرى وإثبات صحة بيانات الاعتماد الحالية، مثل عنوان البريد الإلكتروني وكلمة المرور.

لإلغاء تسجيل المستخدم ومعالجة الخطأ وبدء إعادة المصادقة، استخدِم الرمز التالي:

guard let currentUser = Auth.auth().currentUser else { return }

// Prompt the user to select a factor to unenroll, from this array:
currentUser.multiFactor.enrolledFactors

// ...

// Unenroll the second factor.
let multiFactorInfo = currentUser.multiFactor.enrolledFactors[selectedIndex]
do {
    try await currentUser.multiFactor.unenroll(with: multiFactorInfo)
} catch let error as AuthErrorCode where error.code == .invalidUserToken {
    // Second factor unenrolled, but the user was signed out. Re-authenticate
    // them.
}

الخطوات التالية