Tích hợp Trình quản lý thông tin xác thực với tính năng Đăng nhập bằng Google

Bảng dưới cùng có bật Trình quản lý thông tin xác thực cho thấy nhiều danh tính để chọn.
Hình 1. Hộp thoại của bảng dưới cùng Đăng nhập bằng Google xuất hiện sau khi tích hợp với API Trình quản lý thông tin xác thực.

Tài liệu này giải thích cách di chuyển hộp thoại của bảng dưới cùng Đăng nhập bằng Google từ Dịch vụ nhận dạng của Google (GIS) sang API Trình quản lý thông tin xác thực bằng thư viện trình trợ giúp Mã nhận dạng trên Google.

Một ứng dụng dùng API Trình quản lý thông tin xác thực được định cấu hình để hiển thị giao diện người dùng Android nhất quán cho người dùng cuối. Nhờ vậy, người dùng có thể chọn trong danh sách các lựa chọn đăng nhập đã lưu, bao gồm cả tài khoản đã bật khoá truy cập. Đây là API Android được đề xuất để hợp nhất nhiều loại thông tin xác thực và trình cung cấp. Kể từ Android 14, người dùng cũng có thể sử dụng trình quản lý mật khẩu của bên thứ ba với API trình quản lý thông tin xác thực.

Khai báo phần phụ thuộc

Trong tệp build.gradle của mô-đun, hãy khai báo các phần phụ thuộc bằng cách sử dụng phiên bản mới nhất:

dependencies {
  // ... other dependencies

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

Làm theo hướng dẫn để thiết lập dự án bảng điều khiển API của Google. Thay thế hướng dẫn về cách thêm các phần phụ thuộc bằng hướng dẫn nêu trên.

Tạo thực thể cho yêu cầu đăng nhập bằng Google

Để bắt đầu quá trình triển khai, bạn hãy tạo thực thể cho một yêu cầu đăng nhập bằng Google. Sử dụ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.

Kotlin

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .build()

Java

GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .build();

Trước tiên, bạn phải gọi API có tham số setFilterByAuthorizedAccounts được đặt thành true. Nếu không có thông tin xác thực, hãy gọi lại API và đặt setFilterByAuthorizedAccounts thành false.

Nếu bạn muốn tự động đăng nhập người dùng khi có thể, hãy bật tính năng có setAutoSelectEnabled trong yêu cầu GetGoogleIdOption của bạn. Người dùng có thể tự động được đăng nhập khi đáp ứng các tiêu chí sau đây:

  • Người dùng đã lưu chính xác một thông tin đăng nhập cho ứng dụng của bạn. Tức là người dùng đã lưu một mật khẩu hoặc một Tài khoản Google.
  • 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.

Để cải thiện khả năng bảo mật khi đăng nhập và tránh các cuộc tấn công phát lại, hãy sử dụng setNonce để đưa số chỉ dùng một lần vào mỗi yêu cầu. Tìm hiểu thêm về cách tạo số chỉ dùng một lần.

Kotlin

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Java

GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(SERVER_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>);
  .build();

Đăng nhập bằng Google

Các bước thiết lập quy trình Đăng nhập bằng Google như sau:

  1. Tạo thực thể cho GetCredentialRequest và thêm googleIdOption đã tạo ở trên để truy xuất thông tin đăng nhập.
  2. Truyền yêu cầu này đến lệnh gọi getCredential() (Kotlin) hoặc getCredentialAsync() (Java) để truy xuất thông tin đăng nhập có sẵn của người dùng.
  3. Sau khi API thành công, hãy trích xuất CustomCredential chứa kết quả cho dữ liệu GoogleIdTokenCredential.
  4. Loại CustomCredential phải bằng với giá trị của GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL. Chuyển đổi đối tượng thành GoogleIdTokenCredential bằng phương thức GoogleIdTokenCredential.createFrom.
  5. Nếu quá trình chuyển đổi thành công, hãy trích xuất mã nhận dạng của GoogleIdTokenCredential, xác thực mã này và xác thực thông tin đăng nhập trên máy chủ của bạn.
  6. Nếu không chuyển đổi được GoogleIdTokenParsingException, thì bạn có thể cần cập nhật phiên bản thư viện Đăng nhập bằng Google.
  7. Nắm bắt mọi loại thông tin đăng nhập tuỳ chỉnh không được nhận dạng.

Kotlin

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

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

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

  when (credential) {
    is PublicKeyCredential -> {
      // Share responseJson such as a GetCredentialResponse on your server to
      // validate and authenticate
      responseJson = credential.authenticationResponseJson
    }

    is PasswordCredential -> {
      // Send ID and password to your server to validate and authenticate.
      val username = credential.id
      val password = credential.password
    }

    is CustomCredential -> {
      if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        try {
          // Use googleIdTokenCredential and extract id to validate and
          // authenticate on your server.
          val googleIdTokenCredential = GoogleIdTokenCredential
            .createFrom(credential.data)
        } catch (e: GoogleIdTokenParsingException) {
          Log.e(TAG, "Received an invalid google id token response", e)
        }
      } else {
        // Catch any unrecognized custom credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

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

Java

GetCredentialRequest request = new GetCredentialRequest.Builder()
  .addGetCredentialOption(googleIdOption)
  .build();

// Launch sign in flow and do getCredential Request to retrieve the credentials
credentialManager.getCredentialAsync(
  requireActivity(),
  request,
  cancellationSignal,
  <executor>,
  new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
    @Override
    public void onResult(GetCredentialResponse result) {
      handleSignIn(result);
    }

    @Override
    public void onError(GetCredentialException e) {
      handleFailure(e);
    }
  }
);

public void handleSignIn(GetCredentialResponse result) {
  // Handle the successfully returned credential.
  Credential credential = result.getCredential();

  if (credential instanceof PublicKeyCredential) {
    String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson();
    // Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate
  } else if (credential instanceof PasswordCredential) {
    String username = ((PasswordCredential) credential).getId();
    String password = ((PasswordCredential) credential).getPassword();
    // Use id and password to send to your server to validate and authenticate
  } else if (credential instanceof CustomCredential) {
    if (GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.equals(credential.getType())) {
      try {
        // Use googleIdTokenCredential and extract id to validate and
        // authenticate on your server
        GoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(((CustomCredential) credential).getData());
      } catch (GoogleIdTokenParsingException e) {
        Log.e(TAG, "Received an invalid Google ID token response", e);
      }
    } else {
      // Catch any unrecognized custom credential type here.
      Log.e(TAG, "Unexpected type of credential");
    }
  } else {
    // Catch any unrecognized credential type here.
    Log.e(TAG, "Unexpected type of credential");
  }
}

Nút Đăng nhập bằng Google

Nút Đăng nhập bằng Google được Trình quản lý thông tin xác thực hỗ trợ cùng với thư viện trình trợ giúp mới nhất cho mã nhận dạng trên Google. Để kích hoạt quy trình đăng nhập bằng nút Đăng nhập bằng Google, hãy sử dụng GetSignInWithGoogleOption thay vì GetGoogleIdOption và xử lý GoogleIdTokenCredential được trả về giống như trước đây.

Đăng ký bằng Google

Nếu không kết quả nào được trả về sau khi bạn đặt setFilterByAuthorizedAccounts thành true trong khi tạo thực thể cho yêu cầu GetGoogleIdOption và truyền vào GetCredentialsRequest, thì tức là không có tài khoản nào được uỷ quyền để đăng nhập. Tại thời điểm này, bạn nên đặt setFilterByAuthorizedAccounts(false) và gọi phương thức Đăng ký bằng Google.

Kotlin

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(false)
  .setServerClientId(SERVER_CLIENT_ID)
  .build()

Java

GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(false)
  .setServerClientId(SERVER_CLIENT_ID)
  .build();

Sau khi tạo thực thể cho yêu cầu đăng ký bằng Google, hãy chạy quy trình xác thực theo cách tương tự như đã đề cập trong phần Đăng nhập bằng Google.

Xử lý khi đăng xuất

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 của người dùng hiện tại và đặt lại trạng thái đăng nhập nội bộ.