คุณสามารถให้ผู้ใช้ตรวจสอบสิทธิ์กับ Firebase โดยใช้ Apple ID โดยใช้ Firebase SDK เพื่อดำเนินการขั้นตอนการลงชื่อเข้าใช้ OAuth 2.0 จากต้นทางถึงปลายทาง
ก่อนที่คุณจะเริ่มต้น
ในการลงชื่อเข้าใช้ผู้ใช้โดยใช้ Apple ก่อนอื่นให้กำหนดค่าลงชื่อเข้าใช้ด้วย Apple บนเว็บไซต์นักพัฒนาซอฟต์แวร์ของ Apple จากนั้นเปิดใช้งาน Apple เป็นผู้ให้บริการลงชื่อเข้าใช้สำหรับโปรเจ็กต์ Firebase ของคุณ
เข้าร่วมโปรแกรมนักพัฒนาของ Apple
การลงชื่อเข้าใช้ด้วย Apple สามารถกำหนดค่าได้โดยสมาชิกของ Apple Developer Program เท่านั้น
กำหนดค่าการลงชื่อเข้าใช้ด้วย Apple
บนเว็บไซต์ Apple Developer ให้ทำดังต่อไปนี้:
เชื่อมโยงเว็บไซต์ของคุณกับแอพของคุณตามที่อธิบายไว้ในส่วนแรกของ กำหนดค่าการลงชื่อเข้าใช้ด้วย Apple สำหรับเว็บ เมื่อได้รับแจ้ง ให้ลงทะเบียน URL ต่อไปนี้เป็น URL ที่ส่งคืน:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
คุณสามารถรับรหัสโปรเจ็กต์ Firebase ได้ใน หน้าการตั้งค่าคอนโซล Firebase
เมื่อดำเนินการเสร็จแล้ว ให้จดบันทึก Service ID ใหม่ของคุณ ซึ่งคุณจะต้องใช้ในส่วนถัดไป
- สร้างการลงชื่อเข้าใช้ด้วยคีย์ส่วนตัวของ 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 Team ID ของคุณและคีย์ส่วนตัวและรหัสคีย์ที่คุณสร้างในส่วนก่อนหน้า
ปฏิบัติตามข้อกำหนดข้อมูลที่ไม่ระบุตัวตนของ Apple
การลงชื่อเข้าใช้ด้วย Apple ช่วยให้ผู้ใช้มีตัวเลือกในการปกปิดข้อมูลของตน รวมถึงที่อยู่อีเมลเมื่อลงชื่อเข้าใช้ ผู้ใช้ที่เลือกตัวเลือกนี้จะมีที่อยู่อีเมลที่มีโดเมน privaterelay.appleid.com
เมื่อคุณใช้การลงชื่อเข้าด้วย Apple ในแอพของคุณ คุณต้องปฏิบัติตามนโยบายหรือข้อกำหนดสำหรับนักพัฒนาที่เกี่ยวข้องใดๆ จาก Apple เกี่ยวกับ Apple ID ที่ไม่ระบุตัวตนเหล่านี้
ซึ่งรวมถึงการได้รับความยินยอมจากผู้ใช้ที่จำเป็นก่อนที่คุณจะเชื่อมโยงข้อมูลส่วนตัวที่ระบุโดยตรงกับ Apple ID ที่ไม่ระบุตัวตน เมื่อใช้ Firebase Authentication อาจรวมถึงการดำเนินการต่อไปนี้:
- เชื่อมโยงที่อยู่อีเมลกับ Apple ID ที่ไม่ระบุตัวตนหรือในทางกลับกัน
- เชื่อมโยงหมายเลขโทรศัพท์กับ Apple ID ที่ไม่ระบุตัวตนหรือในทางกลับกัน
- เชื่อมโยงข้อมูลประจำตัวทางสังคมที่ไม่ระบุตัวตน (Facebook, Google ฯลฯ) กับ Apple ID ที่ไม่ระบุตัวตนหรือในทางกลับกัน
รายการข้างต้นไม่ครบถ้วนสมบูรณ์ โปรดดูข้อตกลงสิทธิ์การใช้งานโปรแกรมนักพัฒนาซอฟต์แวร์ของ Apple ในส่วนการเป็นสมาชิกของบัญชีนักพัฒนาของคุณเพื่อให้แน่ใจว่าแอปของคุณเป็นไปตามข้อกำหนดของ Apple
จัดการขั้นตอนการลงชื่อเข้าใช้ด้วย Firebase SDK
บน Android วิธีที่ง่ายที่สุดในการตรวจสอบสิทธิ์ผู้ใช้ของคุณด้วย Firebase โดยใช้บัญชี Apple ของพวกเขาคือจัดการขั้นตอนการลงชื่อเข้าใช้ทั้งหมดด้วย Firebase Android SDK
หากต้องการจัดการขั้นตอนการลงชื่อเข้าใช้ด้วย Firebase Android SDK ให้ทำตามขั้นตอนเหล่านี้:
สร้างอินสแตนซ์ของ
OAuthProvider
โดยใช้ Builder ที่มี ID ผู้ให้บริการ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
อื่นๆ ซึ่งจะควบคุม UI ของคุณด้วยการเปิดแท็บ Chrome แบบกำหนดเอง ดังนั้น อย่าอ้างอิงกิจกรรมของคุณในOnSuccessListener
และOnFailureListener
ที่คุณแนบ เนื่องจากจะแยกออกทันทีเมื่อการดำเนินการเริ่มต้น UIคุณควรตรวจสอบก่อนว่าคุณได้รับคำตอบแล้วหรือไม่ การลงชื่อเข้าใช้ด้วยวิธีนี้จะทำให้กิจกรรมของคุณอยู่ในพื้นหลัง ซึ่งหมายความว่าระบบสามารถเรียกคืนได้ในระหว่างขั้นตอนการลงชื่อเข้าใช้ เพื่อให้แน่ใจว่าคุณจะไม่ให้ผู้ใช้ลองอีกครั้งหากสิ่งนี้เกิดขึ้น คุณควรตรวจสอบว่ามีผลลัพธ์อยู่แล้วหรือไม่
หากต้องการตรวจสอบว่ามีผลลัพธ์ที่รอดำเนินการหรือไม่ ให้เรียก
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 Auth รองรับ 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 โดยจัดการขั้นตอนการลงชื่อเข้าใช้โดยใช้ Apple Sign-In JS SDK สร้างขั้นตอน OAuth ด้วยตนเอง หรือใช้ไลบรารี OAuth เช่น AppAuth
สำหรับทุกคำขอลงชื่อเข้าใช้ ให้สร้างสตริงแบบสุ่ม ซึ่งก็คือ "nonce" ซึ่งคุณจะใช้เพื่อให้แน่ใจว่าโทเค็น ID ที่คุณได้รับนั้นได้รับโดยเฉพาะเพื่อตอบสนองคำขอการตรวจสอบสิทธิ์ของแอป ขั้นตอนนี้มีความสำคัญในการป้องกันการโจมตีซ้ำ
คุณสามารถสร้าง nonce ที่ปลอดภัยด้วยการเข้ารหัสบน 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 ตรวจสอบการตอบสนองโดยแฮช nonce ดั้งเดิมและเปรียบเทียบกับค่าที่ส่งโดย Apple
เริ่มต้นขั้นตอนการลงชื่อเข้าใช้ของ Apple โดยใช้ไลบรารี OAuth ของคุณหรือวิธีอื่นๆ อย่าลืมรวม nonce ที่แฮชเป็นพารามิเตอร์ในคำขอของคุณ
หลังจากที่คุณได้รับการตอบสนองจาก Apple ให้รับโทเค็น ID จากการตอบกลับและใช้โทเค็นที่ไม่ได้แฮชเพื่อสร้าง
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
เพื่อรับข้อมูลบัญชีผู้ใช้
ขั้นตอนถัดไป
หลังจากที่ผู้ใช้ลงชื่อเข้าใช้เป็นครั้งแรก บัญชีผู้ใช้ใหม่จะถูกสร้างขึ้นและเชื่อมโยงกับข้อมูลประจำตัว ซึ่งก็คือชื่อผู้ใช้และรหัสผ่าน หมายเลขโทรศัพท์ หรือข้อมูลผู้ให้บริการตรวจสอบสิทธิ์ ซึ่งผู้ใช้ลงชื่อเข้าใช้ด้วย บัญชีใหม่นี้จัดเก็บเป็นส่วนหนึ่งของโปรเจ็กต์ Firebase และสามารถใช้ระบุผู้ใช้ในทุกแอปในโครงการ ไม่ว่าผู้ใช้จะลงชื่อเข้าใช้ด้วยวิธีใดก็ตาม
ในแอปของคุณ คุณสามารถรับข้อมูลโปรไฟล์พื้นฐานของผู้ใช้ได้จากออบเจ็กต์
FirebaseUser
ดู จัดการผู้ใช้ใน กฎความปลอดภัย ของ Firebase Realtime Database และ Cloud Storage คุณสามารถรับ ID ผู้ใช้ที่ไม่ซ้ำกันของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปร
auth
ความถูกต้อง และใช้เพื่อควบคุมข้อมูลที่ผู้ใช้สามารถเข้าถึงได้
คุณสามารถอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอปของคุณโดยใช้ผู้ให้บริการตรวจสอบสิทธิ์หลายรายโดย เชื่อมโยงข้อมูลประจำตัวของผู้ให้บริการตรวจสอบสิทธิ์กับบัญชีผู้ใช้ที่มีอยู่
ในการออกจากระบบผู้ใช้ โทร signOut
:
Kotlin+KTX
Firebase.auth.signOut()
Java
FirebaseAuth.getInstance().signOut();