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

في حال الترقية إلى Firebase Authentication with Identity Platform، يمكنك إضافة مصادقة متعدّدة العوامل للرسائل القصيرة SMS. إلى تطبيق iOS.

تزيد المصادقة المتعدّدة العوامل من مستوى أمان تطبيقك. لا شك في أنّ المهاجمين اختراق كلمات المرور والحسابات الاجتماعية غالبًا، فإن اعتراض رسالة نصية أكثر صعوبة.

قبل البدء

  1. فعِّل موفّر خدمة واحدًا على الأقل يتيح المصادقة المتعدّدة العوامل. يتيح كل مقدّم خدمة المصادقة المتعدّدة القنوات (MFA)، باستثناء مصادقة الهاتف، والمصادقة المجهولة، Apple Game Center

  2. تأكَّد من أنّ تطبيقك يتحقّق من عناوين البريد الإلكتروني للمستخدمين. تتطلب MFA إثبات ملكية عنوان البريد الإلكتروني. يؤدي ذلك إلى منع الجهات الضارّة من التسجيل في خدمة باستخدام عنوان بريد إلكتروني. التي لا تملكها، ثم نحظر المالك الحقيقي من خلال إضافة علامة .

تفعيل المصادقة المتعدّدة العوامل

  1. افتح المصادقة > طريقة تسجيل الدخول في وحدة التحكم Firebase.

  2. في القسم الإعدادات المتقدّمة، فعِّل المصادقة المتعدّدة العوامل للرسائل القصيرة.

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

  3. إذا لم يسبق لك تفويض نطاق تطبيقك، أضِفه إلى نطاق السماح. في قائمة المصادقة > الإعدادات في وحدة التحكم Firebase.

إثبات ملكية تطبيقك

يحتاج "Firebase" إلى التأكّد من أنّ طلبات الرسائل القصيرة SMS واردة من التطبيق. يمكنك القيام بذلك بطريقتين:

  • إشعارات أسماء نقاط الوصول الصامتة: عند تسجيل دخول مستخدم لأول مرة، يمكن لتطبيق "Firebase" إرسال إشعار فوري صامت إلى جهاز المستخدم. الخاص بك. يمكن متابعة المصادقة في حال تلقّي التطبيق الإشعار. لاحظ أنه بدءًا من iOS 8.0، لا تحتاج إلى مطالبة المستخدم بالسماح بالدفع الإشعارات لاستخدام هذه الطريقة.

  • التحقق من CAPTCHA: إذا لم تتمكن من إرسال إشعار صامت (على سبيل المثال، مثلاً، لأنّ المستخدم أوقف إعادة تحميل الخلفية، أو أنّك تختبر لتطبيقك في محاكي iOS)، يمكنك استخدام reCAPTCHA. في كثير من الحالات، يتم حل reCAPTCHA تلقائيًا بدون تفاعل من المستخدم.

استخدام الإشعارات الصامتة

لتفعيل إشعارات أسماء نقاط الوصول (APN) للاستخدام مع Firebase:

  1. في Xcode، فعِّل الإشعارات الفورية. لمشروعك.

  2. تحميل مفتاح مصادقة أسماء نقاط الوصول (APN) باستخدام "وحدة تحكُّم Firebase" (التغييرات التي أجريتها سيتم نقله تلقائيًا إلى Google Cloud Firebase). إذا لم يكن لديك مفتاح مصادقة أسماء نقاط الوصول (APN)، يمكنك مراجعة إعداد أسماء نقاط الوصول (APN) باستخدام "المراسلة عبر السحابة الإلكترونية من Firebase" لمعرفة كيفية الحصول عليها.

    1. افتح وحدة تحكُّم Firebase.

    2. انتقِل إلى Project Settings (إعدادات المشروع).

    3. حدد علامة التبويب المراسلة عبر السحابة الإلكترونية.

    4. ضِمن مفتاح مصادقة أسماء نقاط الوصول (APN)، في إعدادات تطبيق iOS انقر على تحميل.

    5. اختَر مفتاحك.

    6. أضِف رقم تعريف المفتاح. يمكنك العثور على رقم تعريف المفتاح ضمن الشهادات والمعرفات الملفات الشخصية في مركز أعضاء مطوّري برامج Apple

    7. انقر على تحميل.

إذا كانت لديك شهادة أسماء نقاط الوصول (APN) من قبل، يمكنك تحميل الشهادة بدلاً من ذلك.

استخدام اختبار reCAPTCHA

لتفعيل حزمة تطوير البرامج (SDK) للعميل من استخدام reCAPTCHA:

  1. افتح إعدادات مشروعك في Xcode.

  2. انقر مرّتين على اسم المشروع في العرض التدرّجي الأيمن.

  3. اختَر تطبيقك من قسم الأهداف.

  4. انقر على علامة التبويب المعلومات.

  5. وسِّع قسم أنواع عناوين URL.

  6. انقر على الزر +.

  7. أدخِل معرِّف العميل العكسي في الحقل مخططات عناوين URL. يمكنك الاطّلاع على تم إدراج هذه القيمة في ملف إعداد GoogleService-Info.plist باسم REVERSED_CLIENT_ID

عند الانتهاء، يجب أن تبدو الإعدادات مشابهة لما يلي:

المخطّطات المخصَّصة

يمكنك اختياريًا تخصيص طريقة عرض تطبيقك SFSafariViewController أو UIWebView عند عرض reCAPTCHA. للقيام بذلك، إذًا، أنشِئ فئة مخصّصة تتوافق مع بروتوكول FIRAuthUIDelegate. وأرسِله إلى verifyPhoneNumber:UIDelegate:completion:

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

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

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

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

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

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

تسجيل عامل ثانٍ

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

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

  2. اطلب من المستخدم إدخال رقم هاتفه.

  3. الحصول على جلسة متعددة العوامل للمستخدم:

    Swift

    authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in
      // ...
    }
    

    Objective-C

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. أرسِل رسالة تحقُّق إلى هاتف المستخدم. تأكد من أن رقم الهاتف بتنسيق + في البداية بدون علامات ترقيم أو مسافات بيضاء أخرى (مع مثال: +15105551234)

    Swift

    // Send SMS verification code.
    PhoneAuthProvider.provider().verifyPhoneNumber(
      phoneNumber,
      uiDelegate: nil,
      multiFactorSession: session) { (verificationId, error) in
        // verificationId will be needed for enrollment completion.
    }
    

    Objective-C

    // Send SMS verification code.
    [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber
                                          UIDelegate:nil
                                  multiFactorSession:session
                                          completion:^(NSString * _Nullable verificationID,
                                                        NSError * _Nullable error) {
        // verificationId will be needed for enrollment completion.
    }];
    

    رغم أن الأمر ليس مطلوبًا، إلا أنها من أفضل الممارسات إعلام المستخدمين مسبقًا بأنه سيتلقّى رسالة قصيرة، وتسري هذه الأسعار القياسية.

    تبدأ طريقة verifyPhoneNumber() عملية التحقق من التطبيقات خلال الخلفية باستخدام الإشعارات الفورية الصامتة. في حال تفعيل الإشعارات الفورية الصامتة غير متاح، تم إصدار تحدي reCAPTCHA بدلاً من ذلك.

  5. بعد إرسال رمز SMS، اطلب من المستخدم التحقّق من الرمز. بعد ذلك، استخدم لإنشاء PhoneAuthCredential:

    Swift

    // Ask user for the verification code. Then:
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId,
      verificationCode: verificationCode)
    

    Objective-C

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider
                                           credentialWithVerificationID:verificationID
                                           verificationCode:kPhoneSecondFactorVerificationCode];
    
  6. إعداد كائن تأكيد:

    Swift

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objective-C

    FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  7. أكمِل عملية التسجيل. يمكنك اختياريًا تحديد اسم معروض والعامل الثاني. وهذا مفيد للمستخدمين الذين لديهم عوامل ثانية متعددة، حيث إن يتم إخفاء رقم الهاتف أثناء تدفق المصادقة (على مثال، +1******1234).

    Swift

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
      // ...
    }
    

    Objective-C

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    [authResult.user.multiFactor enrollWithAssertion:assertion
                                         displayName:nil
                                          completion:^(NSError * _Nullable error) {
        // ...
    }];
    

يوضح الرمز أدناه مثالاً كاملاً لتسجيل عامل ثانٍ:

Swift

let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
  // Send SMS verification code.
  PhoneAuthProvider.provider().verifyPhoneNumber(
    phoneNumber,
    uiDelegate: nil,
    multiFactorSession: session
  ) { (verificationId, error) in
    // verificationId will be needed for enrollment completion.
    // Ask user for the verification code.
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId!,
      verificationCode: phoneSecondFactorVerificationCode)
    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
      // ...
    }
  }
})

Objective-C

FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                              NSError * _Nullable error) {
    // Send SMS verification code.
    [FIRPhoneAuthProvider.provider
      verifyPhoneNumber:phoneNumber
      UIDelegate:nil
      multiFactorSession:session
      completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
        // verificationId will be needed for enrollment completion.

        // Ask user for the verification code.
        // ...

        // Then:
        FIRPhoneAuthCredential *credential =
            [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
                                                        verificationCode:kPhoneSecondFactorVerificationCode];
        FIRMultiFactorAssertion *assertion =
            [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];

        // Complete enrollment. This will update the underlying tokens
        // and trigger ID token change listener.
        [user.multiFactor enrollWithAssertion:assertion
                                  displayName:displayName
                                    completion:^(NSError * _Nullable error) {
            // ...
        }];
    }];
}];

تهانينا لقد سجَّلت بنجاح عامل مصادقة ثانٍ مستخدم.

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

لتسجيل دخول مستخدم باستخدام ميزة إثبات الهوية عبر الرسائل القصيرة SMS:

  1. سجّل دخول المستخدم بعامله الأول، ثم ستظهر لك رسالة خطأ تشير إلى تكون المصادقة متعددة العوامل مطلوبة. يحتوي هذا الخطأ على برنامج تعيين، ومؤشرات بشأن العوامل الثانية المسجلة، والجلسة الأساسية يثبت أن المستخدم تمت مصادقته بنجاح مع العامل الأول.

    على سبيل المثال، إذا كان العامل الأول للمستخدم هو البريد الإلكتروني وكلمة المرور:

    Swift

    Auth.auth().signIn(
      withEmail: email,
      password: password
    ) { (result, error) in
      let authError = error as NSError
      if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
        // The user is a multi-factor user. Second factor challenge is required.
        let resolver =
          authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
        // ...
      } else {
        // Handle other errors such as wrong password.
      }
    }
    

    Objective-C

    [FIRAuth.auth signInWithEmail:email
                         password:password
                       completion:^(FIRAuthDataResult * _Nullable authResult,
                                    NSError * _Nullable error) {
        if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
            // User is not enrolled with a second factor and is successfully signed in.
            // ...
        } else {
            // The user is a multi-factor user. Second factor challenge is required.
        }
    }];
    

    إذا كان العامل الأول للمستخدم هو موفر خدمة موحدة، مثل OAuth، ابحث عن حدث خطأ بعد الاتصال بـ getCredentialWith().

  2. إذا كان المستخدم لديه عدة عوامل ثانوية تم تسجيلها، اسأله عن العوامل الثانوية. للاستخدام. يمكنك الحصول على رقم الهاتف المقنَّع باستخدام resolver.hints[selectedIndex].phoneNumber والاسم المعروض مع resolver.hints[selectedIndex].displayName

    Swift

    // Ask user which second factor to use. Then:
    if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID {
      // User selected a phone second factor.
      // ...
    } else if resolver.hints[selectedIndex].factorID == TotpMultiFactorID {
      // User selected a TOTP second factor.
      // ...
    } else {
      // Unsupported second factor.
    }
    

    Objective-C

    FIRMultiFactorResolver *resolver =
        (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
    
    // Ask user which second factor to use. Then:
    FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
    if (hint.factorID == FIRPhoneMultiFactorID) {
      // User selected a phone second factor.
      // ...
    } else if (hint.factorID == FIRTOTPMultiFactorID) {
      // User selected a TOTP second factor.
      // ...
    } else {
      // Unsupported second factor.
    }
    
  3. إرسال رسالة تحقق إلى هاتف المستخدم:

    Swift

    // Send SMS verification code.
    let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
    PhoneAuthProvider.provider().verifyPhoneNumber(
      with: hint,
      uiDelegate: nil,
      multiFactorSession: resolver.session
    ) { (verificationId, error) in
      // verificationId will be needed for sign-in completion.
    }
    

    Objective-C

    // Send SMS verification code
    [FIRPhoneAuthProvider.provider
      verifyPhoneNumberWithMultiFactorInfo:hint
      UIDelegate:nil
      multiFactorSession:resolver.session
      completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
        if (error != nil) {
            // Failed to verify phone number.
        }
    }];
    
  4. بعد إرسال رمز SMS، اطلب من المستخدم التحقّق من الرمز واستخدامه إنشاء PhoneAuthCredential:

    Swift

    // Ask user for the verification code. Then:
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId!,
      verificationCode: verificationCodeFromUser)
    

    Objective-C

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential =
        [FIRPhoneAuthProvider.provider
          credentialWithVerificationID:verificationID
                      verificationCode:verificationCodeFromUser];
    
  5. إعداد كائن تأكيد باستخدام بيانات الاعتماد:

    Swift

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objective-C

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. التعامل بشكل نهائي مع عملية تسجيل الدخول. ويمكنك بعد ذلك الوصول إلى النتيجة الأصلية لتسجيل الدخول، تتضمن بيانات اعتماد المصادقة والبيانات الخاصة بمقدِّم الخدمة العادية:

    Swift

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(with: assertion) { (authResult, error) in
      // authResult will also contain the user, additionalUserInfo, optional
      // credential (null for email/password) associated with the first factor sign-in.
    
      // For example, if the user signed in with Google as a first factor,
      // authResult.additionalUserInfo will contain data related to Google provider that
      // the user signed in with.
    
      // user.credential contains the Google OAuth credential.
      // user.credential.accessToken contains the Google OAuth access token.
      // user.credential.idToken contains the Google OAuth ID token.
    }
    

    Objective-C

    // Complete sign-in.
    [resolver resolveSignInWithAssertion:assertion
                              completion:^(FIRAuthDataResult * _Nullable authResult,
                                            NSError * _Nullable error) {
        if (error != nil) {
            // User successfully signed in with the second factor phone number.
        }
    }];
    

يوضح الرمز أدناه مثالاً كاملاً لتسجيل دخول مستخدم متعدد العوامل:

Swift

Auth.auth().signIn(
  withEmail: email,
  password: password
) { (result, error) in
  let authError = error as NSError?
  if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
    let resolver =
      authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver

    // Ask user which second factor to use.
    // ...

    // Then:
    let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo

    // Send SMS verification code
    PhoneAuthProvider.provider().verifyPhoneNumber(
      with: hint,
      uiDelegate: nil,
      multiFactorSession: resolver.session
    ) { (verificationId, error) in
      if error != nil {
        // Failed to verify phone number.
      }
      // Ask user for the SMS verification code.
      // ...

      // Then:
      let credential = PhoneAuthProvider.provider().credential(
        withVerificationID: verificationId!,
        verificationCode: verificationCodeFromUser)
      let assertion = PhoneMultiFactorGenerator.assertion(with: credential)

      // Complete sign-in.
      resolver.resolveSignIn(with: assertion) { (authResult, error) in
        if error != nil {
          // User successfully signed in with the second factor phone number.
        }
      }
    }
  }
}

Objective-C

[FIRAuth.auth signInWithEmail:email
                     password:password
                   completion:^(FIRAuthDataResult * _Nullable authResult,
                               NSError * _Nullable error) {
    if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
        // User is not enrolled with a second factor and is successfully signed in.
        // ...
    } else {
        FIRMultiFactorResolver *resolver =
            (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];

        // Ask user which second factor to use.
        // ...

        // Then:
        FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];

        // Send SMS verification code
        [FIRPhoneAuthProvider.provider
          verifyPhoneNumberWithMultiFactorInfo:hint
                                    UIDelegate:nil
                            multiFactorSession:resolver.session
                                    completion:^(NSString * _Nullable verificationID,
                                                NSError * _Nullable error) {
            if (error != nil) {
                // Failed to verify phone number.
            }

            // Ask user for the SMS verification code.
            // ...

            // Then:
            FIRPhoneAuthCredential *credential =
                [FIRPhoneAuthProvider.provider
                  credentialWithVerificationID:verificationID
                              verificationCode:kPhoneSecondFactorVerificationCode];
            FIRMultiFactorAssertion *assertion =
                [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];

            // Complete sign-in.
            [resolver resolveSignInWithAssertion:assertion
                                      completion:^(FIRAuthDataResult * _Nullable authResult,
                                                    NSError * _Nullable error) {
                if (error != nil) {
                    // User successfully signed in with the second factor phone number.
                }
            }];
        }];
    }
}];

تهانينا تم تسجيل دخول مستخدم بنجاح باستخدام عوامل متعددة المصادقة.

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