میتوانید به کاربران اجازه دهید بااستفاده از Apple ID خودشان با Firebase اصالتسنجی کنند، برای این کار باید از «کیت توسعه نرمافزار Firebase» برای انجام جریان ورود به سیستم سرتاسر OAuth 2.0 استفاده کنید.
قبل از شروع
برای ورود به سیستم کاربران بااستفاده از Apple، ابتدا «ورود به سیستم با Apple» را در سایت توسعهدهنده Apple پیکربندی کنید، سپس Apple را بهعنوان ارائهدهنده ورود به سیستم برای پروژه Firebase خود فعال کنید.
به «برنامه توسعهدهندگان Apple» بپیوندید
«ورود به سیستم با Apple» فقط توسط اعضای برنامه توسعهدهندگان Apple قابل پیکربندی است.
پیکربندی «ورود به سیستم با Apple»
در سایت توسعهدهنده Apple، مراحل زیر را انجام دهید:
-
وبسایتتان را با برنامهتان مرتبط کنید، همانطور که در بخش اول پیکربندی «ورود به سیستم با Apple» برای وب توضیح داده شده است. وقتی پیامواره دریافت کردید، نشانی وب زیر را بهعنوان «نشانی وب برگشتی» ثبت کنید:
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 ID ناشناس پیوند دهید یا برعکس.
- پیوند دادن شماره تلفن به Apple ID ناشناس یا برعکس
- اعتبار اجتماعی غیرگمنام (Facebook، Google، و غیره) را به Apple ID گمنامشده پیوند دهید یا برعکس.
فهرست بالا کامل نیست. برای اطمینان از اینکه برنامهتان الزامات Apple را برآورده میکند، به «قرارداد پروانه برنامه توسعهدهندگان Apple» در بخش «عضویت» حساب توسعهدهندهتان مراجعه کنید.
مدیریت جریان ورود به سیستم با «کیت توسعه نرمافزار Firebase»
در Android، آسانترین راه برای اصالتسنجی کاربران با Firebase بااستفاده از حسابهای Apple آنها این است که کل جریان ورود به سیستم را با «کیت توسعه نرمافزار Firebase Android» مدیریت کنید.
برای مدیریت جریان ورود به سیستم با «کیت توسعه نرمافزار Firebase Android»، این مراحل را دنبال کنید:
بااستفاده از «سازنده» آن با شناسه ارائهدهنده
apple.com، نمونهای ازOAuthProviderبسازید: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");بااستفاده از شیء ارائهدهنده OAuth، با Firebase اصالتسنجی کنید. توجه داشته باشید که برخلاف دیگر عملیات
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 نشانی وب عکس ارائه نمیدهد.
همچنین، وقتی کاربر انتخاب میکند که ایمیلش را با برنامه همرسانی نکند، 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.
}
}
});
پیشرفته: مدیریت دستی جریان ورود به سیستم
همچنین میتوانید بااستفاده از «حساب Apple» با Firebase اصالتسنجی کنید. برای این کار، جریان ورود به سیستم را بااستفاده از «کیت توسعه نرمافزار JS ورود به سیستم با 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» برای باطل کردن نشانهای کاربر استفاده کنند.
برای برآورده کردن این الزام، مراحل زیر را پیادهسازی کنید:
برای ورود به سیستم بااستفاده از Apple و دریافت
AuthResult، از روشstartActivityForSignInWithProvider()استفاده کنید.کد دسترسی را برای ارائهدهنده Apple دریافت کنید.
Kotlin
val oauthCredential: OAuthCredential = authResult.credential val accessToken = oauthCredential.accessTokenJava
OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential(); String accessToken = oauthCredential.getAccessToken();کد را بااستفاده از
revokeAccessTokenAPI باطل کنید.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();
-