يمكنك السماح للمستخدمين بالمصادقة مع Firebase باستخدام معرّف Apple من خلال استخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase لتنفيذ عملية تسجيل الدخول إلى OAuth 2.0 بشكل تام بين الأطراف.
قبل البدء
لتسجيل دخول المستخدمين باستخدام Apple، يجب أولاً ضبط ميزة "تسجيل الدخول باستخدام حساب Apple" على الموقع الإلكتروني للمطوّرين من Apple، ثم تفعيل Apple كمقدّم خدمة تسجيل الدخول لمشروعك على Firebase.
الانضمام إلى برنامج Apple Developer Program
لا يمكن إعداد ميزة "تسجيل الدخول باستخدام حساب Apple" إلا من قِبل المشتركين في برنامج مطوّري البرامج من Apple.
ضبط ميزة "تسجيل الدخول باستخدام حساب Apple"
على موقع Apple Developer الإلكتروني، اتّبِع الخطوات التالية:
-
اربط موقعك الإلكتروني بتطبيقك على النحو الموضّح في القسم الأول من ضبط ميزة "تسجيل الدخول باستخدام حساب Apple على الويب". سجِّل عنوان URL التالي كعنوان URL للعودة عندما يُطلب منك ذلك:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
يمكنك الحصول على رقم تعريف مشروع Firebase في صفحة إعدادات "وحدة تحكُّم Firebase".
عند الانتهاء، دوِّن رقم تعريف الخدمة الجديد الذي ستحتاجه في القسم التالي.
- أنشئ ميزة تسجيل الدخول باستخدام مفتاح خاص من Apple. ستحتاج إلى مفتاحك الخاص الجديد ومعرّف المفتاح في القسم التالي.
-
في حال استخدام أي من ميزات "مصادقة Firebase" التي ترسل رسائل إلكترونية إلى المستخدمين، بما في ذلك تسجيل الدخول باستخدام رابط البريد الإلكتروني، وإثبات ملكية عنوان البريد الإلكتروني، وإبطال تغيير الحساب، وغيرها، عليك ضبط خدمة إرسال البريد الإلكتروني الخاص في Apple وتسجيل
noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com
(أو نطاق نموذج البريد الإلكتروني المخصّص) حتى تتمكّن Apple من إرسال الرسائل الإلكترونية المُرسَلة من خلال مصادقة Firebase إلى عناوين البريد الإلكتروني المجهولة المصدر في 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) لمنصة Firebase لنظام التشغيل Android.
للتعامل مع عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android لمنصة Firebase، اتّبِع الخطوات التالية:
يمكنك إنشاء مثيل لـ
OAuthProvider
باستخدام أداة الإنشاء الخاصة به باستخدام معرّف الموفّرapple.com
:Kotlin+KTX
val provider = OAuthProvider.newBuilder("apple.com")
Java
OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
اختياري: حدِّد نطاقات OAuth 2.0 الإضافية بخلاف النطاقات التلقائية التي تريد طلبها من موفِّر المصادقة.
Kotlin+KTX
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+KTX
// 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+KTX
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+KTX
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+KTX
// 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+KTX
// 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+KTX
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 من nonce كسلسلة سداسية:
Kotlin+KTX
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 من nonce مع طلب تسجيل الدخول، والتي لن تجرِها Apple بدون تغيير في الاستجابة. يتحقّق Firebase من صحة الردّ من خلال تجزئة رقم التعريف الأصلي الأصلي ومقارنتها بالقيمة التي حدّدتها Apple.
يمكنك بدء عملية تسجيل الدخول إلى Apple باستخدام مكتبة OAuth أو طريقة أخرى. تأكد من تضمين nonce المجزأ كمعلمة في طلبك.
بعد تلقّي ردّ Apple، يمكنك الحصول على الرمز المميّز للمعرّف من الردّ واستخدامه مع الرقم الخاص غير المجزّأ لإنشاء
AuthCredential
:Kotlin+KTX
val credential = OAuthProvider.newCredentialBuilder("apple.com") .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce) .build()
Java
AuthCredential credential = OAuthProvider.newCredentialBuilder("apple.com") .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce) .build();
للمصادقة مع Firebase باستخدام بيانات اعتماد Firebase:
Kotlin+KTX
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" ميزة "تسجيل الدخول باستخدام حساب Apple REST API" لإبطال الرموز المميّزة للمستخدم.
لاستيفاء هذا الشرط، نفِّذ الخطوات التالية:
يُرجى استخدام طريقة
startActivityForSignInWithProvider()
لتسجيل الدخول باستخدام Apple والحصول علىAuthResult
.يمكنك الحصول على رمز الدخول لمزوّد خدمة Apple.
Kotlin+KTX
val oauthCredential: OAuthCredential = authResult.credential val accessToken = oauthCredential.accessToken
Java
OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential(); String accessToken = oauthCredential.getAccessToken();
يمكنك إبطال الرمز المميّز باستخدام واجهة برمجة تطبيقات
revokeAccessToken
.Kotlin+KTX
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 في الوقت الفعلي وقواعد الأمان في Cloud Storage، يمكنك الحصول على رقم تعريف المستخدم الفريد للمستخدم الذي سجّل الدخول من خلال المتغيّر
auth
، واستخدامه للتحكّم في البيانات التي يمكن للمستخدم الوصول إليها.
يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام مزوّدي مصادقة متعددين من خلال ربط بيانات اعتماد موفّر المصادقة بحساب مستخدم حالي.
لتسجيل خروج المستخدم، يمكنك الاتصال على
signOut
:Kotlin+KTX
Firebase.auth.signOut()
Java
FirebaseAuth.getInstance().signOut();
-