يمكنك السماح للمستخدمين بالمصادقة باستخدام Firebase من خلال معرّف Apple عن طريق استخدام حزمة Firebase SDK لتنفيذ عملية تسجيل الدخول الكاملة باستخدام بروتوكول OAuth 2.0.
قبل البدء
لتسجيل دخول المستخدمين باستخدام حساب على Apple، عليك أولاً ضبط ميزة "تسجيل الدخول باستخدام حساب على Apple" على موقع المطوّرين التابع لشركة Apple، ثم تفعيل Apple كمزوّد لتسجيل الدخول في مشروع Firebase.
الانضمام إلى برنامج Apple Developer
لا يمكن ضبط ميزة "تسجيل الدخول باستخدام حساب على Apple" إلا من قِبل أعضاء برنامج Apple Developer Program.
ضبط ميزة "تسجيل الدخول باستخدام حساب على Apple"
على موقع Apple Developer، اتّبِع الخطوات التالية:
-
اربط موقعك الإلكتروني بتطبيقك كما هو موضّح في القسم الأول من ضبط ميزة "تسجيل الدخول باستخدام حساب على 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، انتقِل إلى علامة التبويب
الإعدادات > عام. - انتقِل للأسفل إلى بطاقة تطبيقاتك، واختَر تطبيق Android، وأضِف بصمة SHA-1 في حقل الملفات المرجعية لشهادة SHA.
-
في وحدة تحكّم Firebase، انتقِل إلى علامة التبويب
- في وحدة تحكّم Firebase، انتقِل إلى الأمان > المصادقة.
- في علامة التبويب طريقة تسجيل الدخول ، فعِّل مزوّد تسجيل الدخول Apple. حدِّد "معرّف الخدمة" الذي أنشأته في القسم السابق. في قسم إعدادات عملية الحصول على رمز OAuth، حدِّد أيضًا "معرّف فريق Apple" و المفتاح الخاص ومعرّف المفتاح اللذين أنشأتهما في القسم السابق.
الامتثال لمتطلبات Apple بشأن البيانات المجهولة
تمنح ميزة "تسجيل الدخول باستخدام حساب على Apple" المستخدمين خيار إخفاء هويتهم، بما في ذلك عنوان بريدهم الإلكتروني، عند تسجيل الدخول. يملك المستخدمون الذين يختارون هذا الخيار عناوين بريد إلكتروني بالنطاق privaterelay.appleid.com. عند استخدام ميزة "تسجيل الدخول باستخدام حساب على Apple" في تطبيقك، عليك الامتثال لأي سياسات أو بنود سارية للمطوّرين من Apple بشأن معرّفات Apple المجهولة هذه.
ويشمل ذلك الحصول على أي موافقة مطلوبة من المستخدم قبل ربط أي معلومات شخصية تحدّد الهوية مباشرةً بمعرّف Apple مجهول. عند استخدام "مصادقة Firebase"، قد يشمل ذلك الإجراءات التالية:
- ربط عنوان بريد إلكتروني بمعرّف Apple مجهول أو العكس
- ربط رقم هاتف بمعرّف Apple مجهول أو العكس
- ربط بيانات اعتماد غير مجهولة على وسائل التواصل الاجتماعي (Facebook أو Google أو غيرهما) بمعرّف Apple مجهول أو العكس
القائمة أعلاه غير شاملة. يُرجى الرجوع إلى اتفاقية ترخيص برنامج Apple Developer في قسم العضوية ضمن حساب المطوّرين للتأكّد من أنّ تطبيقك يستوفي متطلبات Apple.
التعامل مع عملية تسجيل الدخول باستخدام حزمة Firebase SDK
على Android، أسهل طريقة لمصادقة المستخدمين باستخدام Firebase من خلال حساباتهم على Apple هي التعامل مع عملية تسجيل الدخول بالكامل باستخدام حزمة Firebase Android SDK.
للتعامل مع عملية تسجيل الدخول باستخدام حزمة Firebase Android SDK، اتّبِع الخطوات التالية:
أنشِئ مثيلاً من
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"، لا يقدّم 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 عن طريق التعامل مع عملية تسجيل الدخول إما باستخدام حزمة Apple Sign-In JS SDK أو إنشاء عملية 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.accessTokenJava
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();
-