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

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

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

เพิ่มการอ้างอิงไปยังแอป

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

Kotlin

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

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.6.0-rc02"
    implementation "androidx.credentials:credentials-play-services-auth:1.6.0-rc02"
    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 ในตัวของเครื่องมือจัดการข้อมูลเข้าสู่ระบบ การใช้ UI นี้จะสร้างประสบการณ์การใช้งานที่สอดคล้องกันในวิธีการตรวจสอบสิทธิ์ทั้งหมด เช่น รหัสผ่าน พาสคีย์ และลงชื่อเข้าใช้ด้วย Google

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

พยายามส่งคำขอลงชื่อเข้าใช้ Google ด้วย GetGoogleIdOption เพื่อ เรียกข้อมูลโทเค็นรหัส Google ของผู้ใช้

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

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

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

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

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

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

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

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

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

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

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

สร้างขั้นตอนการลงชื่อเข้าใช้

สร้างคำขอลงชื่อเข้าใช้ด้วย Google โดยใช้ GetSignInWithGoogleOption เพื่อดึงข้อมูลโทเค็นรหัส Google

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

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

สร้างฟังก์ชันการลงชื่อเข้าใช้ที่แชร์สำหรับ 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 หลายบัญชีในอุปกรณ์และตัดสินใจ ลงชื่อเข้าใช้จากบัญชีอื่น คุณระบุข้อมูลนี้ได้ในหน้าการตั้งค่า เช่น

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

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