הוסף אימות מרובה גורמים לאפליקציית iOS שלך

אם שדרגת ל-Firebase Authentication with Identity Platform, תוכל להוסיף אימות רב-גורמי SMS לאפליקציית iOS שלך.

אימות רב-גורמי מגביר את האבטחה של האפליקציה שלך. בעוד שתוקפים מתפשרים לעתים קרובות על סיסמאות וחשבונות חברתיים, יירוט הודעת טקסט קשה יותר.

לפני שאתה מתחיל

  1. אפשר לפחות ספק אחד שתומך באימות רב-גורמי. כל ספק תומך ב-MFA, למעט אישור טלפוני, אישור אנונימי ומרכז המשחקים של Apple.

  2. ודא שהאפליקציה שלך מאמתת אימיילים של משתמשים. MFA דורש אימות דוא"ל. זה מונע משחקנים זדוניים להירשם לשירות עם אימייל שאינם בבעלותם, ולאחר מכן לנעול את הבעלים האמיתי על ידי הוספת גורם שני.

הפעלת אימות מרובה גורמים

  1. פתח את הדף אימות > שיטת כניסה של מסוף Firebase.

  2. בקטע מתקדם , הפעל אימות רב-גורמי של SMS .

    עליך להזין גם את מספרי הטלפון שאיתם תבדוק את האפליקציה שלך. אמנם אופציונלי, אך מומלץ מאוד לרשום מספרי טלפון לבדיקה כדי למנוע מצערת במהלך הפיתוח.

  3. אם עדיין לא אישרת את הדומיין של האפליקציה שלך, הוסף אותו לרשימת ההיתרים בדף אימות > הגדרות של מסוף Firebase.

מאמת את האפליקציה שלך

Firebase צריך לאמת שבקשות SMS מגיעות מהאפליקציה שלך. אתה יכול לעשות זאת בשתי דרכים:

  • התראות APN שקטות : כאשר אתה נכנס למשתמש בפעם הראשונה, Firebase יכול לשלוח הודעת דחיפה שקטה למכשיר של המשתמש. האימות יכול להמשיך אם האפליקציה תקבל את ההודעה. שים לב שהחל מ-iOS 8.0, אינך צריך לבקש מהמשתמש לאפשר הודעות דחיפה כדי להשתמש בשיטה זו.

  • אימות reCAPTCHA : אם אינך יכול לשלוח הודעה שקטה (לדוגמה, בגלל שהמשתמש השבית את רענון הרקע, או שאתה בודק את האפליקציה שלך בסימולטור iOS), אתה יכול להשתמש ב-reCAPTCHA. במקרים רבים, ה-reCAPTCHA יפתור את עצמו באופן אוטומטי ללא אינטראקציה של המשתמש.

שימוש בהתראות שקטות

כדי להפעיל התראות APNs לשימוש עם Firebase:

  1. ב-Xcode, אפשר הודעות דחיפה עבור הפרויקט שלך.

  2. העלה את מפתח האימות של ה-APN שלך באמצעות מסוף Firebase (השינויים שלך יועברו אוטומטית ל-Google Cloud Firebase). אם עדיין אין לך מפתח אימות APNs שלך, ראה הגדרת APNs עם FCM כדי ללמוד כיצד להשיג אותו.

    1. פתח את מסוף Firebase .

    2. נווט אל הגדרות הפרויקט .

    3. בחר בכרטיסייה הודעות בענן .

    4. תחת מפתח אימות APN , בקטע תצורת אפליקציית iOS , לחץ על העלה .

    5. בחר את המפתח שלך.

    6. הוסף את מזהה המפתח עבור המפתח. אתה יכול למצוא את מזהה המפתח תחת אישורים, מזהים ופרופילים ב- Apple Developer Member Center .

    7. לחץ על העלה .

אם כבר יש לך אישור APNs, אתה יכול להעלות את האישור במקום זאת.

משתמש באימות reCAPTCHA

כדי לאפשר ל-SDK של הלקוח להשתמש ב-reCAPTCHA:

  1. פתח את תצורת הפרויקט שלך ב-Xcode.

  2. לחץ פעמיים על שם הפרויקט בתצוגת העץ השמאלית.

  3. בחר את האפליקציה שלך מקטע היעדים .

  4. בחר בכרטיסייה מידע .

  5. הרחב את הקטע סוגי כתובות אתרים .

  6. לחץ על הלחצן + .

  7. הזן את מזהה הלקוח ההפוך שלך בשדה סכימות URL . אתה יכול למצוא ערך זה רשום בקובץ התצורה GoogleService-Info.plist בתור REVERSED_CLIENT_ID .

בסיום, התצורה שלך אמורה להיראות דומה לזה:

תוכניות מותאמות אישית

לחלופין, אתה יכול להתאים אישית את האופן שבו האפליקציה שלך מציגה את SFSafariViewController או UIWebView בעת הצגת ה-reCAPTCHA. כדי לעשות זאת, צור מחלקה מותאמת אישית התואמת את פרוטוקול FIRAuthUIDelegate , והעבר אותו ל- verifyPhoneNumber:UIDelegate:completion: .

בחירת דפוס הרשמה

אתה יכול לבחור אם האפליקציה שלך דורשת אימות רב-גורמי, וכיצד ומתי לרשום את המשתמשים שלך. כמה דפוסים נפוצים כוללים:

  • רשום את הגורם השני של המשתמש כחלק מההרשמה. השתמש בשיטה זו אם האפליקציה שלך דורשת אימות רב-גורמי עבור כל המשתמשים. שים לב שלחשבון חייבת להיות כתובת אימייל מאומתת כדי לרשום גורם שני, כך שזרימת ההרשמה שלך תצטרך להתאים זאת.

  • הצע אפשרות ניתנת לדילוג כדי לרשום גורם שני במהלך ההרשמה. אפליקציות שרוצות לעודד, אך לא דורשות, אימות רב-גורמי עשויות להעדיף גישה זו.

  • ספק את היכולת להוסיף גורם שני מדף ניהול החשבון או הפרופיל של המשתמש, במקום מסך ההרשמה. זה ממזער את החיכוך במהלך תהליך הרישום, תוך מתן אימות רב-גורמי לזמין עבור משתמשים רגישים לאבטחה.

  • דרוש הוספת גורם שני בהדרגה כאשר המשתמש רוצה לגשת לתכונות עם דרישות אבטחה מוגברות.

רישום גורם שני

כדי לרשום גורם משני חדש עבור משתמש:

  1. אימות מחדש של המשתמש.

  2. בקשו מהמשתמש להזין את מספר הטלפון שלו.

  3. קבל הפעלה מרובה גורמים עבור המשתמש:

    מָהִיר

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

    Objective-C

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. שלח הודעת אימות לטלפון של המשתמש. ודא שמספר הטלפון מעוצב עם + מוביל וללא סימני פיסוק או רווחים אחרים (לדוגמה: +15105551234 )

    מָהִיר

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

    אמנם לא חובה, אך שיטת העבודה המומלצת היא ליידע את המשתמשים מראש שהם יקבלו הודעת SMS וכי חלים תעריפים סטנדרטיים.

    שיטת verifyPhoneNumber() מתחילה תהליך אימות אפליקציה ברקע באמצעות הודעת דחיפה שקטה. אם הודעת דחיפה שקטה אינה זמינה, במקום זאת מונפק אתגר reCAPTCHA.

  5. לאחר שליחת קוד ה-SMS, בקש מהמשתמש לאמת את הקוד. לאחר מכן, השתמש בתגובה שלהם כדי לבנות PhoneAuthCredential :

    מָהִיר

    // 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. אתחול אובייקט קביעה:

    מָהִיר

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objective-C

    FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  7. השלם את ההרשמה. לחלופין, תוכל לציין שם תצוגה עבור הגורם השני. זה שימושי למשתמשים עם מספר גורמים שניים, מכיוון שמספר הטלפון מוסווה במהלך זרימת האימות (לדוגמה, +1********1234).

    מָהִיר

    // 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) {
        // ...
    }];
    

הקוד שלהלן מציג דוגמה מלאה של רישום גורם שני:

מָהִיר

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. היכנס למשתמש עם הגורם הראשון שלו, ואז תופס שגיאה המציינת שנדרש אימות מרובה גורמים. שגיאה זו מכילה פותר, רמזים על הגורמים השניים שנרשמו, והפעלה בסיסית המוכיחה שהמשתמש אומת בהצלחה עם הגורם הראשון.

    לדוגמה, אם הגורם הראשון של המשתמש היה דוא"ל וסיסמה:

    מָהִיר

    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 .

    מָהִיר

    // 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. שלח הודעת אימות לטלפון של המשתמש:

    מָהִיר

    // 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 :

    מָהִיר

    // 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. אתחול אובייקט קביעה עם האישור:

    מָהִיר

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objective-C

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. פתור את הכניסה. לאחר מכן תוכל לגשת לתוצאת הכניסה המקורית, הכוללת את הנתונים הסטנדרטיים הספציפיים לספק ואישורי אימות:

    מָהִיר

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

הקוד שלהלן מציג דוגמה מלאה לכניסה למשתמש מרובה גורמים:

מָהִיר

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.
                }
            }];
        }];
    }
}];

מזל טוב! נכנסת בהצלחה למשתמש באמצעות אימות רב-גורמי.

מה הלאה