אימות באמצעות OpenID Connect בפלטפורמות של Apple

אם שדרגת ל-Firebase Authentication with Identity Platform, תוכל לאמת את המשתמשים שלך באמצעות Firebase באמצעות ספק תואם OpenID Connect (OIDC) לבחירתכם. כך תוכלו להשתמש בספקי זהויות שלא נתמכים באופן מקורי ב-Firebase.

לפני שמתחילים

כדי לאפשר למשתמשים להיכנס באמצעות ספק OIDC, קודם צריך לאסוף מהספק כמה פרטים:

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

  • Client secret: מחרוזת סודית שבה הספק משתמש כדי לאשר את הבעלות של מזהה הלקוח. לכל מזהה לקוח צריך סוד לקוח תואם. (הערך הזה נדרש רק אם אתם משתמשים בתהליך קוד האימות, שמומלץ מאוד להשתמש בו).

  • Issuer: מחרוזת שמזהה את הספק שלך. הערך הזה חייב להיות כתובת URL שמצורף ל-/.well-known/openid-configuration, הוא המיקום של מסמך הגילוי מסוג OIDC של הספק. לדוגמה, אם המנפיק הוא https://auth.example.com, מסמך הגילוי חייב להיות זמין בכתובת https://auth.example.com/.well-known/openid-configuration.

אחרי שמקבלים את המידע שלמעלה, מפעילים את OpenID Connect כספק כניסה לפרויקט ב-Firebase:

  1. מוסיפים את Firebase לפרויקט ל-iOS.

  2. אם לא שדרגתם ל-Firebase Authentication with Identity Platform, צריך לשדרג את המינוי. אימות OpenID Connect זמינה רק בפרויקטים משודרגים.

  3. בדף Sign-in providers במסוף Firebase, לוחצים על Add new provider ואז על OpenID Connect.

  4. בוחרים אם להשתמש בהרשאה באמצעות קוד או הענקת זרם הענקת גישה משתמע.

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

  5. נותנים שם לספק הזה. שימו לב למזהה הספק שנוצר: משהו כמו oidc.example-provider. תצטרכו את המזהה הזה כשתוסיפו לאפליקציה קוד כניסה.

  6. מציינים את מזהה הלקוח ואת סוד הלקוח ואת מחרוזת המנפיק של הספק. הערכים האלה חייבים להיות זהים לערכים שהוקצו לכם על ידי הספק.

  7. שומרים את השינויים.

טיפול בתהליך הכניסה באמצעות Firebase SDK

הדרך הקלה ביותר לאמת את המשתמשים ב-Firebase באמצעות ה-OIDC הוא לטפל בכל תהליך הכניסה באמצעות ה-SDK של Firebase.

כדי לבצע את תהליך הכניסה באמצעות ה-SDK של פלטפורמות Apple ב-Firebase, צריך לפעול לפי השלבים הבאים שלבים:

  1. מוסיפים לפרויקט Xcode סכמות של כתובות URL בהתאמה אישית:

    1. פותחים את הגדרות הפרויקט: לוחצים לחיצה כפולה על שם הפרויקט תצוגת עץ שמאלית בוחרים את האפליקציה בקטע TARGETS, ואז לוחצים על הכרטיסייה Info ומרחיבים את הקטע URL Types.
    2. לוחצים על הלחצן + ומוסיפים את מזהה האפליקציה המקודד ככתובת URL. scheme. מזהה האפליקציה המקודד מופיע בדף General Settings במסוף Firebase, בקטע של האפליקציה ל-iOS. משאירים את שאר השדות ריקים.

      בסיום, הקטע של הגדרות ה-config אמור להיראות בערך כך (אבל עם הערכים הספציפיים לאפליקציה שלכם):

      צילום מסך של ממשק ההגדרה של סכימה של כתובת URL מותאמת אישית ב-Xcode
  2. יוצרים מכונה של OAuthProvider באמצעות מזהה הספק שקיבלת במסוף Firebase.

    Swift

    var provider = OAuthProvider(providerID: "oidc.example-provider")
    

    Objective-C

    FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"oidc.example-provider"];
    
  3. אופציונלי: מציינים פרמטרים מותאמים אישית נוספים של OAuth שרוצים לשלוח עם בקשת ה-OAuth.

    Swift

    provider.customParameters = [
      "login_hint": "user@example.com"
    ]
    

    Objective-C

    [provider setCustomParameters:@{@"login_hint": @"user@example.com"}];
    

    מומלץ לברר עם הספק אילו פרמטרים הוא תומך. שימו לב: אי אפשר להעביר פרמטרים שנדרשים ל-Firebase באמצעות setCustomParameters. הפרמטרים האלה הם client_id,‏ response_type,‏ redirect_uri,‏ state,‏ scope ו-response_mode.

  4. אופציונלי: מציינים היקפי הרשאות OAuth 2.0 נוספים מעבר לפרופיל הבסיסי שרוצים לבקש מספק האימות.

    Swift

    provider.scopes = ["mail.read", "calendars.read"]
    

    Objective-C

    [provider setScopes:@[@"mail.read", @"calendars.read"]];
    

    מומלץ לברר עם הספק את היקפי ההרשאות שנתמכים בו.

  5. אופציונלי: אם אתם רוצים להתאים אישית את האופן שבו האפליקציה מציגה את SFSafariViewController או את UIWebView כשהיא מציגה את reCAPTCHA למשתמש, תוכלו ליצור כיתה מותאמת אישית שתואמת לפרוטוקול AuthUIDelegate.

  6. מבצעים אימות עם Firebase באמצעות אובייקט של ספק OAuth.

    Swift

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    provider.getCredentialWith(nil) { credential, error in
      if error != nil {
        // Handle error.
      }
      if credential != nil {
        Auth().signIn(with: credential) { authResult, error in
          if error != nil {
            // Handle error.
          }
          // User is signed in.
          // IdP data available in authResult.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.accessToken
          // OAuth ID token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.idToken
        }
      }
    }
    

    Objective-C

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    [provider getCredentialWithUIDelegate:nil
                                completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) {
      if (error) {
        // Handle error.
      }
      if (credential) {
        [[FIRAuth auth] signInWithCredential:credential
                                  completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
          if (error) {
            // Handle error.
          }
          // User is signed in.
          // IdP data available in authResult.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).accessToken
          // OAuth ID token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).idToken
        }];
      }
    }];
    
  7. הדוגמאות שלמעלה מתמקדות בתהליכי כניסה, אבל אפשר גם לקשר ספק OIDC למשתמש קיים באמצעות linkWithCredential. לדוגמה, אפשר לקשר מספר ספקים לאותו משתמש, כדי לאפשר להם להיכנס עם אחד מהם.

    Swift

    Auth().currentUser.link(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    Objective-C

    [[FIRAuth auth].currentUser
        linkWithCredential:credential
                completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    
  8. אפשר להשתמש באותו דפוס עם reauthenticateWithCredential, כדי לאחזר פרטי כניסה עדכניים לפעולות רגישות שדורשות התחברות מהזמן האחרון.

    Swift

    Auth().currentUser.reauthenticateWithCredential(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // User is re-authenticated with fresh tokens minted and
      // should be able to perform sensitive operations like account
      // deletion and email or password update.
      // IdP data available in result.additionalUserInfo.profile.
      // Additional OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    Objective-C

    [[FIRAuth auth].currentUser
        reauthenticateWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // User is re-authenticated with fresh tokens minted and
      // should be able to perform sensitive operations like account
      // deletion and email or password update.
      // IdP data available in result.additionalUserInfo.profile.
      // Additional OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    

איך מטפלים בתהליך הכניסה באופן ידני

אם כבר הטמעתם באפליקציה את תהליך הכניסה באמצעות OpenID Connect, יכולים להשתמש ישירות באסימון המזהה כדי לבצע אימות מול Firebase:

Swift

let credential = OAuthProvider.credential(
    withProviderID: "oidc.example-provider",  // As registered in Firebase console.
    idToken: idToken,  // ID token from OpenID Connect flow.
    rawNonce: nil
)
Auth.auth().signIn(with: credential) { authResult, error in
    if error {
        // Handle error.
        return
    }
    // User is signed in.
    // IdP data available in authResult?.additionalUserInfo?.profile
}

Objective-C

FIROAuthCredential *credential =
    [FIROAuthProvider credentialWithProviderID:@"oidc.example-provider"  // As registered in Firebase console.
                                       IDToken:idToken  // ID token from OpenID Connect flow.
                                      rawNonce:nil];
[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                      NSError * _Nullable error) {
    if (error != nil) {
        // Handle error.
        return;
    }
    // User is signed in.
    // IdP data available in authResult.additionalUserInfo.profile
}];

השלבים הבאים

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

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

  • בכללי האבטחה של Firebase Realtime Database ו-Cloud Storage, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש שנכנס לחשבון מהמשתנה auth, ולהשתמש בו כדי לקבוע לאילו נתונים למשתמש תהיה גישה.

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

כדי להוציא משתמש מהחשבון, קוראים לפונקציה signOut:.

Swift

let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}

Objective-C

NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

כדאי גם להוסיף קוד לטיפול בשגיאות בשביל כל טווח האימות שגיאות. אפשר לעיין בקטע טיפול בשגיאות.