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

Tính năng Đăng nhập bằng Google giúp bạn nhanh chóng tích hợp phương thức xác thực người dùng với ứng dụng Android. Người dùng có thể dùng Tài khoản Google để đăng nhập vào ứng dụng, đồng ý và chia sẻ thông tin hồ sơ với ứng dụng của bạn một cách an toàn. Thư viện Jetpack của Trình quản lý thông tin xác thực của Android giúp quá trình tích hợp này diễn ra suôn sẻ, mang đến trải nghiệm nhất quán trên các thiết bị Android bằng một API duy nhất.

Tài liệu này hướng dẫn bạn triển khai tính năng Đăng nhập bằng Google trong ứng dụng Android, cách thiết lập giao diện người dùng của nút Đăng nhập bằng Google cũng như cách định cấu hình trải nghiệm đăng nhập và đăng ký bằng một lần chạm được tối ưu hoá cho ứng dụng. Để di chuyển thiết bị suôn sẻ, tính năng Đăng nhập bằng Google hỗ trợ tính năng tự động đăng nhập. Bản chất của nhiều nền tảng trên các nền tảng Android, iOS và web giúp bạn cung cấp quyền truy cập đăng nhập cho ứng dụng của mình trên mọi thiết bị.

Để thiết lập tính năng Đăng nhập bằng Google, hãy làm theo hai bước chính sau:

Định cấu hình tính năng Đăng nhập bằng Google dưới dạng một tuỳ chọn cho 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. Bạn có thể thiết lập tính năng này để tự động nhắc người dùng đăng nhập. Nếu đã triển khai khoá truy cập hoặc mật khẩu, bạn có thể yêu cầu đồng thời mọi loại thông tin xác thực có liên quan để người dùng không phải nhớ tuỳ chọn họ đã dùng trước đó để đăng nhập.

Bảng dưới cùng của Trình quản lý thông tin xác thực
Hình 1. Giao diện người dùng chọn thông tin xác thực trong bảng dưới cùng của Trình quản lý thông tin xác thực

Thêm nút Đăng nhập bằng Google vào giao diện người dùng của ứng dụng. Nút Đăng nhập bằng Google giúp người dùng sử dụng Tài khoản Google hiện có của họ để đăng ký hoặc đăng nhập vào các ứng dụng Android một cách hợp lý. Người dùng sẽ nhấp vào nút Đăng nhập bằng Google nếu họ đóng giao diện người dùng ở bảng dưới cùng, hoặc nếu họ rõ ràng muốn sử dụng Tài khoản Google của mình để đăng ký và đăng nhập. Đối với nhà phát triển, điều này giúp quy trình làm quen của người dùng trở nên dễ dàng hơn và giảm thiểu những bước phiền hà trong quá trình đăng ký.

Ảnh động minh hoạ quy trình Đăng nhập bằng Google
Hình 2. Giao diện người dùng của nút Đăng nhập bằng Google trong Trình quản lý thông tin xác thực

Tài liệu này giải thích cách tích hợp nút Đăng nhập bằng Google và hộp thoại ở bảng dưới cùng với 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.

Thiết lập dự án trên bảng điều khiển API của Google

  1. Mở dự án của bạn trong Bảng điều khiển API hoặc tạo một dự án nếu bạn chưa có.
  2. Trên trang màn hình xin phép bằng OAuth, hãy đảm bảo tất cả thông tin đều đầy đủ và chính xác.
    1. Đảm bảo bạn đã chỉ định đúng Tên ứng dụng, Biểu trưng ứng dụng và Trang chủ ứng dụng cho ứng dụng. Các giá trị này sẽ hiển thị cho người dùng trên màn hình đồng ý Đăng nhập bằng Google khi đăng ký, cũng như màn hình Các ứng dụng và dịch vụ bên thứ ba.
    2. Đảm bảo rằng bạn đã chỉ định các URL trong chính sách quyền riêng tư và điều khoản dịch vụ của ứng dụng.
  3. Trên trang Thông tin xác thực, hãy tạo một mã ứng dụng khách Android cho ứng dụng của bạn nếu bạn chưa có. Bạn sẽ cần chỉ định tên gói và chữ ký SHA-1 của ứng dụng.
    1. Truy cập trang Thông tin xác thực.
    2. Nhấp vào Tạo thông tin xác thực > Mã ứng dụng khách OAuth.
    3. Chọn loại ứng dụng Android.
  4. Trên trang Thông tin xác thực, hãy tạo một mã ứng dụng khách "Ứng dụng web" mới nếu bạn chưa có. Hiện tại, bạn có thể bỏ qua các trường "Nguồn gốc JavaScript được cho phép" và "URI chuyển hướng được uỷ quyền". Mã ứng dụng khách này sẽ được dùng để xác định máy chủ phụ trợ của bạn khi máy chủ này giao tiếp với các dịch vụ xác thực của Google.
    1. Truy cập trang Thông tin xác thực.
    2. Nhấp vào Tạo thông tin xác thực > Mã ứng dụng khách OAuth.
    3. Chọn loại ứng dụng web.

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 của Trình quản lý thông tin xác thực:

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

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, 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.

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

Trước tiên, hãy kiểm tra xem người dùng có tài khoản nào từng được dùng để đăng nhập vào ứng dụng của bạn hay không bằng cách gọi API với tham số setFilterByAuthorizedAccounts được đặt thành true. Người dùng có thể chọn trong số các tài khoản hiện có để đăng nhập.

Nếu không có Tài khoản Google được uỷ quyền nào, thì người dùng sẽ được nhắc đăng ký bằng bất kỳ tài khoản nào mà họ hiện có. Để thực hiện việc này, hãy nhắc người dùng bằng cách gọi lại API và đặt setFilterByAuthorizedAccounts thành false. Tìm hiểu thêm về cách đăng ký.

Bật tính năng tự động đăng nhập cho người dùng cũ (được đề xuất)

Nhà phát triển nên bật tính năng tự động đăng nhập cho những người dùng đăng ký bằng một tài khoản duy nhất. Điều này mang lại trải nghiệm liền mạch trên các thiết bị, đặc biệt là trong quá trình di chuyển thiết bị, trong đó người dùng có thể nhanh chóng lấy lại quyền truy cập vào tài khoản của mình mà không cần nhập lại thông tin đăng nhập. Đối với người dùng, việc này sẽ loại bỏ sự phiền toái không cần thiết khi họ đã đăng nhập trước đó.

Để bật tính năng tự động đăng nhập, hãy sử dụng setAutoSelectEnabled(true). Bạn chỉ có thể tự động đăng nhập khi đáp ứng các tiêu chí sau đây:

  • Có một thông tin xác thực phù hợp với yêu cầu, có thể là Tài khoản Google hoặc mật khẩu, và thông tin đăng nhập này khớp với tài khoản mặc định trên thiết bị chạy Android.
  • Người dùng chưa đăng xuất một cách rõ ràng.
  • 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.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Hãy nhớ xử lý quy trình đăng xuất đúng cách khi triển khai chế độ đăng nhập tự động để người dùng luôn có thể chọn đúng tài khoản sau khi đã đăng xuất khỏi ứng dụng của bạn một cách rõ ràng.

Đặt số chỉ dùng một lần để tăng cường bảo mật

Để 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 thêm 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.

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

Tạo quy trình Đă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, sau đó thêm googleIdOption đã tạo trước đó bằng cách sử dụng addCredentialOption() để truy xuất thông tin xác thực.
  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 của 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 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.

val request: GetCredentialRequest = Builder()
  .addCredentialOption(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) {

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

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

    // GoogleIdToken credential
    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")
    }
  }
}

Kích hoạt quy trình nút Đăng nhập bằng Google

Để kích hoạt quy trình nút Đăng nhập bằng Google, hãy sử dụng GetSignInWithGoogleOption thay vì GetGoogleIdOption:

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder()
  .setServerClientId(WEB_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Xử lý GoogleIdTokenCredential được trả về như mô tả trong đoạn mã ví dụ sau.

fun handleSignIn(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 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 credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

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

Sau khi tạo thực thể cho yêu cầu đăng nhập 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.

Cho phép đăng ký cho người dùng mới (được đề xuất)

Đăng nhập bằng Google là cách dễ nhất để người dùng tạo tài khoản mới bằng ứng dụng hoặc dịch vụ của bạn chỉ bằng vài lần nhấn.

Nếu không tìm thấy thông tin đăng nhập đã lưu (không tìm thấy Tài khoản Google nào do getGoogleIdOption trả về), hãy nhắc người dùng đăng ký. Trước tiên, hãy kiểm tra xem setFilterByAuthorizedAccounts(true) có tồn tại tài khoản đã sử dụng trước đó hay không. Nếu không tìm thấy gì, hãy nhắc người dùng đăng ký bằng Tài khoản Google của họ thông qua setFilterByAuthorizedAccounts(false)

Ví dụ:

val googleIdOption: GetGoogleIdOption = 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. Nếu người dùng không muốn đăng ký qua Google, hãy cân nhắc sử dụng các dịch vụ tự động điền hoặc khoá truy cập để tạo tài khoản.

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 khỏi tất cả các trình cung cấp thông tin xác thực. Thao tác này sẽ thông báo cho tất cả các trình cung cấp thông tin xác thực rằng mọi phiên thông tin xác thực đã lưu trữ cho ứng dụng nhất định sẽ bị xoá.

Trình cung cấp thông tin xác thực có thể đã lưu trữ một phiên thông tin xác thực đang hoạt động và sử dụng phiên đó để giới hạn các tuỳ chọn đăng nhập cho các lệnh gọi nhận thông tin xác thực trong tương lai. Ví dụ: hệ thống này có thể ưu tiên thông tin xác thực đang hoạt động hơn mọi thông tin xác thực có sẵn khác. Khi người dùng đăng xuất khỏi ứng dụng của bạn một cách rõ ràng và để có được các tuỳ chọn đăng nhập toàn diện vào lần tiếp theo, bạn nên gọi API này để cho phép trình cung cấp xoá mọi phiên thông tin xác thực được lưu trữ.