本文說明如何使用 Google ID 輔助程式庫,將「使用 Google 帳戶登入」底部功能表對話方塊從 Google Identity 服務 (GIS) 遷移至 Credential Manager API。
如果應用程式使用 Credential Manager API,就會向使用者提供一致的 Android 使用者介面,使用者就能從已儲存的登入選項清單中選取所需項目,包括已啟用密碼金鑰的帳戶。如要整合不同的憑證類型和提供者,則建議使用這個 Android API。從 Android 14 開始,使用者也可以搭配使用第三方密碼管理工具與 Credential Manager API。
宣告依附元件
請在模組的 build.gradle
檔案中,使用最新版本宣告依附元件:
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>"
}
請按照這個操作說明設定 Google API 控制台專案,但請依照前文提及的說明納入依附元件。
將 Google 登入要求例項化
如要開始實作,請將 Google 登入要求例項化。請使用 GetGoogleIdOption
擷取使用者的 Google ID 權杖。
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();
您應先呼叫 setFilterByAuthorizedAccounts
參數設為 true
的 API。如果沒有可用憑證,請再次呼叫 API,並將 setFilterByAuthorizedAccounts
設為 false
。
如要盡可能讓使用者自動登入,請在 GetGoogleIdOption
要求中使用 setAutoSelectEnabled
啟用這項功能。只要符合下列條件,就可以自動登入:
- 使用者只儲存了一組應用程式憑證,也就是只儲存一組密碼或一個 Google 帳戶。
- 使用者未在 Google 帳戶設定中停用自動登入功能。
為提升登入安全性並避免重送攻擊,請使用 setNonce
,在每項要求中加入 Nonce。進一步瞭解如何產生 Nonce。
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();
使用 Google 帳戶登入
設定「使用 Google 帳戶登入」流程的步驟如下:
- 將
GetCredentialRequest
例項化,並新增在上述步驟中建立的googleIdOption
來擷取憑證。 - 將這項要求傳遞至
getCredential()
(Kotlin) 或getCredentialAsync()
(Java) 呼叫,擷取使用者可用的憑證。 - API 成功後,請擷取保留
GoogleIdTokenCredential
資料結果的CustomCredential
。 CustomCredential
的類型應等於GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
的值。請使用GoogleIdTokenCredential.createFrom
方法,將物件轉換為GoogleIdTokenCredential
。- 如果轉換成功,請擷取並驗證
GoogleIdTokenCredential
的 ID,然後在伺服器上驗證憑證。 - 如果轉換作業因
GoogleIdTokenParsingException
失敗,您可能需要更新使用 Google 帳戶登入資料庫的版本。 - 找出所有無法辨識的自訂憑證類型。
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");
}
}
「使用 Google 帳戶登入」按鈕
搭配使用 Credential Manager 和最新的 Google ID 輔助程式庫,即可支援「使用 Google 帳戶登入」按鈕。如要觸發「使用 Google 帳戶登入」按鈕流程,請使用 GetSignInWithGoogleOption
(而非 GetGoogleIdOption
),然後採用與先前相同的方式處理傳回的 GoogleIdTokenCredential
。
使用 Google 帳戶註冊
如果在將 GetGoogleIdOption
例項化及傳遞至 GetCredentialsRequest
時將 setFilterByAuthorizedAccounts
設為 true
,之後系統卻沒有傳回任何結果,就表示沒有可登入的已授權帳戶。此時,您應設定 setFilterByAuthorizedAccounts(false)
,並呼叫使用 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();
將 Google 註冊要求例項化後,請採用「使用 Google 帳戶登入」一節所述的類似方式啟動驗證流程。
處理登出動作
當使用者登出應用程式時,請呼叫 API clearCredentialState()
方法,清除目前的使用者憑證狀態,並重設登入程序的內部狀態。