אתם יכולים לאפשר למשתמשים לבצע אימות ב-Firebase באמצעות ספקי OAuth כמו Microsoft Azure Active Directory. לשם כך, משלבים באפליקציה כניסה גנרית מבוססת-אינטרנט באמצעות OAuth באמצעות Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה.
לפני שמתחילים
כדי להיכנס למשתמשים באמצעות חשבונות Microsoft (Azure Active Directory ו-Individual חשבונות Microsoft), עליך להפעיל תחילה את Microsoft כספקית כניסה עבור לפרויקט Firebase שלכם:
- מוסיפים את Firebase לפרויקט ב-Apple.
- במסוף Firebase, פותחים את הקטע אימות.
- בכרטיסייה Sign in method, מפעילים את הספק Microsoft.
- מוסיפים את Client ID ואת Client Secret ממסוף המפתחים של הספק הזה אל
תצורת ספק:
- כדי לרשום לקוח Microsoft OAuth, פועלים לפי ההוראות הבאות: מדריך למתחילים: רישום אפליקציה באמצעות נקודת הקצה של Azure Active Directory גרסה 2.0. חשוב לשים לב שנקודת הקצה הזו תומכת בכניסה באמצעות חשבונות Microsoft לשימוש אישי וגם באמצעות Azure חשבונות Active Directory. מידע נוסף על Azure Active Directory v2.0
- כשרושמים אפליקציות אצל הספקים האלה, חשוב לרשום את
הדומיין
*.firebaseapp.com
של הפרויקט כדומיין ההפניה האוטומטית של אפליקציה.
- לוחצים על שמירה.
טיפול בתהליך הכניסה באמצעות Firebase SDK
כדי לטפל בתהליך הכניסה באמצעות ה-SDK של Firebase לפלטפורמות Apple:
מוסיפים סכימות של כתובות URL מותאמות אישית לפרויקט Xcode:
- פותחים את הגדרות הפרויקט: לוחצים לחיצה כפולה על שם הפרויקט בתצוגת העץ שמימין. בוחרים את האפליקציה בקטע יעדים, ואז בוחרים את הכרטיסייה מידע ומרחיבים את הקטע סוגי כתובות URL.
- לוחצים על הלחצן + ומוסיפים את מזהה האפליקציה המקודד בתור סכימה של כתובת URL. ניתן למצוא את מזהה האפליקציה המקודד
כללי
דף הגדרות במסוף Firebase, בקטע של iOS
אפליקציה. משאירים את שאר השדות ריקים.
בסיום התהליך, ההגדרה אמורה להיראות בערך כך הבא (אבל עם הערכים הספציפיים לאפליקציה שלך):
יוצרים מופע של OAuthProvider באמצעות מזהה הספק microsoft.com.
var provider = OAuthProvider(providerID: "microsoft.com")
FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"microsoft.com"];
אופציונלי: מציינים פרמטרים מותאמים אישית נוספים של OAuth שרוצים להגדיר שליחה עם בקשת ה-OAuth.
provider.customParameters = [ "prompt": "consent", "login_hint": "user@firstadd.onmicrosoft.com" ]
[provider setCustomParameters:@{@"prompt": @"consent", @"login_hint": @"user@firstadd.onmicrosoft.com"}];
הפרמטרים שבהם Microsoft תומכת מפורטים במסמכי התיעוד של Microsoft OAuth. שימו לב שאי אפשר להעביר פרמטרים שנדרשים ל-Firebase עם
setCustomParameters
הפרמטרים האלה הם client_id, response_type, redirect_uri, state, scope וגם response_mode.כדי לאפשר רק למשתמשים מדייר מסוים ב-Azure AD להיכנס לאפליקציה, אפשר להשתמש בשם הדומיין הידידותי של הדייר ב-Azure AD או במזהה ה-GUID של הדייר. כדי לעשות זאת, אפשר לציין ה-"tenant" באובייקט של הפרמטרים המותאמים אישית.
provider.customParameters = [ // Optional "tenant" parameter in case you are using an Azure AD // tenant. eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or // 'contoso.onmicrosoft.com' or "common" for tenant-independent // tokens. The default value is "common". "tenant": "TENANT_ID" ]
// Optional "tenant" parameter in case you are using an Azure AD tenant. // eg. '8eaef023-2b34-4da1-9baa-8bc8c9d6a490' or // 'contoso.onmicrosoft.com' or "common" for tenant-independent tokens. // The default value is "common". provider.customParameters = @{@"tenant": @"TENANT_ID"};
אופציונלי: מציינים היקפי הרשאות OAuth 2.0 נוספים מעבר לפרופיל הבסיסי שרוצים לבקש מספק האימות.
provider.scopes = ["mail.read", "calendars.read"]
[provider setScopes:@[@"mail.read", @"calendars.read"]];
מידע נוסף זמין מסמכי בנושא הרשאות והסכמה של Microsoft.
אופציונלי: אם רוצים להתאים אישית את האופן שבו האפליקציה מציגה את
SFSafariViewController
או אתUIWebView
כשהיא מציגה את reCAPTCHA למשתמש, יוצרים כיתה מותאמת אישית שתואמת לפרוטוקולAuthUIDelegate
ומעבירים אותה ל-credentialWithUIDelegate
.אימות באמצעות Firebase באמצעות אובייקט הספק של OAuth.
// Replace nil with the custom class that conforms to AuthUIDelegate // you created in last step to use a customized web view. 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 } } }
[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 }]; } }];
באמצעות אסימון הגישה של OAuth, אפשר לקרוא ל- Microsoft Graph API.
לדוגמה, כדי לקבל פרטי פרופיל בסיסיים, אפשר לקרוא ל-API ל-REST, העברת אסימון הגישה בכותרת
Authorization
:https://graph.microsoft.com/v1.0/me
בניגוד לספקים אחרים שנתמכים על ידי אימות Firebase, Microsoft לא מספקת כתובת URL של תמונה. במקום זאת, צריך לבקש את הנתונים הבינאריים של תמונת הפרופיל דרך Microsoft Graph API.
בנוסף לאסימון הגישה של OAuth, אפשר לאחזר מהאובייקט
OAuthCredential
גם את אסימון המזהה של המשתמש ב-OAuth. ההצהרהsub
באסימון המזהה היא ספציפית לאפליקציה ולא תותאם להצהרה המאוחדת מזהה משתמש שמשמש את Firebase Auth ונגיש דרךuser.providerData[0].uid
. במקום זאת, צריך להשתמש בשדה ההצהרהoid
. כשמשתמשים בדייר Azure AD כדי להיכנס לחשבון, ההצהרהoid
תהיה תואמת בדיוק. עם זאת, במקרה של חשבון שאינו של דייר, השדהoid
ממולא. למזהה מאוחד4b2eabcdefghijkl
, ה-oid
יהיה בפורמט00000000-0000-0000-4b2e-abcdefghijkl
.הדוגמאות שלמעלה מתמקדות בתהליכי כניסה, אבל אפשר גם לקשר ספק של Microsoft למשתמש קיים באמצעות
linkWithCredential
. לדוגמה, אפשר לקשר כמה ספקים לאותו משתמש ולאפשר לו להיכנס באמצעות כל אחד מהם.Auth().currentUser.link(withCredential: credential) { authResult, error in if error != nil { // Handle error. } // Microsoft 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 }
[[FIRAuth auth].currentUser linkWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error) { // Handle error. } // Microsoft 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 }];
אפשר להשתמש באותו קו ביטול נעילה עם
reauthenticateWithCredential
, ואפשר להשתמש בו כדי לאחזר פרטי כניסה חדשים עבור פעולות רגישות שמצריכות ביצוע של .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 }
[[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 }];
טיפול בשגיאות מסוג account-exists-with-different-credential
אם הפעלתם את ההגדרה One account per email address (חשבון אחד לכל כתובת אימייל) במסוף Firebase, כשמשתמש ינסה להיכנס לחשבון אצל ספק (כמו Microsoft) עם כתובת אימייל שכבר קיימת אצל ספק אחר של משתמש ב-Firebase (כמו Google), תוצג הודעת השגיאה FIRAuthErrorCodeAccountExistsWithDifferentCredential
יחד עם אובייקט FIRAuthCredential
זמני (פרטי כניסה של Microsoft). כדי להשלים את הכניסה לספק הרצוי, המשתמש צריך להיכנס קודם לספק הקיים (Google) ואז לקשר ל-FIRAuthCredential
הקודם (פרטי הכניסה ל-Microsoft). זה ייראה כך:
// 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 לא תומך באותה יכולת עבור ספקים כמו Microsoft, כי שרת האימות ב-Firebase לא יכול לאמת את הקהל של אסימוני הגישה של Microsoft ב-OAuth. זוהי דרישת אבטחה קריטית שעלולה לחשוף אפליקציות אתרים להעברה חוזרת של מתקפות שבהן התקבל אסימון גישה של Microsoft OAuth עבור אפשר להשתמש בפרויקט אחד (תוקפים) כדי להיכנס לפרויקט אחר (קורבן). במקום זאת, Firebase Auth מאפשר לטפל בכל תהליך OAuth ובהחלפת קוד ההרשאה באמצעות מזהה הלקוח והסוד של OAuth שהוגדרו במסוף Firebase. מאחר שניתן להשתמש רק בקוד ההרשאה יחד עם מזהה/סוד לקוח ספציפי, קוד הרשאה שהתקבלו עבור פרויקט אחד, לא יכולות לשמש בפרויקט אחר.
אם נדרש שימוש בספקים האלה בסביבות לא נתמכות, ספריית OAuth של צד שלישי אימות מותאם אישית ב-Firebase יצטרך להשתמש ב-Gemini. הראשון נדרש כדי לבצע אימות מול הספק, והשני נדרש כדי להחליף את פרטי הכניסה של הספק באסימון מותאם אישית.
אחרי שמשתמש נכנס בפעם הראשונה, נוצר חשבון משתמש חדש שמקושרות לפרטי הכניסה - כלומר שם המשתמש והסיסמה, מספר הטלפון מספר, או פרטים של ספק אימות – המשתמש נכנס באמצעותו. החשבון החדש הזה מאוחסן כחלק מפרויקט 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; }
כדאי גם להוסיף קוד טיפול בשגיאות לכל טווח האימות שגיאות. אפשר לקרוא על טיפול בשגיאות.