Triển khai tính năng Đăng nhập bằng Google

Hướng dẫn này mô tả cách triển khai tính năng Đăng nhập bằng Google và bao gồm các bước sau:

  • Thêm các phần phụ thuộc vào ứng dụng.
  • Tạo thực thể CredentialManager.
  • Tạo quy trình bảng dưới cùng.
  • Tạo luồng nút.
  • Xử lý phản hồi đăng nhập.
  • Xử lý lỗi.
  • Xử lý khi đăng xuất.

Thêm phần phụ thuộc vào ứng dụng

Trong tệp build.gradle của mô-đun, hãy khai báo các phần phụ thuộc bằng phiên bản mới nhất của Trình quản lý thông tin xác thực, Xác thực Dịch vụ Playgoogleid:

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>"
}

Khởi tạo Trình quản lý thông tin xác thực

Sử dụng ngữ cảnh ứng dụng hoặc hoạt động để tạo đối tượng CredentialManager.

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

Tạo quy trình cho bảng dưới cùng

Bảng dưới cùng là giao diện người dùng tích hợp sẵn của Trình quản lý thông tin xác thực. Việc sử dụng giao diện người dùng này sẽ tạo ra trải nghiệm nhất quán trên tất cả các phương thức xác thực, chẳng hạn như mật khẩu, khoá truy cập và Đăng nhập bằng Google.

Định cấu hình yêu cầu đăng nhập cho các tài khoản đã được uỷ quyền trước đây

Thử yêu cầu đăng nhập bằng Google bằng GetGoogleIdOption để truy xuất Mã thông báo cho mã nhận dạng trên Google của người dùng.

Các đoạn mã sau đây kiểm tra xem tài khoản có phải là tài khoản được uỷ quyền hay không.

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

Đối tượng googleIdOption của yêu cầu được định cấu hình như sau:

  • Lọc các tài khoản đã được uỷ quyền trước đó: Để truy xuất các tài khoản đã được uỷ quyền từng được dùng để đăng nhập vào ứng dụng của bạn, hãy đặt setFilterByAuthorizedAccounts thành true.

    Xin lưu ý rằng giá trị mặc định cho setFilterByAuthorizedAccountstrue, tức là hành vi mặc định cho giao diện người dùng bảng dưới cùng là chỉ hiển thị những tài khoản đã được uỷ quyền trước đó.

  • Đặt mã ứng dụng khách máy chủ: Đặt tham số setServerClientId. webClientId là Mã ứng dụng khách trên web mà bạn thiết lập cho OAuth trong Dự án Google Cloud khi hoàn tất các điều kiện tiên quyết.

  • Bật tính năng tự động đăng nhập (không bắt buộc): Để bật tính năng tự động đăng nhập cho người dùng cũ, hãy sử dụng setAutoSelectEnabled(true)setFilterByAuthorizedAccounts(true). Đối với người dùng ứng dụng của bạn, điều này giúp loại bỏ những rào cản không cần thiết nếu họ đã đăng nhập trước đó.

    Người dùng chỉ có thể tự động được đăng nhập khi đáp ứng các tiêu chí sau đây:

    • Chỉ có một tài khoản được uỷ quyền duy nhất trên thiết bị và tài khoản được uỷ quyền đó đã từng được dùng để đăng nhập vào ứng dụng trên thiết bị. Nhiều tài khoản được uỷ quyền trên thiết bị sẽ tắt tính năng tự động đăng nhập.
    • Người dùng chưa đăng xuất khỏi ứng dụng một cách rõ ràng trong phiên trước.
    • Người dùng chưa tắt tính năng Tự động đăng nhập trong phần Cài đặt Tài khoản Google.
  • Đặt số chỉ dùng một lần (không bắt buộc): Để tăng cường bảo mật, hãy đặt số chỉ dùng một lần cho quy trình xác minh phía máy chủ. Để ngăn chặn các cuộc tấn công phát lại, bạn có thể thêm một số chỉ dùng một lần để xác minh phía máy chủ bằng setNonce(). Đảm bảo rằng mã phía máy chủ của bạn xác thực rằng các số chỉ dùng một lần của yêu cầu và phản hồi là giống nhau.

    Để tạo số chỉ dùng một lần, hãy sử dụng một hàm tương tự như hàm sau. Hàm này tạo một số chỉ dùng một lần ngẫu nhiên có độ bảo mật cao với độ dài được chỉ định và mã hoá số đó bằng cách sử dụng 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)
}

Yêu cầu đăng nhập

Kiểm tra xem người dùng có tài khoản được uỷ quyền trên thiết bị hay không bằng cách gọi phương thức 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
    }
}

Định cấu hình yêu cầu đăng nhập nếu không có tài khoản nào được uỷ quyền

Nếu không có người dùng nào được uỷ quyền cho ứng dụng của bạn trên thiết bị, thì CredentialManager sẽ trả về NoCredentialException. Trong trường hợp này, hãy tắt bộ lọc tài khoản được uỷ quyền để người dùng có thể sử dụng một tài khoản khác để đăng ký.

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

Tiếp theo, hãy yêu cầu đăng nhập tương tự như cách bạn đã làm đối với tài khoản được uỷ quyền.

Tạo luồng nút

Sử dụng nút nếu bạn muốn người dùng có thể Đăng nhập bằng Google trong các trường hợp sau:

  • Người dùng đã đóng giao diện người dùng bảng dưới cùng của Trình quản lý thông tin xác thực.
  • Không có Tài khoản Google nào trên thiết bị này.
  • Bạn cần xác thực lại các tài khoản hiện có trên thiết bị.

Tạo giao diện người dùng cho nút

Mặc dù có thể thực hiện việc này bằng nút Jetpack Compose, nhưng bạn có thể sử dụng biểu tượng thương hiệu được phê duyệt trước trên trang Nguyên tắc sử dụng thương hiệu của tính năng Đăng nhập bằng Google.

Tạo quy trình đăng nhập

Tạo yêu cầu đăng nhập bằng Google bằng GetSignInWithGoogleOption để truy xuất Mã thông báo cho mã nhận dạng trên Google.

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

Tiếp theo, hãy yêu cầu đăng nhập tương tự như cách bạn đã làm cho giao diện người dùng của bảng dưới cùng.

Tạo chức năng đăng nhập dùng chung cho bảng dưới cùng và nút

Để xử lý quy trình đăng nhập, hãy hoàn tất các bước sau:

  1. Sử dụng hàm getCredential() của CredentialManager. Nếu phản hồi thành công, hãy trích xuất CustomCredential, phải thuộc loại GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.
  2. Chuyển đổi đối tượng thành GoogleIdTokenCredential bằng phương thức GoogleIdTokenCredential.createFrom().

  3. Xác thực thông tin đăng nhập trên máy chủ bên thứ ba đáng tin cậy.

  4. Đảm bảo rằng bạn xử lý lỗi một cách phù hợp.

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")
        }
    }
}

Xử lý lỗi

Xem lại các lỗi được liệt kê trong phần Khắc phục sự cố để đảm bảo mã của bạn xử lý tất cả các trường hợp lỗi có thể xảy ra.

Xử lý khi đăng xuất

Bạn cần cung cấp một cơ chế để người dùng đăng xuất khỏi ứng dụng của bạn. Ví dụ: người dùng có thể có nhiều Tài khoản Google trên thiết bị và quyết định đăng nhập bằng một tài khoản khác. Bạn có thể cung cấp thông tin này trong trang cài đặt của mình, chẳng hạn.

Trình cung cấp thông tin đăng nhập có thể lưu trữ một phiên thông tin đăng nhập đang hoạt động và sử dụng phiên đó để giới hạn các lựa chọn đăng nhập cho các yêu cầu đăng nhập trong tương lai. Ví dụ: nó có thể ưu tiên thông tin đăng nhập đang hoạt động hơn bất kỳ thông tin đăng nhập nào khác có sẵn.

Khi người dùng đăng xuất khỏi ứng dụng, hãy gọi phương thức API clearCredentialState() để xoá trạng thái thông tin đăng nhập hiện tại của người dùng khỏi tất cả trình cung cấp thông tin đăng nhập. Thao tác này sẽ thông báo cho tất cả các trình cung cấp thông tin đăng nhập rằng mọi phiên thông tin đăng nhập đã lưu trữ cho ứng dụng đã cho đều phải được xoá, cung cấp cho người dùng đầy đủ các lựa chọn đăng nhập vào lần tiếp theo.