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

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

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

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

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

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

  • 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. פותחים את הגדרות הפרויקט: לוחצים לחיצה כפולה על שם הפרויקט בתצוגת העץ שמימין. בוחרים את האפליקציה בקטע יעדים, ואז בוחרים את הכרטיסייה מידע ומרחיבים את הקטע סוגי כתובות URL.
    2. לוחצים על הלחצן + ומוסיפים את מזהה האפליקציה המקודד ככתובת URL. scheme. מזהה האפליקציה המקודד מופיע בדף General Settings במסוף Firebase, בקטע של האפליקציה ל-iOS. משאירים את שאר השדות ריקים.

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

      צילום מסך של ממשק ההגדרה של סכימה של כתובת 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;
}

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