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

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

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

قبل البدء

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

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

  3. ثبِّت حزمة تطوير البرامج (SDK) من Firebase لنظام التشغيل Apple إذا لم يسبق لك إجراء ذلك.

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

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

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

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

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

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

  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) لقبول كلمات المرور هذه من الفترات الزمنية المتجاورة أيضًا.

لتفعيل المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (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) لقبول كلمات المرور هذه من الفترات الزمنية المتجاورة أيضًا.

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

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

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

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

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

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

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

بعد تفعيل المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) كعامل ثانٍ لتطبيقك، عليك تنفيذ منطق من جهة العميل لتسجيل المستخدمين في المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP):

  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) التي يعرضها تطبيق المصادقة واستخدامها لإنهاء عملية التسجيل في المصادقة المتعدّدة العوامل (MFA):

    // 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.
    }
    

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

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

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

    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. يجب أن تطلب عملية المصادقة المتعدّدة العوامل (MFA) في تطبيقك أولاً من المستخدم اختيار العامل الثاني الذي يريد استخدامه. يمكنك الحصول على قائمة بالعوامل الثانية المتاحة من خلال فحص السمة hints في مثيل MultiFactorResolver:

    let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
    guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return }
    let enrolledFactors = resolver.hints.map(\.displayName)
    
  3. إذا اختار المستخدم استخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (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)

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

إذا كان المستخدم قد اشترك في خيارات متعدّدة للمصادقة المتعدّدة العوامل (MFA)، وإذا ألغى تسجيله في الخيار الذي تم تفعيله مؤخرًا، سيتلقّى رسالة 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.
}

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