يمكنك السماح للمستخدمين بالمصادقة باستخدام Firebase من خلال حساباتهم على Apple عن طريق استخدام حزمة تطوير البرامج (SDK) من Firebase لتنفيذ عملية تسجيل الدخول الكاملة باستخدام بروتوكول OAuth 2.0.
قبل البدء
لتسجيل دخول المستخدمين باستخدام Apple، عليك أولاً إعداد ميزة "تسجيل الدخول باستخدام Apple" على موقع مطوّري Apple الإلكتروني، ثم تفعيل Apple كموفّر خدمة تسجيل الدخول لمشروعك على Firebase.
الانضمام إلى "برنامج المطوّرين من Apple"
لا يمكن إعداد ميزة "تسجيل الدخول باستخدام حساب على Apple" إلا من خلال أعضاء برنامج Apple Developer.
ضبط ميزة "تسجيل الدخول باستخدام حساب على Apple"
في موقع مطوّري Apple، اتّبِع الخطوات التالية:
-
اربط موقعك الإلكتروني بتطبيقك كما هو موضّح في القسم الأول من مقالة إعداد ميزة "تسجيل الدخول باستخدام Apple" على الويب. عندما يُطلب منك ذلك، سجِّل عنوان URL التالي كعنوان URL للرجوع:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
يمكنك الحصول على رقم تعريف مشروعك على Firebase من صفحة إعداداتFirebase وحدة التحكّم.
عند الانتهاء، سجِّل رقم تعريف الخدمة الجديد الذي ستحتاج إليه في القسم التالي.
- إنشاء مفتاح خاص لتطبيق "تسجيل الدخول باستخدام Apple" ستحتاج إلى المفتاح الخاص الجديد ورقم تعريف المفتاح في القسم التالي.
-
إذا كنت تستخدم أيًا من ميزات Firebase Authentication التي ترسل رسائل إلكترونية إلى المستخدمين، بما في ذلك تسجيل الدخول باستخدام رابط في البريد الإلكتروني، وإثبات ملكية عنوان البريد الإلكتروني، وإلغاء تغيير الحساب، وغيرها، عليك إعداد خدمة ترحيل البريد الإلكتروني الخاص من Apple وتسجيل
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com
(أو نطاق نموذج البريد الإلكتروني المخصّص) لكي تتمكّن Apple من ترحيل الرسائل الإلكترونية التي ترسلها Firebase Authentication إلى عناوين بريد إلكتروني مجهولة الهوية من Apple.
تفعيل Apple كموفّر لخدمة تسجيل الدخول
- أضِف Firebase إلى مشروع Android. احرص على تسجيل توقيع SHA-1 لتطبيقك عند إعداد تطبيقك في وحدة تحكّم Firebase.
- في وحدة تحكّم Firebase، افتح قسم المصادقة. في علامة التبويب طريقة تسجيل الدخول، فعِّل موفّر Apple. حدِّد معرّف الخدمة الذي أنشأته في القسم السابق. في قسم إعدادات عملية الحصول على رمز OAuth، حدِّد أيضًا معرّف فريق Apple والمفتاح الخاص ومعرّف المفتاح اللذين أنشأتهما في القسم السابق.
الالتزام بمتطلبات Apple بشأن البيانات المخفية الهوية
يمنح خيار "تسجيل الدخول باستخدام Apple" المستخدمين إمكانية إخفاء هوية بياناتهم، بما في ذلك عنوان بريدهم الإلكتروني، عند تسجيل الدخول. يحصل المستخدمون الذين يختارون هذا الخيار على عناوين بريد إلكتروني تتضمّن النطاق privaterelay.appleid.com
. عند استخدام ميزة "تسجيل الدخول باستخدام Apple" في تطبيقك، عليك الالتزام بأي سياسات أو بنود مطوّرين سارية من Apple بشأن معرّفات Apple المجهولة الهوية هذه.
ويشمل ذلك الحصول على موافقة المستخدمين المطلوبة قبل ربط أي معلومات شخصية تحدد الهوية مباشرةً بمعرّف Apple مجهول الهوية. عند استخدام "مصادقة Firebase"، قد يشمل ذلك الإجراءات التالية:
- ربط عنوان بريد إلكتروني بمعرّف Apple مخفيّ الهوية أو العكس
- ربط رقم هاتف بمعرّف Apple مخفي الهوية أو العكس
- ربط بيانات اعتماد اجتماعية غير مجهولة الهوية (Facebook أو Google أو غير ذلك) بمعرّف Apple مجهول الهوية أو العكس
يُرجى العِلم أنّ القائمة أعلاه ليست شاملة. يُرجى الرجوع إلى اتفاقية ترخيص برنامج Apple للمطوّرين في قسم "الاشتراك" ضمن حساب المطوّر للتأكّد من أنّ تطبيقك يستوفي متطلبات Apple.
التعامل مع عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) من Firebase
على أجهزة Android، أسهل طريقة لمصادقة المستخدمين باستخدام Firebase من خلال حساباتهم على Apple هي التعامل مع عملية تسجيل الدخول بأكملها باستخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android من Firebase.
لإدارة عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android من Firebase، اتّبِع الخطوات التالية:
أنشئ مثيلاً من
OAuthProvider
باستخدام أداة الإنشاء الخاصة به مع معرّف الموفّرapple.com
:Kotlin
val provider = OAuthProvider.newBuilder("apple.com")
Java
OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
اختياري: حدِّد نطاقات إضافية لبروتوكول OAuth 2.0 تتجاوز النطاقات التلقائية التي تريد طلبها من موفّر المصادقة.
Kotlin
provider.setScopes(arrayOf("email", "name"))
Java
List<String> scopes = new ArrayList<String>() { { add("email"); add("name"); } }; provider.setScopes(scopes);
عند تفعيل خيار حساب واحد لكل عنوان بريد إلكتروني تلقائيًا، يطلب Firebase نطاقات البريد الإلكتروني والاسم. في حال تغيير هذا الإعداد إلى حسابات متعدّدة لكل عنوان بريد إلكتروني، لن تطلب Firebase أي نطاقات من Apple إلا إذا حدّدتها.
اختياري: إذا كنت تريد عرض شاشة تسجيل الدخول من Apple بلغة أخرى غير الإنجليزية، اضبط المَعلمة
locale
. راجِع مستندات "تسجيل الدخول باستخدام Apple" لمعرفة اللغات المتوافقة.Kotlin
// Localize the Apple authentication screen in French. provider.addCustomParameter("locale", "fr")
Java
// Localize the Apple authentication screen in French. provider.addCustomParameter("locale", "fr");
يمكنك المصادقة باستخدام Firebase من خلال عنصر موفّر OAuth. يُرجى العِلم أنّه على عكس عمليات
FirebaseAuth
الأخرى، ستتحكّم هذه العملية في واجهة المستخدم من خلال فتح علامة تبويب مخصّصة في Chrome. وبالتالي، لا تشِر إلى النشاط فيOnSuccessListener
وOnFailureListener
اللذين ترفقهما لأنّهما سيتم فصلهما فورًا عند بدء العملية لواجهة المستخدم.عليك أولاً التحقّق مما إذا كنت قد تلقّيت ردًا. يؤدي تسجيل الدخول بهذه الطريقة إلى وضع "النشاط" في الخلفية، ما يعني أنّه يمكن للنظام استرداده أثناء عملية تسجيل الدخول. للتأكّد من أنّك لن تطلب من المستخدم إعادة المحاولة في حال حدوث ذلك، عليك التحقّق مما إذا كانت النتيجة معروضة حاليًا.
للتحقّق مما إذا كانت هناك نتيجة معلّقة، اتّصِل بالرقم
getPendingAuthResult()
:Kotlin
val pending = auth.pendingAuthResult if (pending != null) { pending.addOnSuccessListener { authResult -> Log.d(TAG, "checkPending:onSuccess:$authResult") // Get the user profile with authResult.getUser() and // authResult.getAdditionalUserInfo(), and the ID // token from Apple with authResult.getCredential(). }.addOnFailureListener { e -> Log.w(TAG, "checkPending:onFailure", e) } } else { Log.d(TAG, "pending: null") }
Java
mAuth = FirebaseAuth.getInstance(); Task<AuthResult> pending = mAuth.getPendingAuthResult(); if (pending != null) { pending.addOnSuccessListener(new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { Log.d(TAG, "checkPending:onSuccess:" + authResult); // Get the user profile with authResult.getUser() and // authResult.getAdditionalUserInfo(), and the ID // token from Apple with authResult.getCredential(). } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.w(TAG, "checkPending:onFailure", e); } }); } else { Log.d(TAG, "pending: null"); }
إذا لم تكن هناك نتيجة معلّقة، ابدأ عملية تسجيل الدخول من خلال استدعاء
startActivityForSignInWithProvider()
:Kotlin
auth.startActivityForSignInWithProvider(this, provider.build()) .addOnSuccessListener { authResult -> // Sign-in successful! Log.d(TAG, "activitySignIn:onSuccess:${authResult.user}") val user = authResult.user // ... } .addOnFailureListener { e -> Log.w(TAG, "activitySignIn:onFailure", e) }
Java
mAuth.startActivityForSignInWithProvider(this, provider.build()) .addOnSuccessListener( new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { // Sign-in successful! Log.d(TAG, "activitySignIn:onSuccess:" + authResult.getUser()); FirebaseUser user = authResult.getUser(); // ... } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.w(TAG, "activitySignIn:onFailure", e); } });
على عكس موفّري الخدمات الآخرين الذين تتوافق معهم خدمة Firebase Auth، لا توفّر Apple عنوان URL للصورة.
عندما يختار المستخدم عدم مشاركة عنوان بريده الإلكتروني مع التطبيق، توفّر Apple عنوان بريد إلكتروني فريدًا لهذا المستخدم (بالتنسيق
xyz@privaterelay.appleid.com
)، وتشاركه مع تطبيقك. وإذا كنت قد أعددت خدمة الترحيل عبر البريد الإلكتروني الخاص، تعيد Apple توجيه الرسائل الإلكترونية المرسَلة إلى العنوان المجهول إلى عنوان البريد الإلكتروني الحقيقي للمستخدم.تشارك Apple معلومات المستخدمين، مثل الاسم المعروض، مع التطبيقات فقط عند تسجيل المستخدم الدخول لأول مرة. يخزّن Firebase عادةً الاسم المعروض عند تسجيل دخول المستخدم لأول مرة باستخدام Apple، ويمكنك الحصول عليه باستخدام
getCurrentUser().getDisplayName()
. ومع ذلك، إذا سبق لك استخدام Apple لتسجيل دخول المستخدم إلى التطبيق بدون استخدام Firebase، لن يوفّر Apple لـ Firebase اسم العرض الخاص بالمستخدم.
إعادة المصادقة وربط الحساب
يمكن استخدام النمط نفسه مع startActivityForReauthenticateWithProvider()
الذي يمكنك استخدامه لاسترداد بيانات اعتماد جديدة للعمليات الحسّاسة التي
تتطلّب تسجيل دخول حديث:
Kotlin
// The user is already signed-in.
val firebaseUser = auth.getCurrentUser()
firebaseUser
.startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
.addOnSuccessListener( authResult -> {
// User is re-authenticated with fresh tokens and
// should be able to perform sensitive operations
// like account deletion and email or password
// update.
})
.addOnFailureListener( e -> {
// Handle failure.
})
Java
// The user is already signed-in.
FirebaseUser firebaseUser = mAuth.getCurrentUser();
firebaseUser
.startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
.addOnSuccessListener(
new OnSuccessListener<AuthResult>() {
@Override
public void onSuccess(AuthResult authResult) {
// User is re-authenticated with fresh tokens and
// should be able to perform sensitive operations
// like account deletion and email or password
// update.
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Handle failure.
}
});
ويمكنك استخدام linkWithCredential()
لربط مقدّمي خدمات هوية مختلفين بالحسابات الحالية.
يُرجى العِلم أنّ Apple تفرض عليك الحصول على موافقة صريحة من المستخدمين قبل ربط حساباتهم على Apple ببيانات أخرى.
على سبيل المثال، لربط حساب على Facebook بحساب Firebase الحالي، استخدِم رمز الدخول الذي حصلت عليه من خلال تسجيل دخول المستخدم إلى Facebook:
Kotlin
// Initialize a Facebook credential with a Facebook access token.
val credential = FacebookAuthProvider.getCredential(token.getToken())
// Assuming the current user is an Apple user linking a Facebook provider.
mAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
// Facebook credential is linked to the current Apple user.
// The user can now sign in to the same account
// with either Apple or Facebook.
}
});
Java
// Initialize a Facebook credential with a Facebook access token.
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
// Assuming the current user is an Apple user linking a Facebook provider.
mAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Facebook credential is linked to the current Apple user.
// The user can now sign in to the same account
// with either Apple or Facebook.
}
}
});
إجراء متقدّم: التعامل مع عملية تسجيل الدخول يدويًا
يمكنك أيضًا المصادقة باستخدام Firebase من خلال حساب Apple عن طريق التعامل مع مسار تسجيل الدخول إما باستخدام حزمة تطوير البرامج (SDK) بلغة JavaScript الخاصة بميزة "تسجيل الدخول باستخدام حساب Apple"، أو إنشاء مسار OAuth يدويًا، أو باستخدام مكتبة OAuth، مثل AppAuth.
لكل طلب تسجيل دخول، أنشئ سلسلة عشوائية، وهي "رقم استخدام لمرة واحدة"، ستستخدمه للتأكّد من أنّ رمز التعريف الذي تحصل عليه قد تم منحه تحديدًا استجابةً لطلب المصادقة الذي أرسله تطبيقك. هذه الخطوة مهمة لمنع هجمات إعادة الإرسال.
يمكنك إنشاء قيمة عشوائية آمنة تشفيرًا على Android باستخدام
SecureRandom
، كما في المثال التالي:Kotlin
private fun generateNonce(length: Int): String { val generator = SecureRandom() val charsetDecoder = StandardCharsets.US_ASCII.newDecoder() charsetDecoder.onUnmappableCharacter(CodingErrorAction.IGNORE) charsetDecoder.onMalformedInput(CodingErrorAction.IGNORE) val bytes = ByteArray(length) val inBuffer = ByteBuffer.wrap(bytes) val outBuffer = CharBuffer.allocate(length) while (outBuffer.hasRemaining()) { generator.nextBytes(bytes) inBuffer.rewind() charsetDecoder.reset() charsetDecoder.decode(inBuffer, outBuffer, false) } outBuffer.flip() return outBuffer.toString() }
Java
private String generateNonce(int length) { SecureRandom generator = new SecureRandom(); CharsetDecoder charsetDecoder = StandardCharsets.US_ASCII.newDecoder(); charsetDecoder.onUnmappableCharacter(CodingErrorAction.IGNORE); charsetDecoder.onMalformedInput(CodingErrorAction.IGNORE); byte[] bytes = new byte[length]; ByteBuffer inBuffer = ByteBuffer.wrap(bytes); CharBuffer outBuffer = CharBuffer.allocate(length); while (outBuffer.hasRemaining()) { generator.nextBytes(bytes); inBuffer.rewind(); charsetDecoder.reset(); charsetDecoder.decode(inBuffer, outBuffer, false); } outBuffer.flip(); return outBuffer.toString(); }
بعد ذلك، احصل على تجزئة SHA246 للرقم العشوائي كقيمة سداسية عشرية:
Kotlin
private fun sha256(s: String): String { val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(s.toByteArray()) val hash = StringBuilder() for (c in digest) { hash.append(String.format("%02x", c)) } return hash.toString() }
Java
private String sha256(String s) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(s.getBytes()); StringBuilder hash = new StringBuilder(); for (byte c: digest) { hash.append(String.format("%02x", c)); } return hash.toString(); }
سترسل تجزئة SHA256 للرقم العشوائي مع طلب تسجيل الدخول، وستمرّره Apple بدون تغيير في الرد. تتحقّق Firebase من صحة الرد من خلال تجزئة الرقم العشوائي الأصلي ومقارنته بالقيمة التي أرسلتها Apple.
ابدأ عملية تسجيل الدخول في Apple باستخدام مكتبة OAuth أو طريقة أخرى. احرص على تضمين الرقم العشوائي المجزّأ كمَعلمة في طلبك.
بعد تلقّي ردّ Apple، احصل على رمز التعريف من الردّ واستخدِمه مع الرقم العشوائي غير المجزأ لإنشاء
AuthCredential
:Kotlin
val credential = OAuthProvider.newCredentialBuilder("apple.com") .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce) .build()
Java
AuthCredential credential = OAuthProvider.newCredentialBuilder("apple.com") .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce) .build();
يمكنك المصادقة باستخدام Firebase من خلال بيانات اعتماد Firebase باتّباع الخطوات التالية:
Kotlin
auth.signInWithCredential(credential) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // User successfully signed in with Apple ID token. // ... } }
Java
mAuth.signInWithCredential(credential) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { // User successfully signed in with Apple ID token. // ... } } });
في حال نجاح طلب signInWithCredential
، يمكنك استخدام طريقة getCurrentUser
للحصول على بيانات حساب المستخدم.
إبطال الرمز المميز
تشترط Apple أن تتيح التطبيقات التي تتيح إنشاء الحسابات للمستخدمين بدء عملية حذف حساباتهم من داخل التطبيق، كما هو موضّح في إرشادات مراجعة App Store.
بالإضافة إلى ذلك، يجب أن تستخدم التطبيقات التي تتيح ميزة "تسجيل الدخول باستخدام Apple" واجهة برمجة التطبيقات REST الخاصة بميزة "تسجيل الدخول باستخدام Apple" لإبطال رموز المستخدمين المميزة.
لاستيفاء هذا الشرط، اتّبِع الخطوات التالية:
استخدِم طريقة
startActivityForSignInWithProvider()
لتسجيل الدخول باستخدام Apple والحصول علىAuthResult
.احصل على رمز الدخول لموفّر Apple.
Kotlin
val oauthCredential: OAuthCredential = authResult.credential val accessToken = oauthCredential.accessToken
Java
OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential(); String accessToken = oauthCredential.getAccessToken();
إبطال الرمز المميّز باستخدام واجهة برمجة التطبيقات
revokeAccessToken
Kotlin
mAuth.revokeAccessToken(accessToken) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // Access token successfully revoked // for the user ... } }
Java
mAuth.revokeAccessToken(accessToken) .addOnCompleteListener(this, new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { // Access token successfully revoked // for the user ... } } });
- أخيرًا، احذف حساب المستخدم (وجميع البيانات المرتبطة به).
الخطوات التالية
بعد أن يسجّل المستخدم الدخول لأول مرة، يتم إنشاء حساب مستخدم جديد وربطه ببيانات الاعتماد التي سجّل الدخول بها، أي اسم المستخدم وكلمة المرور أو رقم الهاتف أو معلومات مقدّم خدمة المصادقة. يتم تخزين هذا الحساب الجديد كجزء من مشروعك على Firebase، ويمكن استخدامه لتحديد هوية المستخدم على مستوى كل تطبيق في مشروعك، بغض النظر عن طريقة تسجيل الدخول.
-
في تطبيقاتك، يمكنك الحصول على معلومات الملف الشخصي الأساسية للمستخدم من عنصر
FirebaseUser
. راجِع إدارة المستخدمين. في Firebase Realtime Database وCloud Storage قواعد الأمان، يمكنك الحصول على معرّف المستخدِم الفريد للمستخدِم الذي سجّل الدخول من المتغيّر
auth
، واستخدامه للتحكّم في البيانات التي يمكن للمستخدِم الوصول إليها.
يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام موفّري مصادقة متعدّدين من خلال ربط بيانات اعتماد موفّر المصادقة بحساب مستخدم حالي.
لتسجيل خروج مستخدم، اتّبِع الخطوات التالية:
signOut
Kotlin
Firebase.auth.signOut()
Java
FirebaseAuth.getInstance().signOut();
-