ติดตั้งใช้งานฟีเจอร์ลงชื่อเข้าใช้ด้วย Google

บทความนี้จะอธิบายวิธีใช้ฟีเจอร์ลงชื่อเข้าใช้ด้วย Google และครอบคลุมขั้นตอนต่อไปนี้

  • เพิ่มทรัพยากร Dependency ลงในแอป
  • สร้างอินสแตนซ์ของ CredentialManager
  • สร้างโฟลว์ของ Bottom Sheet
  • สร้างโฟลว์ของปุ่ม
  • จัดการการตอบกลับการลงชื่อเข้าใช้
  • จัดการข้อผิดพลาด
  • จัดการการออกจากระบบ

เพิ่มทรัพยากร Dependency ลงในแอป

ประกาศทรัพยากร Dependency โดยใช้ Credential Manager, บริการ Google Play Auth และ เวอร์ชันล่าสุดในไฟล์ build.gradle ของโมดูลgoogleid

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha01")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha01")
    implementation("com.google.android.libraries.identity.googleid:googleid:<latest version>")
}

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha01"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha01"
    implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}

สร้างอินสแตนซ์ของ Credential Manager

ใช้บริบทของแอปหรือกิจกรรมเพื่อสร้างออบเจ็กต์ CredentialManager

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

สร้างโฟลว์ของ Bottom Sheet

Bottom Sheet คือ UI ในตัวของ Credential Manager การใช้ UI นี้จะสร้างประสบการณ์การใช้งานที่สอดคล้องกันในวิธีการตรวจสอบสิทธิ์ทั้งหมด เช่น รหัสผ่าน, Passkey และลงชื่อเข้าใช้ด้วย Google

กำหนดค่าคำขอลงชื่อเข้าใช้สำหรับบัญชีที่ได้รับอนุญาตก่อนหน้านี้

ลองส่งคำขอลงชื่อเข้าใช้ด้วย Google ด้วย GetGoogleIdOption เพื่อ ดึงข้อมูล Google ID Token ของผู้ใช้

ข้อมูลโค้ดต่อไปนี้จะตรวจสอบว่าบัญชีเป็นบัญชีที่ได้รับอนุญาตหรือไม่

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(true)
    .setServerClientId(WEB_CLIENT_ID)
    .setAutoSelectEnabled(true)
    .setNonce(generateSecureRandomNonce())
    .build()

กำหนดค่าออบเจ็กต์ googleIdOption ของคำขอได้ดังนี้

  • กรองบัญชีที่ได้รับอนุญาตก่อนหน้านี้: หากต้องการดึงข้อมูลบัญชีที่ได้รับอนุญาตซึ่งเคยใช้ลงชื่อเข้าใช้แอป ให้ตั้งค่า setFilterByAuthorizedAccounts เป็น true

    โปรดทราบว่าค่าเริ่มต้นของ setFilterByAuthorizedAccounts คือ true ซึ่งหมายความว่าลักษณะการทำงานเริ่มต้นของ UI ของ Bottom Sheet คือการแสดงเฉพาะบัญชีที่ได้รับอนุญาตก่อนหน้านี้

  • ตั้งค่ารหัสไคลเอ็นต์ของเซิร์ฟเวอร์: ตั้งค่าพารามิเตอร์ setServerClientId The webClientId คือรหัสไคลเอ็นต์ของเว็บที่คุณตั้งค่าไว้สำหรับ OAuth ใน Google Cloud โปรเจ็กต์ขณะทำตามข้อกำหนดเบื้องต้น

  • เปิดใช้การลงชื่อเข้าใช้โดยอัตโนมัติ (ไม่บังคับ): หากต้องการเปิดใช้ การลงชื่อเข้าใช้โดยอัต3โนมัติ สำหรับผู้ใช้ที่กลับมา ให้ใช้ setAutoSelectEnabled(true) และ setFilterByAuthorizedAccounts(true) สำหรับผู้ใช้แอป การดำเนินการนี้จะช่วยลดความยุ่งยากที่ไม่จำเป็นหากผู้ใช้เคยลงชื่อเข้าใช้ก่อนหน้านี้

    การลงชื่อเข้าใช้โดยอัตโนมัติจะทำได้ก็ต่อเมื่อเป็นไปตามเกณฑ์ต่อไปนี้

    • มีบัญชีที่ได้รับอนุญาตเพียงบัญชีเดียวในอุปกรณ์ และบัญชีที่ได้รับอนุญาตนั้นเคยใช้ลงชื่อเข้าใช้แอปในอุปกรณ์ บัญชีที่ได้รับอนุญาตหลายบัญชีในอุปกรณ์จะปิดใช้การลงชื่อเข้าใช้โดยอัตโนมัติ
    • ผู้ใช้ไม่ได้ออกจากระบบแอปอย่างชัดแจ้งในเซสชันก่อนหน้า
    • ผู้ใช้ไม่ได้ปิดใช้การลงชื่อเข้าใช้โดยอัตโนมัติในการตั้งค่าบัญชี Google
  • ตั้งค่า Nonce (ไม่บังคับ): หากต้องการเปิดใช้ความปลอดภัยที่เพิ่มขึ้น ให้ตั้งค่า Nonce สำหรับการยืนยันฝั่งเซิร์ฟเวอร์ คุณสามารถใส่ Nonce สำหรับการยืนยันฝั่งเซิร์ฟเวอร์ด้วย setNonce() เพื่อป้องกันการโจมตีแบบ Replay ตรวจสอบว่าโค้ดฝั่งเซิร์ฟเวอร์ตรวจสอบแล้วว่า Nonce ของคำขอและการตอบกลับเหมือนกัน

    หากต้องการสร้าง Nonce ให้ใช้ฟังก์ชันที่คล้ายกับฟังก์ชันต่อไปนี้ ซึ่งจะสร้าง Nonce แบบสุ่มที่เข้ารหัสลับอย่างปลอดภัยซึ่งมีความยาวที่ระบุและเข้ารหัสโดยใช้ Base64

fun generateSecureRandomNonce(byteLength: Int = 32): String {
    val randomBytes = ByteArray(byteLength)
    SecureRandom().nextBytes(randomBytes)
    return Base64.encodeToString(randomBytes, Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING)
}

ขอให้ลงชื่อเข้าใช้

ตรวจสอบว่าผู้ใช้มีบัญชีที่ได้รับอนุญาตในอุปกรณ์หรือไม่โดยเรียกใช้เมธอด getCredential

val request: GetCredentialRequest = GetCredentialRequest.Builder()
    .addCredentialOption(googleIdOption)
    .build()

coroutineScope {
    try {
        val result = credentialManager.getCredential(
            request = request,
            context = activityContext,
        )
        handleSignIn(result)
    } catch (e: GetCredentialException) {
        // Handle failures
    }
}

กำหนดค่าคำขอลงชื่อเข้าใช้หากไม่มีบัญชีที่ได้รับอนุญาต

หากไม่มีผู้ใช้ที่ได้รับอนุญาตสำหรับแอปในอุปกรณ์ CredentialManager จะแสดง NoCredentialException ในกรณีนี้ ให้ปิดใช้ตัวกรองบัญชีที่ได้รับอนุญาตเพื่อให้ผู้ใช้ใช้บัญชีอื่นลงชื่อสมัครใช้ได้

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(false)
    .setServerClientId(WEB_CLIENT_ID)
    .setNonce(generateSecureRandomNonce())
    .build()

จากนั้นขอให้ลงชื่อเข้าใช้ในลักษณะเดียวกับที่คุณทำสำหรับบัญชีที่ได้รับอนุญาต

สร้างโฟลว์ของปุ่ม

ใช้ปุ่มหากต้องการให้ผู้ใช้ลงชื่อเข้าใช้ด้วย Google ได้ในกรณีต่อไปนี้

  • ผู้ใช้ปิด UI ของ Bottom Sheet ของ Credential Manager
  • ไม่มีบัญชี Google ในอุปกรณ์
  • บัญชีที่มีอยู่ในอุปกรณ์ต้องมีการตรวจสอบสิทธิ์อีกครั้ง

สร้าง UI ของปุ่ม

แม้ว่าคุณจะทำได้ด้วยปุ่ม Jetpack Compose แต่คุณสามารถใช้ไอคอนแบรนด์ที่ได้รับอนุมัติล่วงหน้า จากหน้าหลักเกณฑ์การสร้างแบรนด์ของฟีเจอร์ลงชื่อเข้าใช้ด้วย Google

สร้างโฟลว์การลงชื่อเข้าใช้

สร้างคำขอลงชื่อเข้าใช้ด้วย Google ด้วย GetSignInWithGoogleOption เพื่อดึงข้อมูล Google ID Token

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
    serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
    .build()

จากนั้น ขอให้ลงชื่อเข้าใช้ ในลักษณะเดียวกับที่คุณทำสำหรับ UI ของ Bottom Sheet

สร้างฟังก์ชันการลงชื่อเข้าใช้ที่แชร์สำหรับ Bottom Sheet และปุ่ม

หากต้องการจัดการการลงชื่อเข้าใช้ ให้ทำตามขั้นตอนต่อไปนี้

  1. ใช้ฟังก์ชัน getCredential() ของ CredentialManager หากการตอบกลับสำเร็จ ให้แยก CustomCredential ซึ่งควรเป็นประเภท GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
  2. แปลงออบเจ็กต์เป็น GoogleIdTokenCredential โดยใช้ เมธอด GoogleIdTokenCredential.createFrom()

  3. ตรวจสอบข้อมูลเข้าสู่ระบบในเซิร์ฟเวอร์ของบริษัทอื่นที่เกี่ยวข้อง

  4. ตรวจสอบว่าคุณจัดการข้อผิดพลาดอย่างเหมาะสม

fun handleSign(result: GetCredentialResponse) {
    // Handle the successfully returned credential.
    val credential = result.credential

    when (credential) {
        is CustomCredential -> {
            if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
                try {
                    // Use googleIdTokenCredential and extract the ID for server-side validation.
                    val googleIdTokenCredential = GoogleIdTokenCredential
                        .createFrom(credential.data)
                } catch (e: GoogleIdTokenParsingException) {
                    Log.e(TAG, "Received an invalid google id token response", e)
                }
            } else {
                // Catch any unrecognized credential type here.
                Log.e(TAG, "Unexpected type of credential")
            }
        }

        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential")
        }
    }
}

จัดการข้อผิดพลาด

ตรวจสอบข้อผิดพลาดที่ระบุไว้ใน การแก้ปัญหา เพื่อให้แน่ใจว่าโค้ดของคุณจัดการ สถานการณ์ข้อผิดพลาดที่เป็นไปได้ทั้งหมด

จัดการการออกจากระบบ

คุณต้องมีกลไกให้ผู้ใช้ออกจากระบบแอปได้ เช่น ผู้ใช้อาจมีบัญชี Google หลายบัญชีในอุปกรณ์และตัดสินใจลงชื่อเข้าใช้จากบัญชีอื่น คุณสามารถระบุกลไกนี้ไว้ในหน้าการตั้งค่า เป็นต้น

ผู้ให้บริการข้อมูลเข้าสู่ระบบอาจจัดเก็บเซสชันข้อมูลเข้าสู่ระบบที่ใช้งานอยู่และใช้เซสชันดังกล่าวเพื่อจำกัดตัวเลือกการลงชื่อเข้าใช้สำหรับคำขอลงชื่อเข้าใช้ในอนาคต เช่น อาจจัดลำดับความสำคัญของข้อมูลเข้าสู่ระบบที่ใช้งานอยู่เหนือข้อมูลเข้าสู่ระบบอื่นๆ ที่มี

เมื่อผู้ใช้ออกจากระบบแอป ให้เรียกใช้เมธอด API clearCredentialState() เพื่อล้างสถานะข้อมูลเข้าสู่ระบบของผู้ใช้ปัจจุบันจากผู้ให้บริการข้อมูลเข้าสู่ระบบทั้งหมด การดำเนินการนี้จะแจ้งให้ผู้ให้บริการข้อมูลเข้าสู่ระบบทั้งหมดทราบว่าควรล้างเซสชันข้อมูลเข้าสู่ระบบที่จัดเก็บไว้สำหรับแอปที่กำหนด เพื่อให้ผู้ใช้มีตัวเลือกการลงชื่อเข้าใช้ทั้งหมดในครั้งถัดไป