يمكنك السماح للمستخدمين بالمصادقة باستخدام Firebase من خلال معرّف Apple الخاص بهم عن طريق استخدام حزمة تطوير البرامج (SDK) من Firebase لتنفيذ عملية تسجيل الدخول الكاملة باستخدام بروتوكول OAuth 2.0.
قبل البدء
لتسجيل دخول المستخدمين باستخدام Apple، عليك أولاً إعداد ميزة "تسجيل الدخول باستخدام Apple" على موقع مطوّري Apple الإلكتروني، ثم تفعيل Apple كموفّر خدمة تسجيل الدخول لمشروعك على Firebase.
الانضمام إلى برنامج Apple Developer
لا يمكن إعداد ميزة "تسجيل الدخول باستخدام حساب على Apple" إلا من خلال أعضاء برنامج Apple Developer.
ضبط ميزة "تسجيل الدخول باستخدام حساب على Apple"
في موقع Apple Developer الإلكتروني، اتّبِع الخطوات التالية:
-
اربط موقعك الإلكتروني بتطبيقك كما هو موضّح في القسم الأول من مقالة إعداد ميزة "تسجيل الدخول باستخدام Apple" على الويب. عندما يُطلب منك ذلك، سجِّل عنوان URL التالي كعنوان URL للردّ:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
يمكنك العثور على معرّف مشروعك على Firebase في علامة التبويب
الإعدادات > عام في وحدة تحكّم Firebase.عند الانتهاء، سجِّل رقم تعريف الخدمة الجديد الذي ستحتاج إليه في القسم التالي.
- أنشئ مفتاحًا خاصًا لتطبيق Sign In with Apple. ستحتاج إلى المفتاح الخاص الجديد ومعرّف المفتاح في القسم التالي.
-
إذا كنت تستخدم أيًا من ميزات Firebase Authentication التي ترسل رسائل إلكترونية إلى المستخدمين، بما في ذلك تسجيل الدخول باستخدام رابط البريد الإلكتروني، وإثبات ملكية عنوان البريد الإلكتروني، وإلغاء تغيير الحساب، وغير ذلك، عليك ضبط خدمة ترحيل البريد الإلكتروني الخاص من Apple وتسجيل
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(أو نطاق نموذج البريد الإلكتروني المخصّص) لكي تتمكّن Apple من ترحيل الرسائل الإلكترونية التي ترسلها Firebase Authentication إلى عناوين بريد إلكتروني مجهولة الهوية من Apple.
تفعيل Apple كموفّر خدمة تسجيل الدخول
- أضِف Firebase إلى مشروعك.
- في وحدة تحكّم Firebase، انتقِل إلى الأمان > المصادقة.
- في علامة التبويب طريقة تسجيل الدخول، فعِّل موفّر تسجيل الدخول Apple. حدِّد معرّف الخدمة الذي أنشأته في القسم السابق. في قسم إعدادات مسار رمز OAuth، حدِّد أيضًا معرّف فريق Apple والمفتاح الخاص ومعرّف المفتاح اللذين أنشأتهما في القسم السابق.
الالتزام بمتطلبات Apple بشأن البيانات المخفية الهوية
يمنح خيار "تسجيل الدخول باستخدام Apple" المستخدمين إمكانية إخفاء هوية بياناتهم، بما في ذلك عنوان بريدهم الإلكتروني، عند تسجيل الدخول. يحصل المستخدمون الذين يختارون هذا الخيار على عناوين بريد إلكتروني تتضمّن النطاق privaterelay.appleid.com. عند استخدام ميزة "تسجيل الدخول باستخدام Apple" في تطبيقك، عليك الالتزام بأي سياسات أو بنود مطوّرين سارية من Apple بشأن معرّفات Apple المجهولة الهوية هذه.
ويشمل ذلك الحصول على موافقة المستخدمين المطلوبة قبل ربط أي معلومات شخصية تحدِّد الهوية مباشرةً بمعرّف Apple مجهول الهوية. عند استخدام "مصادقة Firebase"، قد يشمل ذلك الإجراءات التالية:
- ربط عنوان بريد إلكتروني بمعرّف Apple مخفي الهوية أو العكس
- ربط رقم هاتف بمعرّف Apple مجهول الهوية أو العكس
- ربط بيانات اعتماد اجتماعية غير مجهولة الهوية (Facebook أو Google أو غير ذلك) بمعرّف Apple مجهول الهوية أو العكس
يُرجى العِلم أنّ القائمة أعلاه ليست شاملة. يُرجى الرجوع إلى اتفاقية الترخيص الخاصة ببرنامج Apple للمطوّرين في قسم "الاشتراك" ضمن حساب المطوّر للتأكّد من أنّ تطبيقك يستوفي متطلبات Apple.
التعامل مع عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) من Firebase
إذا كنت بصدد إنشاء تطبيق ويب، فإنّ أسهل طريقة لمصادقة المستخدمين باستخدام Firebase من خلال حساباتهم على Apple هي التعامل مع عملية تسجيل الدخول بأكملها باستخدام حزمة تطوير البرامج (SDK) من Firebase JavaScript.
للتعامل مع عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) من Firebase JavaScript، اتّبِع الخطوات التالية:
أنشئ مثيلاً من 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 إلا إذا حدّدتها.
اختياري: إذا كنت تريد عرض شاشة تسجيل الدخول من 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; // ... });
يمكنك أيضًا رصد الأخطاء ومعالجتها من خلالها. للاطّلاع على قائمة برموز الأخطاء، يُرجى الرجوع إلى مرجع واجهة برمجة التطبيقات.
على عكس موفّري الخدمات الآخرين الذين تتوافق معهم خدمة Firebase Auth، لا توفّر Apple عنوان URL للصورة.
عندما يختار المستخدم عدم مشاركة عنوان بريده الإلكتروني مع التطبيق، توفّر Apple عنوان بريد إلكتروني فريدًا لهذا المستخدم (بالتنسيق
xyz@privaterelay.appleid.com)، وتشاركه مع تطبيقك. وإذا كنت قد أعددت خدمة الترحيل عبر البريد الإلكتروني الخاص، تعيد Apple توجيه الرسائل الإلكترونية المُرسَلة إلى العنوان المجهول إلى عنوان البريد الإلكتروني الحقيقي للمستخدم.لا تشارك 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 تفرض عليك الحصول على موافقة صريحة من المستخدمين قبل ربط حساباتهم على Apple ببيانات أخرى.
على سبيل المثال، لربط حساب على Facebook بحساب Firebase الحالي، استخدِم رمز الدخول الذي حصلت عليه من تسجيل دخول المستخدم إلى Facebook:
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.
لاستيفاء هذا الشرط، اتّبِع الخطوات التالية:
تأكَّد من ملء قسمَي معرّف الخدمات وإعدادات مسار رمز OAuth في إعدادات مقدّم خدمة "تسجيل الدخول باستخدام 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 الخاص بالمستخدم. يمكنك إجراء ذلك بعدة طرق، مثلاً إذا كان تطبيق Node.js يحتوي على واجهة أمامية للمتصفّح:
في الخلفية، أنشئ سلسلة عشوائية (قيمة "nonce") واحتسِب تجزئة SHA256 الخاصة بها. قيمة nonce هي قيمة تُستخدَم لمرة واحدة للتحقّق من صحة عملية تبادل واحدة بين الخلفية وخوادم المصادقة التابعة لشركة 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 من استجابة المصادقة التي تم إرسالها باستخدام 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 الخاص بالمستخدم، استخدِمه لإنشاء عنصر 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. });