אתם יכולים לאפשר למשתמשים לבצע אימות ב-Firebase באמצעות ספקי OAuth כמו Yahoo. לשם כך, משלבים את OAuth Login הגנרי באפליקציה באמצעות Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה.
לפני שמתחילים
כדי להיכנס משתמשים באמצעות חשבונות Yahoo, קודם צריך להפעיל את Yahoo בתור כניסה הספק של פרויקט Firebase שלכם:
- מוסיפים את Firebase לפרויקט ב-Apple.
- במסוף Firebase, פותחים את הקטע Auth.
- בכרטיסייה שיטת כניסה, מפעילים את הספק Yahoo.
- מוסיפים את Client ID ואת Client Secret ממסוף המפתחים של הספק הזה אל
תצורת ספק:
-
כדי לרשום לקוח OAuth של Yahoo, פועלים לפי ההוראות במסמכי העזרה למפתחים של Yahoo בנושא רישום אפליקציית אינטרנט ב-Yahoo.
חשוב לבחור את שתי ההרשאות של OpenID Connect API:
profile
ו-email
. - כשרושמים אפליקציות אצל הספקים האלה, חשוב לרשום את
הדומיין
*.firebaseapp.com
של הפרויקט כדומיין ההפניה האוטומטית של אפליקציה.
-
- לוחצים על שמירה.
טיפול בתהליך הכניסה באמצעות Firebase SDK
כדי לבצע את תהליך הכניסה באמצעות ה-SDK של פלטפורמות Apple ב-Firebase, פועלים לפי השלבים הבאים:
מוסיפים סכימות של כתובות URL מותאמות אישית לפרויקט Xcode:
- פותחים את הגדרות הפרויקט: לוחצים לחיצה כפולה על שם הפרויקט תצוגת עץ שמאלית בוחרים את האפליקציה בקטע TARGETS, ואז לוחצים על הכרטיסייה Info ומרחיבים את הקטע URL Types.
- לוחצים על הלחצן + ומוסיפים את מזהה האפליקציה המקודד ככתובת URL.
scheme. ניתן למצוא את מזהה האפליקציה המקודד
כללי
דף הגדרות במסוף Firebase, בקטע של iOS
אפליקציה. משאירים את שאר השדות ריקים.
בסיום התהליך, ההגדרה אמורה להיראות בערך כך הבא (אבל עם הערכים הספציפיים לאפליקציה שלך):
יוצרים מופע של OAuthProvider באמצעות מזהה הספק yahoo.com.
var provider = OAuthProvider(providerID: "yahoo.com")
FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"yahoo.com"];
אופציונלי: מציינים פרמטרים מותאמים אישית נוספים של OAuth שרוצים להגדיר שליחה עם בקשת ה-OAuth.
provider.customParameters = [ "prompt": "login", "language": "fr" ]
[provider setCustomParameters:@{@"prompt": @"login", @"language": @"fr"}];
הפרמטרים שבהם Yahoo תומכת מפורטים במסמכי התיעוד של Yahoo OAuth. שימו לב שאי אפשר להעביר פרמטרים שנדרשים ל-Firebase עם
setCustomParameters
הפרמטרים האלה הם client_id, redirect_uri, response_type, scope ו-state.אופציונלי: אפשר לציין היקפי הרשאות OAuth 2.0 נוספים, מעבר ל-
profile
וכןemail
שברצונך לבקש מספק האימות. אם נדרשת גישה לנתוני משתמשים פרטיים מ-Yahoo APIs, תצטרכו לבקש הרשאות ל-Yahoo APIs בקטע הרשאות API Yahoo Developer Console. היקפי ה-OAuth המבוקשים חייבים להיות זהים להיקפים שהוגדרו מראש בהרשאות ה-API של האפליקציה. לדוגמה, אם בוחרים בקריאה/כתיבה הם מתבקשים לגשת לאנשי הקשר של המשתמשים, והם מוגדרים מראש ב-API של האפליקציה הרשאות, צריך להעביר אתsdct-w
במקום היקף הרשאות ה-OAuth לקריאה בלבדsdct-r
. אחרת, התהליך ייכשל ותוצג שגיאה למשתמש קצה.// Request access to Yahoo Mail API. // Request read/write access to user contacts. // This must be preconfigured in the app's API permissions. provider.scopes = ["mail-r", "sdct-w"]
// Request access to Yahoo Mail API. // Request read/write access to user contacts. // This must be preconfigured in the app's API permissions. [provider setScopes:@[@"mail-r", @"sdct-w"]];
למידע נוסף, אפשר לעיין במסמכי התיעוד בנושא היקפי הרשאה ב-Yahoo.
אופציונלי: אם רוצים להתאים אישית את האופן שבו האפליקציה מציגה את
SFSafariViewController
או אתUIWebView
כשהיא מציגה את reCAPTCHA למשתמש, יוצרים כיתה מותאמת אישית שתואמת לפרוטוקולAuthUIDelegate
ומעבירים אותה ל-credentialWithUIDelegate
.אימות באמצעות Firebase באמצעות אובייקט הספק של OAuth.
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. // Yahoo OAuth access token can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // Yahoo OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken } } }
[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. // Yahoo OAuth access token can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // Yahoo OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }]; } }];
באמצעות אסימון הגישה של OAuth, אפשר לקרוא ל- Yahoo API
לדוגמה, כדי לקבל פרטי פרופיל בסיסיים, אפשר לקרוא ל-API ל-REST, העברת אסימון הגישה בכותרת
Authorization
:https://social.yahooapis.com/v1/user/YAHOO_USER_UID/profile?format=json
כאשר
YAHOO_USER_UID
הוא מזהה המשתמש ב-Yahoo שאפשר לאחזר מ: השדהAuth.auth.currentUser.providerData[0].uid
או מתוךauthResult.additionalUserInfo.profile
.הדוגמאות שלמעלה מתמקדות בתהליכי כניסה, אבל אפשר גם לקשר ספק של Yahoo למשתמש קיים באמצעות
linkWithPopup
. לדוגמה, אפשר לקשר מספר ספקים לאותו משתמש, כדי לאפשר להם להיכנס עם אחד מהם.Auth().currentUser.link(withCredential: credential) { authResult, error in if error != nil { // Handle error. } // Yahoo credential is linked to the current user. // IdP data available in authResult.additionalUserInfo.profile. // Yahoo OAuth access token can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // Yahoo OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken }
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { // Handle error. } // Yahoo credential is linked to the current user. // IdP data available in authResult.additionalUserInfo.profile. // Yahoo OAuth access token is can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // Yahoo OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }];
אפשר להשתמש באותו דפוס עם
reauthenticateWithPopup
/reauthenticateWithRedirect
, כדי לאחזר פרטי כניסה עדכניים לפעולות רגישות שדורשות התחברות מהזמן האחרון.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 is can also be retrieved by: // (authResult.credential as? OAuthCredential)?.accessToken // Yahoo OAuth ID token can be retrieved by calling: // (authResult.credential as? OAuthCredential)?.idToken }
[[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 is can also be retrieved by: // ((FIROAuthCredential *)authResult.credential).accessToken // Yahoo OAuth ID token can be retrieved by calling: // ((FIROAuthCredential *)authResult.credential).idToken }];
טיפול בשגיאות מסוג account-exists-with-different-credential
אם הפעלתם את ההגדרה חשבון אחד לכל כתובת אימייל במסוף Firebase,
כשמשתמש מנסה להיכנס לחשבון אצל ספק (למשל Yahoo) באמצעות כתובת אימייל שכבר
קיים לספק אחר של משתמש Firebase (כמו Google), השגיאה
זריקת FIRAuthErrorCodeAccountExistsWithDifferentCredential
ביחד עם ערך זמני
אובייקט FIRAuthCredential
(פרטי כניסה ל-Yahoo). כדי להשלים את הכניסה אל
הספק הקיים צריך להיכנס קודם לספק הקיים (Google) ואז לקשר
FIRAuthCredential
לשעבר (פרטי כניסה ל-Yahoo). זה ייראה כך:
// Sign-in with an OAuth credential. provider.getCredentialWith(nil) { credential, error in // An account with the same email already exists. if (error as NSError?)?.code == AuthErrorCode.accountExistsWithDifferentCredential.rawValue { // Get pending credential and email of existing account. let existingAcctEmail = (error! as NSError).userInfo[AuthErrorUserInfoEmailKey] as! String let pendingCred = (error! as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as! AuthCredential // Lookup existing account identifier by the email. Auth.auth().fetchProviders(forEmail:existingAcctEmail) { providers, error in // Existing email/password account. if (providers?.contains(EmailAuthProviderID))! { // Existing password account for email. Ask user to provide the password of the // existing account. // Sign in with existing account. Auth.auth().signIn(withEmail:existingAcctEmail, password:password) { user, error in // Successfully signed in. if user != nil { // Link pending credential to account. Auth.auth().currentUser?.linkAndRetrieveData(with: pendingCred) { result, error in // ... } } } } } return } // Other errors. if error != nil { // handle the error. return } // Sign in with the credential. if credential != nil { Auth.auth().signInAndRetrieveData(with: credential!) { result, error in if error != nil { // handle the error. return } } } }
// Sign-in with an OAuth credential. [provider getCredentialWithUIDelegate:nil completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) { // An account with the same email already exists. if (error.code == FIRAuthErrorCodeAccountExistsWithDifferentCredential) { // Get pending credential and email of existing account. NSString *existingAcctEmail = error.userInfo[FIRAuthErrorUserInfoEmailKey]; FIRAuthCredential *pendingCred = error.userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey]; // Lookup existing account identifier by the email. [[FIRAuth auth] fetchProvidersForEmail:existingAcctEmail completion:^(NSArray<NSString *> *_Nullable providers, NSError *_Nullable error) { // Existing email/password account. if ( [providers containsObject:FIREmailAuthProviderID] ) { // Existing password account for email. Ask user to provide the password of the // existing account. // Sign in with existing account. [[FIRAuth auth] signInWithEmail:existingAcctEmail password:password completion:^(FIRUser *user, NSError *error) { // Successfully signed in. if (user) { // Link pending credential to account. [[FIRAuth auth].currentUser linkWithCredential:pendingCred completion:^(FIRUser *_Nullable user, NSError *_Nullable error) { // ... }]; } }]; } }]; return; } // Other errors. if (error) { // handle the error. return; } // Sign in with the credential. if (credential) { [[FIRAuth auth] signInAndRetrieveDataWithCredential:credential completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) { if (error) { // handle the error. return; } }]; } }];
מתקדם: טיפול בתהליך הכניסה באופן ידני
בניגוד לספקי OAuth אחרים שנתמכים על ידי Firebase, כמו Google, Facebook, וב-Twitter, שבהם אפשר להיכנס ישירות לחשבון באמצעות אסימון גישה ל-OAuth שמבוססים על פרטי כניסה, אימות Firebase לא תומך באותה יכולת עבור כמו Yahoo בגלל חוסר היכולת של Firebase שרת אימות לאימות הקהל של אסימוני הגישה של Yahoo OAuth. זוהי דרישת אבטחה קריטית, והיא עלולה לחשוף אפליקציות ואתרים למתקפות של שחזור, שבהן אפשר להשתמש באסימון גישה של Yahoo OAuth שנוצר לפרויקט אחד (תוקף) כדי להיכנס לפרויקט אחר (קורבן). במקום זאת, Firebase Auth מאפשר לטפל בכל תהליך OAuth ובהחלפת קוד ההרשאה באמצעות מזהה הלקוח והסוד של OAuth שהוגדרו במסוף Firebase. מאחר שניתן להשתמש רק בקוד ההרשאה יחד עם מזהה/סוד לקוח ספציפי, קוד הרשאה שהתקבלו עבור פרויקט אחד, לא יכולות לשמש בפרויקט אחר.
אם צריך להשתמש בספקים האלה בסביבות שלא נתמכות, צריך להשתמש בספריית OAuth של צד שלישי ובאימות מותאם אישית של Firebase. הראשון נדרש כדי לבצע אימות מול הספק, והשני נדרש כדי להחליף את פרטי הכניסה של הספק באסימון מותאם אישית.
השלבים הבאים
אחרי שמשתמש נכנס בפעם הראשונה, נוצר חשבון משתמש חדש שמקושרות לפרטי הכניסה - כלומר שם המשתמש והסיסמה, מספר הטלפון מספר, או פרטים של ספק אימות – המשתמש נכנס באמצעותו. החדש הזה מאוחסנים כחלק מפרויקט Firebase, וניתן להשתמש בהם כדי לזהות משתמש בכל האפליקציות בפרויקט, בלי קשר לאופן שבו המשתמשים נכנסים לחשבון.
-
באפליקציות שלכם, תוכלו לקבל את פרטי הפרופיל הבסיסיים של המשתמש דרך
User
. למידע נוסף, ראו ניהול משתמשים. בתוך Firebase Realtime Database ו-Cloud Storage כללי אבטחה – מקבלים את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה
auth
, ולהשתמש בהם כדי לקבוע לאילו נתונים המשתמש יוכל לגשת.
אפשר לאפשר למשתמשים להיכנס לאפליקציה באמצעות מספר סוגי אימות מספקים באמצעות קישור פרטי הכניסה של ספק האימות קיים חשבון משתמש קיים.
כדי לנתק משתמש מהחשבון, יש להתקשר אל
signOut:
let firebaseAuth = Auth.auth() do { try firebaseAuth.signOut() } catch let signOutError as NSError { print("Error signing out: %@", signOutError) }
NSError *signOutError; BOOL status = [[FIRAuth auth] signOut:&signOutError]; if (!status) { NSLog(@"Error signing out: %@", signOutError); return; }
כדאי גם להוסיף קוד טיפול בשגיאות לכל טווח האימות שגיאות. אפשר לעיין במאמר טיפול בשגיאות.