אתם יכולים לאפשר למשתמשים שלכם לבצע אימות באמצעות Firebase באמצעות Apple ID שלהם, על ידי שימוש ב-Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה של OAuth 2.0.
לפני שמתחילים
כדי לאפשר למשתמשים להיכנס באמצעות Apple, קודם צריך להגדיר את הכניסה באמצעות Apple באתר למפתחים של Apple, ואז להפעיל את Apple כספק כניסה לפרויקט Firebase.
הצטרפות לתוכנית המפתחים של Apple
רק חברים בתוכנית המפתחים של אפל יכולים להגדיר את הכניסה באמצעות אפל.
הגדרת "כניסה באמצעות Apple"
באתר Apple Developer, מבצעים את הפעולות הבאות:
-
משייכים את האתר לאפליקציה, כמו שמתואר בקטע הראשון של המאמר Configure Sign In with Apple for the web (הגדרת כניסה באמצעות חשבון Apple לאתרים). כשמופיעה בקשה, רושמים את כתובת ה-URL הבאה ככתובת URL להחזרה:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
מזהה הפרויקט ב-Firebase מופיע בכרטיסייה General (כללי) בקטע
Settings (הגדרות) במסוף Firebase.בסיום, שימו לב למזהה השירות החדש, שתצטרכו להשתמש בו בקטע הבא.
- יוצרים מפתח פרטי של Sign In with Apple. תצטרכו את המפתח הפרטי החדש ואת מזהה המפתח בקטע הבא.
-
אם אתם משתמשים בתכונות של Firebase Authentication ששולחות אימיילים למשתמשים, כולל כניסה באמצעות קישור באימייל, אימות כתובת אימייל, ביטול שינויים בחשבון ותכונות אחרות, הגדירו את שירות ממסר האימייל הפרטי של אפל ורשמו את
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(או את הדומיין של תבנית האימייל המותאמת אישית שלכם) כדי שאפל תוכל להעביר אימיילים שנשלחו על ידי Firebase Authentication לכתובות אימייל אנונימיות של אפל.
הפעלת Apple כספק כניסה
- מוסיפים את Firebase לפרויקט.
- במסוף Firebase, נכנסים אל אבטחה > אימות.
- בכרטיסייה Sign-in method, מפעילים את ספק הכניסה של Apple. מציינים את מזהה השירות שיצרתם בקטע הקודם. בנוסף, בקטע OAuth code flow configuration, מציינים את מזהה הצוות של אפל, את המפתח הפרטי ואת מזהה המפתח שיצרתם בקטע הקודם.
עמידה בדרישות של אפל לגבי נתונים שעברו אנונימיזציה
התכונה "כניסה באמצעות חשבון אפל" מאפשרת למשתמשים להפוך את הנתונים שלהם לאנונימיים, כולל כתובת האימייל, כשהם נכנסים לחשבון. למשתמשים שבוחרים באפשרות הזו יש כתובות אימייל עם הדומיין privaterelay.appleid.com. כשמשתמשים בתכונה 'כניסה באמצעות Apple' באפליקציה, צריך לפעול בהתאם לכללי המדיניות או לתנאים הרלוונטיים למפתחים של Apple בנוגע למזהי Apple האנונימיים האלה.
הדבר כולל קבלת הסכמה מהמשתמש לפני שמשייכים פרטים אישיים מזהים ישירות למזהה Apple אנונימי. כשמשתמשים באימות ב-Firebase, הפעולות האלה עשויות לכלול את הפעולות הבאות:
- קישור של כתובת אימייל ל-Apple ID אנונימי או להיפך.
- קישור של מספר טלפון ל-Apple ID אנונימי או להיפך
- לקשר פרטי כניסה לא אנונימיים לרשתות חברתיות (פייסבוק, Google וכו') ל-Apple ID אנונימי, או להיפך.
הרשימה שלמעלה היא חלקית. כדי לוודא שהאפליקציה עומדת בדרישות של אפל, צריך לעיין בהסכם הרישיון של 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 לא מבקשת היקפי הרשאות מאפל אלא אם מציינים אותם.
אופציונלי: אם רוצים להציג את מסך הכניסה של אפל בשפה שאינה אנגלית, מגדירים את הפרמטר
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, אפל לא מספקת כתובת 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() כדי לקשר ספקי זהויות שונים לחשבונות קיימים.
חשוב לזכור: אפל דורשת לקבל הסכמה מפורשת מהמשתמשים לפני שמקשרים את חשבונות אפל שלהם לנתונים אחרים.
לדוגמה, כדי לקשר חשבון פייסבוק לחשבון 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
ביטול הטוקן
לפי הדרישות של אפל, אפליקציות שתומכות ביצירת חשבון חייבות לאפשר למשתמשים להתחיל את תהליך המחיקה של החשבון שלהם בתוך האפליקציה, כפי שמתואר בהנחיות לבדיקת אפליקציות ב-App Store.
כדי לעמוד בדרישה הזו, צריך לבצע את השלבים הבאים:
חשוב לוודא שמילאתם את הקטע Services ID וOAuth code flow configuration בהגדרות של ספק הכניסה באמצעות אפל, כמו שמתואר בקטע הגדרת כניסה באמצעות אפל.
מערכת 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 יש חזית של דפדפן:
ב-backend, יוצרים מחרוזת אקראית (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, ואפשר להשתמש בו כדי לזהות משתמש בכל אפליקציה בפרויקט, בלי קשר לשיטת הכניסה של המשתמש.
-
הדרך המומלצת לדעת מה סטטוס האימות של המשתמש באפליקציות היא להגדיר אובייקט
Authשל צופה. לאחר מכן תוכלו לקבל את פרטי הפרופיל הבסיסיים של המשתמש מהאובייקטUser. ניהול משתמשים בכללי האבטחה של Firebase Realtime Database ו-Cloud Storage, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה
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. });