אתם יכולים לאפשר למשתמשים שלכם לבצע אימות באמצעות Firebase באמצעות Apple ID שלהם, על ידי שימוש ב-Firebase SDK כדי לבצע את תהליך הכניסה מקצה לקצה של OAuth 2.0.
לפני שמתחילים
כדי לאפשר למשתמשים להיכנס באמצעות Apple, קודם צריך להגדיר את הכניסה באמצעות Apple באתר למפתחים של Apple, ואז להפעיל את Apple כספק כניסה בפרויקט Firebase.
הצטרפות לתוכנית המפתחים של אפל
אפשר להגדיר כניסה באמצעות Apple רק על ידי חברים בתוכנית המפתחים של Apple.
הגדרת כניסה באמצעות Apple
באתר Apple Developer, מבצעים את הפעולות הבאות:
-
משייכים את האתר לאפליקציה כמו שמתואר בקטע הראשון של המאמר בנושא הגדרת כניסה באמצעות Apple לאתרים. כשמוצגת בקשה, רושמים את כתובת ה-URL הבאה ככתובת URL להחזרה:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
אפשר לראות את מזהה פרויקט Firebase בדף ההגדרות של מסוף Firebase.
בסיום, חשוב לשים לב למזהה השירות החדש, שתצטרכו לו בקטע הבא.
- יוצרים מפתח פרטי של 'כניסה באמצעות אפל'. בקטע הבא תצטרכו את המפתח הפרטי החדש ואת מזהה המפתח.
-
אם אתם משתמשים בתכונות של Firebase Authentication ששולחות אימיילים למשתמשים, כולל כניסה באמצעות קישור באימייל, אימות כתובת אימייל, ביטול שינוי בחשבון ועוד, אתם צריכים להגדיר את שירות העברת האימייל הפרטי של אפל ולרשום את
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com
(או את הדומיין של תבנית האימייל המותאמת אישית שלכם) כדי שאפל תוכל להעביר אימיילים שנשלחים על ידי Firebase Authentication לכתובות אימייל אנונימיות של אפל.
הפעלת Apple כספק כניסה
- מוסיפים את Firebase לפרויקט.
- במסוף Firebase, פותחים את הקטע אימות. בכרטיסייה שיטת הכניסה, מפעילים את הספק Apple. מציינים את מזהה השירות שיצרתם בקטע הקודם. בנוסף, בקטע OAuth code flow configuration (הגדרת תהליך קוד OAuth), מציינים את מזהה הצוות שלכם ב-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, כדאי לעיין במדריך בנושא מסמכים מחוץ למסך.
חשוב לזכור שעדיין צריך לאמת את הדומיין המותאם אישית מול Apple, בדומה לדומיין ברירת המחדל 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 שעבר גיבוב בהגדרה של 'כניסה באמצעות אפל':
<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 כללי האבטחה, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה
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. });