אתם יכולים לאפשר למשתמשים שלכם לבצע אימות באמצעות Firebase באמצעות Apple ID שלהם, על ידי שימוש ב-Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה של OAuth 2.0.
לפני שמתחילים
כדי לאפשר למשתמשים להיכנס באמצעות Apple, קודם צריך להגדיר את הכניסה באמצעות Apple באתר למפתחים של Apple, ואז להפעיל את Apple כספק כניסה בפרויקט Firebase.
הצטרפות לתוכנית המפתחים של Apple
רק חברים בתוכנית המפתחים של Apple יכולים להגדיר כניסה באמצעות Apple.
הגדרת כניסה באמצעות Apple
באתר Apple Developer, מבצעים את הפעולות הבאות:
-
משייכים את האתר לאפליקציה כמו שמתואר בקטע הראשון של הגדרת כניסה באמצעות Apple לאתר. כשמופיעה הבקשה, רושמים את כתובת ה-URL הבאה ככתובת URL להחזרה:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
מזהה הפרויקט ב-Firebase מופיע בכרטיסייה General (כללי) בקטע
Settings (הגדרות) במסוף Firebase.בסיום, רושמים את מזהה השירות החדש, שיהיה נחוץ בקטע הבא.
- יוצרים מפתח פרטי של 'כניסה באמצעות אפל'. בקטע הבא תצטרכו את המפתח הפרטי החדש ואת מזהה המפתח.
-
אם אתם משתמשים בתכונות של Firebase Authentication ששולחות אימיילים למשתמשים, כולל כניסה באמצעות קישור באימייל, אימות כתובת אימייל, ביטול שינוי בחשבון ועוד, אתם צריכים להגדיר את שירות העברת האימייל הפרטי של אפל ולרשום את
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(או את הדומיין של תבנית האימייל המותאמת אישית שלכם) כדי שאפל תוכל להעביר אימיילים שנשלחים על ידי Firebase Authentication לכתובות אימייל אנונימיות של אפל.
הפעלת Apple כספק כניסה
- מוסיפים את Firebase לפרויקט.
- במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות).
- בכרטיסייה שיטת כניסה, מפעילים את ספק הכניסה Apple. מציינים את מזהה השירות שיצרתם בקטע הקודם. בנוסף, בקטע OAuth code flow configuration (הגדרת זרימת קוד OAuth), מציינים את מזהה הצוות שלכם ב-Apple, את המפתח הפרטי ואת מזהה המפתח שיצרתם בקטע הקודם.
עמידה בדרישות של Apple לגבי נתונים שעברו אנונימיזציה
התכונה 'כניסה באמצעות Apple' מאפשרת למשתמשים להפוך את הנתונים שלהם לאנונימיים, כולל כתובת האימייל, בזמן הכניסה. משתמשים שבוחרים באפשרות הזו מקבלים כתובות אימייל עם הדומיין privaterelay.appleid.com. כשמשתמשים בתכונה 'כניסה באמצעות Apple' באפליקציה, צריך לפעול בהתאם לכללי המדיניות או לתנאים הרלוונטיים למפתחים של Apple בנוגע למזהי Apple האנונימיים האלה.
זה כולל קבלת הסכמה מהמשתמש לפני שמשייכים פרטים אישיים מזהים ישירות למזהה Apple אנונימי. כשמשתמשים באימות ב-Firebase, זה עשוי לכלול את הפעולות הבאות:
- קישור של כתובת אימייל ל-Apple ID שעבר אנונימיזציה או להפך.
- קישור מספר טלפון ל-Apple ID אנונימי או להיפך
- לקשר פרטי כניסה לרשתות חברתיות שלא עברו אנונימיזציה (פייסבוק, Google וכו') למזהה Apple שעבר אנונימיזציה או להיפך.
הרשימה שלמעלה היא חלקית. כדי לוודא שהאפליקציה עומדת בדרישות של Apple, אפשר לעיין בהסכם הרישיון של Apple Developer Program בקטע Membership (חברות) בחשבון הפיתוח.
טיפול בתהליך הכניסה באמצעות Firebase SDK
אם אתם מפתחים אפליקציית אינטרנט, הדרך הקלה ביותר לאמת את המשתמשים באמצעות Firebase דרך חשבונות Apple שלהם היא לטפל בכל תהליך הכניסה באמצעות Firebase JavaScript SDK.
כדי לטפל בתהליך הכניסה באמצעות Firebase JavaScript SDK, פועלים לפי השלבים הבאים:
יוצרים מופע של OAuthProvider באמצעות מזהה הספק המתאים apple.com.
Web
import { OAuthProvider } from "firebase/auth"; const provider = new OAuthProvider('apple.com');
Web
var provider = new firebase.auth.OAuthProvider('apple.com');
אופציונלי: מציינים היקפי הרשאות נוספים של OAuth 2.0 מעבר לברירת המחדל שרוצים לבקש מספק האימות.
Web
provider.addScope('email'); provider.addScope('name');
Web
provider.addScope('email'); provider.addScope('name');
כברירת מחדל, כשמופעלת האפשרות חשבון אחד לכל כתובת אימייל, Firebase מבקש הרשאות גישה לכתובת האימייל ולשם. אם משנים את ההגדרה הזו לכמה חשבונות לכל כתובת אימייל, Firebase לא מבקש הרשאות גישה מ-Apple, אלא אם מציינים אותן.
אופציונלי: אם רוצים להציג את מסך הכניסה של אפל בשפה שאינה אנגלית, מגדירים את הפרמטר
locale. במסמכים בנושא 'כניסה באמצעות Apple' מפורטים הלוקאלים הנתמכים.Web
provider.setCustomParameters({ // Localize the Apple authentication screen in French. locale: 'fr' });
Web
provider.setCustomParameters({ // Localize the Apple authentication screen in French. locale: 'fr' });
מתבצע אימות באמצעות Firebase באמצעות אובייקט ספק OAuth. אפשר להציג למשתמשים חלון קופץ או להפנות אותם לדף הכניסה כדי להיכנס באמצעות חשבונות Apple שלהם. עדיף להשתמש בשיטת ההפניה במכשירים ניידים.
כדי להיכנס באמצעות חלון קופץ, מתקשרים אל
signInWithPopup():Web
import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth"; const auth = getAuth(); signInWithPopup(auth, provider) .then((result) => { // The signed-in user info. const user = result.user; // Apple credential const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; const idToken = credential.idToken; // IdP data available using getAdditionalUserInfo(result) // ... }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
Web
firebase .auth() .signInWithPopup(provider) .then((result) => { /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // The signed-in user info. var user = result.user; // You can also get the Apple OAuth Access and ID Tokens. var accessToken = credential.accessToken; var idToken = credential.idToken; // IdP data available using getAdditionalUserInfo(result) // ... }) .catch((error) => { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; // The email of the user's account used. var email = error.email; // The firebase.auth.AuthCredential type that was used. var credential = error.credential; // ... });
כדי להיכנס באמצעות הפניה לדף הכניסה, קוראים ל-
signInWithRedirect():
כדאי לפעול לפי השיטות המומלצות כשמשתמשים ב-
signInWithRedirect, ב-linkWithRedirectאו ב-reauthenticateWithRedirect.Web
import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);
Web
firebase.auth().signInWithRedirect(provider);
אחרי שהמשתמש משלים את הכניסה וחוזר לדף, אפשר לקבל את תוצאת הכניסה על ידי קריאה ל-
getRedirectResult():Web
import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth"; // Result from Redirect auth flow. const auth = getAuth(); getRedirectResult(auth) .then((result) => { const credential = OAuthProvider.credentialFromResult(result); if (credential) { // You can also get the Apple OAuth Access and ID Tokens. const accessToken = credential.accessToken; const idToken = credential.idToken; } // The signed-in user info. const user = result.user; }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
Web
// Result from Redirect auth flow. firebase .auth() .getRedirectResult() .then((result) => { if (result.credential) { /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // You can get the Apple OAuth Access and ID Tokens. var accessToken = credential.accessToken; var idToken = credential.idToken; // IdP data available in result.additionalUserInfo.profile. // ... } // The signed-in user info. var user = result.user; }) .catch((error) => { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; // The email of the user's account used. var email = error.email; // The firebase.auth.AuthCredential type that was used. var credential = error.credential; // ... });
כאן גם אפשר לזהות ולטפל בשגיאות. רשימה של קודי שגיאה זמינה בהפניית ה-API.
בניגוד לספקים אחרים שנתמכים על ידי Firebase Auth, Apple לא מספקת כתובת URL של תמונה.
בנוסף, אם המשתמש בוחר לא לשתף את כתובת האימייל שלו עם האפליקציה, אפל מספקת כתובת אימייל ייחודית למשתמש (בפורמט
xyz@privaterelay.appleid.com) ומשתפת אותה עם האפליקציה. אם הגדרתם את שירות ממסר האימייל הפרטי, אפל מעבירה אימיילים שנשלחים לכתובת האנונימית לכתובת האימייל האמיתית של המשתמש.Apple משתפת מידע על משתמשים, כמו השם לתצוגה, רק עם אפליקציות בפעם הראשונה שמשתמש נכנס לחשבון. בדרך כלל, Firebase שומר את שם התצוגה בפעם הראשונה שמשתמש נכנס לחשבון באמצעות Apple, ואפשר לקבל אותו באמצעות
firebase.auth().currentUser.displayName. עם זאת, אם השתמשתם בעבר ב-Apple כדי להחתים משתמש באפליקציה בלי להשתמש ב-Firebase, Apple לא תספק ל-Firebase את השם המוצג של המשתמש.
אימות מחדש וקישור חשבונות
אפשר להשתמש באותו דפוס עם reauthenticateWithPopup() ועם reauthenticateWithRedirect(), שבהם אפשר להשתמש כדי לאחזר פרטי כניסה חדשים לפעולות רגישות שדורשות כניסה עדכנית:
Web
import { getAuth, reauthenticateWithPopup, OAuthProvider } from "firebase/auth"; // Result from Redirect auth flow. const auth = getAuth(); const provider = new OAuthProvider('apple.com'); reauthenticateWithPopup(auth.currentUser, provider) .then((result) => { // User is re-authenticated with fresh tokens minted and can perform // sensitive operations like account deletion, or updating their email // address or password. // The signed-in user info. const user = result.user; // You can also get the Apple OAuth Access and ID Tokens. const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; const idToken = credential.idToken; // ... }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
Web
const provider = new firebase.auth.OAuthProvider('apple.com'); firebase .auth() .currentUser .reauthenticateWithPopup(provider) .then((result) => { // User is re-authenticated with fresh tokens minted and can perform // sensitive operations like account deletion, or updating their email // address or password. /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // The signed-in user info. var user = result.user; // You can also get the Apple OAuth Access and ID Tokens. var accessToken = credential.accessToken; var idToken = credential.idToken; // IdP data available in result.additionalUserInfo.profile. // ... }) .catch((error) => { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; // The email of the user's account used. var email = error.email; // The firebase.auth.AuthCredential type that was used. var credential = error.credential; // ... });
בנוסף, אפשר להשתמש ב-linkWithPopup() וב-linkWithRedirect() כדי לקשר ספקי זהויות שונים לחשבונות קיימים.
חשוב לזכור שחברת אפל דורשת לקבל הסכמה מפורשת מהמשתמשים לפני שמקשרים את החשבונות שלהם ב-Apple לנתונים אחרים.
לדוגמה, כדי לקשר חשבון פייסבוק לחשבון Firebase הנוכחי, משתמשים באסימון הגישה שמתקבל מהתחברות המשתמש לפייסבוק:
Web
import { getAuth, linkWithPopup, FacebookAuthProvider } from "firebase/auth"; const auth = getAuth(); const provider = new FacebookAuthProvider(); provider.addScope('user_birthday'); // Assuming the current user is an Apple user linking a Facebook provider. linkWithPopup(auth.currentUser, provider) .then((result) => { // Facebook credential is linked to the current Apple user. // ... // The user can now sign in to the same account // with either Apple or Facebook. }) .catch((error) => { // Handle error. });
Web
const provider = new firebase.auth.FacebookAuthProvider(); provider.addScope('user_birthday'); // Assuming the current user is an Apple user linking a Facebook provider. firebase.auth().currentUser.linkWithPopup(provider) .then((result) => { // Facebook credential is linked to the current Apple user. // Facebook additional data available in result.additionalUserInfo.profile, // Additional Facebook OAuth access token can also be retrieved. // result.credential.accessToken // The user can now sign in to the same account // with either Apple or Facebook. }) .catch((error) => { // Handle error. });
אימות באמצעות Firebase בתוסף ל-Chrome
אם אתם מפתחים אפליקציית תוסף ל-Chrome, כדאי לעיין במדריך למסמכים מחוץ למסך.
שימו לב שעדיין צריך לאמת את הדומיין המותאם אישית מול אפל, בדומה לדומיין firebaseapp.com שמוגדר כברירת מחדל:
http://auth.custom.example.com/.well-known/apple-developer-domain-association.txt
ביטול טוקן
Apple דורשת שאפליקציות שתומכות ביצירת חשבון יאפשרו למשתמשים להתחיל את תהליך מחיקת החשבון שלהם בתוך האפליקציה, כפי שמתואר בהנחיות לבדיקת אפליקציות ב-App Store.
כדי לעמוד בדרישה הזו, צריך לבצע את השלבים הבאים:
חשוב לוודא שמילאתם את הקטע Services ID ואת הקטע OAuth code flow configuration בהגדרות של ספק הכניסה באמצעות Apple, כמו שמתואר בקטע הגדרת כניסה באמצעות Apple.
מערכת Firebase לא שומרת טוקנים של משתמשים כשיוצרים משתמשים באמצעות 'כניסה באמצעות Apple', ולכן צריך לבקש מהמשתמש להיכנס שוב לפני שמבטלים את הטוקן שלו ומוחקים את החשבון.
לאחר מכן, מקבלים את טוקן הגישה של Apple OAuth מ-
OAuthCredentialומשתמשים בו כדי להתקשר אלrevokeAccessToken(auth, token)ולבטל את טוקן הגישה של Apple OAuth.const provider = new OAuthProvider('apple.com'); provider.addScope('email'); provider.addScope('name'); const auth = getAuth(); signInWithPopup(auth, provider).then(result => { // Get the Apple OAuth access token. const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; // Revoke the Apple OAuth access token. revokeAccessToken(auth, accessToken) .then(() => { // Token revoked. // Delete the user account. // ... }) .catch(error => { // An error happened. // ... }); });לבסוף, מוחקים את חשבון המשתמש (ואת כל הנתונים שמשויכים אליו).
למתקדמים: אימות באמצעות Firebase ב-Node.js
כדי לבצע אימות באמצעות Firebase באפליקציית Node.js:
מתחברים לחשבון Apple של המשתמש ומקבלים את טוקן Apple ID של המשתמש. אפשר לעשות את זה בכמה דרכים. לדוגמה, אם לאפליקציית Node.js שלכם יש ממשק קצה של דפדפן:
בשרת העורפי, יוצרים מחרוזת אקראית (nonce) ומחשבים את הגיבוב שלה באמצעות SHA256. ה-nonce הוא ערך לשימוש חד-פעמי שמשמש לאימות של הלוך ושוב יחיד בין ה-backend שלכם לבין שרתי האימות של Apple.
Web
const crypto = require("crypto"); const string_decoder = require("string_decoder"); // Generate a new random string for each sign-in const generateNonce = (length) => { const decoder = new string_decoder.StringDecoder("ascii"); const buf = Buffer.alloc(length); let nonce = ""; while (nonce.length < length) { crypto.randomFillSync(buf); nonce = decoder.write(buf); } return nonce.slice(0, length); }; const unhashedNonce = generateNonce(10); // SHA256-hashed nonce in hex const hashedNonceHex = crypto.createHash('sha256') .update(unhashedNonce).digest().toString('hex');
Web
const crypto = require("crypto"); const string_decoder = require("string_decoder"); // Generate a new random string for each sign-in const generateNonce = function(length) { const decoder = new string_decoder.StringDecoder("ascii"); const buf = Buffer.alloc(length); var nonce = ""; while (nonce.length < length) { crypto.randomFillSync(buf); nonce = decoder.write(buf); } return nonce.slice(0, length); }; const unhashedNonce = generateNonce(10); // SHA256-hashed nonce in hex const hashedNonceHex = crypto.createHash('sha256') .update(unhashedNonce).digest().toString('hex');
בדף הכניסה, מציינים את ה-nonce שעבר גיבוב בהגדרה של 'כניסה באמצעות Apple':
<script src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script> <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div> <script> AppleID.auth.init({ clientId: YOUR_APPLE_CLIENT_ID, scope: 'name email', redirectURI: URL_TO_YOUR_REDIRECT_HANDLER, // See the next step. state: '[STATE]', // Optional value that Apple will send back to you // so you can return users to the same context after // they sign in. nonce: HASHED_NONCE // The hashed nonce you generated in the previous step. }); </script>קבלת טוקן Apple ID מהתגובה לאימות שנשלחה ב-POST בצד השרת:
app.post('/redirect', (req, res) => { const savedState = req.cookies.__session; const code = req.body.code; const state = req.body.state; const appleIdToken = req.body.id_token; if (savedState !== state || !code) { res.status(403).send('403: Permission denied'); } else { // Sign in with Firebase using appleIdToken. (See next step). } });
אפשר לעיין גם במאמר הגדרת דף אינטרנט לכניסה באמצעות חשבון Apple.
אחרי שמקבלים את טוקן Apple ID של המשתמש, משתמשים בו כדי ליצור אובייקט Credential ואז מתחברים לחשבון של המשתמש באמצעות פרטי הכניסה:
Web
import { getAuth, signInWithCredential, OAuthProvider } from "firebase/auth"; const auth = getAuth(); // Build Firebase credential with the Apple ID token. const provider = new OAuthProvider('apple.com'); const authCredential = provider.credential({ idToken: appleIdToken, rawNonce: unhashedNonce, }); // Sign in with credential form the Apple user. signInWithCredential(auth, authCredential) .then((result) => { // User signed in. }) .catch((error) => { // An error occurred. If error.code == 'auth/missing-or-invalid-nonce', // make sure you're sending the SHA256-hashed nonce as a hex string // with your request to Apple. console.log(error); });
Web
// Build Firebase credential with the Apple ID token. const provider = new firebase.auth.OAuthProvider('apple.com'); const authCredential = provider.credential({ idToken: appleIdToken, rawNonce: unhashedNonce, }); // Sign in with credential form the Apple user. firebase.auth().signInWithCredential(authCredential) .then((result) => { // User signed in. }) .catch((error) => { // An error occurred. If error.code == 'auth/missing-or-invalid-nonce', // make sure you're sending the SHA256-hashed nonce as a hex string // with your request to Apple. console.log(error); });
השלבים הבאים
אחרי שמשתמש נכנס לחשבון בפעם הראשונה, נוצר חשבון משתמש חדש שמקושר לפרטי הכניסה – כלומר, שם המשתמש והסיסמה, מספר הטלפון או פרטי ספק האימות – שבאמצעותם המשתמש נכנס לחשבון. החשבון החדש הזה נשמר כחלק מפרויקט Firebase, ואפשר להשתמש בו כדי לזהות משתמש בכל האפליקציות בפרויקט, בלי קשר לשיטת הכניסה של המשתמש.
-
באפליקציות, הדרך המומלצת לדעת מה סטטוס האימות של המשתמש היא להגדיר אובייקט observer ב-
Auth. אחרי כן תוכלו לקבל את פרטי הפרופיל הבסיסיים של המשתמש מאובייקטUser. ניהול משתמשים ב-Firebase Realtime Database וב-Cloud Storage Security Rules, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה
auth, ולהשתמש בו כדי לקבוע לאילו נתונים משתמש יכול לגשת.
אתם יכולים לאפשר למשתמשים להיכנס לאפליקציה שלכם באמצעות כמה ספקי אימות על ידי קישור פרטי כניסה של ספק אימות לחשבון משתמש קיים.
כדי להוציא משתמש מהחשבון, מתקשרים אל
signOut:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });