使用 Google 帳戶登入可協助您快速將使用者驗證功能整合至 Android 應用程式。使用者可以使用 Google 帳戶登入您的應用程式、提供同意聲明,並安全地將個人資料與您的應用程式分享。Android 的 Credential Manager Jetpack 程式庫可讓這項整合作業順利進行,並透過單一 API 在各 Android 裝置上提供一致的體驗。
本文將引導您在 Android 應用程式中實作「使用 Google 帳戶登入」功能,說明如何設定「使用 Google 帳戶登入」按鈕 UI,以及如何設定應用程式最佳化的 One Tap 註冊和登入體驗。為了順利進行裝置遷移,使用 Google 帳戶登入功能可支援自動登入,而且跨平台的特性可在 Android、iOS 和網頁介面上,為任何裝置上的應用程式提供登入存取權。如果您為應用程式使用 Firebase 驗證,請參閱「在 Android 上使用 Google 進行驗證」指南,進一步瞭解如何整合「使用 Google 帳戶登入」和 Credential Manager。
如要設定「使用 Google 帳戶登入」,請按照下列兩個主要步驟操作:
將「使用 Google 帳戶登入」設定為 Credential Manager 底部功能表 UI 的選項。您可以設定這項功能,讓系統自動提示使用者登入。如果您已導入 密碼金鑰或密碼,可以同時要求所有相關的憑證類型,這樣使用者就不必記得先前用來登入的選項。

在應用程式的 UI 中加入「使用 Google 帳戶登入」按鈕。「使用 Google 帳戶登入」按鈕可讓使用者以現有的 Google 帳戶登入 Android 應用程式,或註冊該應用程式。如果使用者關閉底部功能表 UI,或是明確想要使用 Google 帳戶登入/註冊,就會點選「使用 Google 帳戶登入」按鈕。對開發人員而言,這代表使用者更容易完成新手上路流程,註冊過程也更順暢。

本文說明如何使用 Google ID 輔助程式庫,將「使用 Google 帳戶登入」按鈕和底部功能表對話方塊與 Credential Manager API 整合。
設定 專案
- 在 中開啟專案,或建立專案 (如果尚未建立)。
- 在 中,請確認所有資訊都完整且正確。
- 在 中,為應用程式建立 Android 用戶端 ID (如果尚未建立)。您必須指定應用程式的套件名稱和 SHA-1 簽名。
- 在 中,建立新的「Web application」用戶端 ID (如果尚未建立)。您可以先忽略「Authorized JavaScript Origins」和「Authorized redirect URIs」欄位。當後端伺服器與 Google 驗證服務通訊時,這個用戶端 ID 會用於識別後端伺服器。
宣告依附元件
在模組的 build.gradle 檔案中,使用最新版本的 Credential Manager 宣告依附元件:
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 登入要求例項化
如要開始實作,請將 Google 登入要求例項化。請使用 GetGoogleIdOption
擷取使用者的 Google ID 權杖。
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()
首先,請呼叫 API,並將 setFilterByAuthorizedAccounts
參數設為 true
,檢查使用者是否有任何帳戶先前用於登入您的應用程式。使用者可以選擇要登入哪個帳戶。
如果沒有可授權的 Google 帳戶,系統應會提示使用者使用任何可用的帳戶登入。如要這麼做,請再次呼叫 API 並將 setFilterByAuthorizedAccounts
設為 false
,提示使用者。進一步瞭解如何註冊。
為回訪使用者啟用自動登入功能 (建議)
開發人員應為使用單一帳戶註冊的使用者啟用自動登入功能。這麼做可提供跨裝置的流暢體驗,尤其是在裝置遷移期間,使用者無須重新輸入憑證,即可快速重新存取帳戶。對於使用者而言,這可在他們先前已登入時,消除不必要的摩擦。
如要啟用自動登入功能,請使用 setAutoSelectEnabled(true)
。只有在符合下列條件時,才能自動登入:
- 只有一個憑證符合要求,可能是 Google 帳戶或密碼,且這項憑證與 Android 裝置上的預設帳戶相符。
- 使用者未明確登出。
- 使用者未在 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()
實作自動登入功能時,請務必正確處理登出程序,以便使用者在明確登出應用程式後,隨時都能選擇正確的帳戶。
設定 Nonce 來提升安全性
為提升登入安全性並避免重送攻擊,請新增 setNonce
,在每項要求中加入 Nonce。進一步瞭解如何產生 Nonce。
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()
建立「使用 Google 帳戶登入」流程
設定「使用 Google 帳戶登入」流程的步驟如下:
- 將
GetCredentialRequest
例項化,然後使用addCredentialOption()
新增先前建立的googleIdOption
,以便擷取憑證。 - 將這項要求傳遞至
getCredential()
(Kotlin) 或getCredentialAsync()
(Java) 呼叫,擷取使用者可用的憑證。 - API 成功後,請擷取保留
GoogleIdTokenCredential
資料結果的CustomCredential
。 CustomCredential
的類型應等於GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
的值。請使用GoogleIdTokenCredential.createFrom
方法,將物件轉換為GoogleIdTokenCredential
。如果轉換成功,請擷取並驗證
GoogleIdTokenCredential
ID,然後在伺服器上驗證憑證。如果轉換作業因
GoogleIdTokenParsingException
失敗,您可能需要更新使用 Google 帳戶登入資料庫的版本。找出所有無法辨識的自訂憑證類型。
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 the ID to validate and
// authenticate on your server.
val googleIdTokenCredential = GoogleIdTokenCredential
.createFrom(credential.data)
// You can use the members of googleIdTokenCredential directly for UX
// purposes, but don't use them to store or control access to user
// data. For that you first need to validate the token:
// pass googleIdTokenCredential.getIdToken() to the backend server.
GoogleIdTokenVerifier verifier = ... // see validation instructions
GoogleIdToken idToken = verifier.verify(idTokenString);
// To get a stable account identifier (e.g. for storing user data),
// use the subject ID:
idToken.getPayload().getSubject()
} 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")
}
}
}
觸發「使用 Google 帳戶登入」按鈕流程
如要觸發「使用 Google 帳戶登入」按鈕流程,請使用 GetSignInWithGoogleOption
(而非 GetGoogleIdOption
):
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder()
.setServerClientId(WEB_CLIENT_ID)
.setNonce(<nonce string to use when generating a Google ID token>)
.build()
請按照以下程式碼範例所述,處理傳回的 GoogleIdTokenCredential
。
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")
}
}
}
將 Google 登入要求例項化後,請採用「使用 Google 帳戶登入」一節所述的類似方式啟動驗證流程。
啟用新使用者的註冊功能 (建議採用)
使用者只要輕觸幾下,就能透過「使用 Google 帳戶登入」功能,在您的應用程式或服務中建立新帳戶。
如果找不到已儲存的憑證 (getGoogleIdOption
不會傳回任何 Google 帳戶),請提示使用者登入。首先,請檢查 setFilterByAuthorizedAccounts(true)
,看看是否有任何先前使用的帳戶。如果找不到任何帳戶,請使用 setFilterByAuthorizedAccounts(false)
提示使用者使用 Google 帳戶註冊
例子:
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(WEB_CLIENT_ID)
.build()
將 Google 註冊要求例項化後,請啟動驗證流程。如果使用者不想使用「使用 Google 帳戶登入」功能註冊,建議您為應用程式進行自動填入功能最佳化。使用者建立帳戶後,建議您將他們加入密碼金鑰,做為建立帳戶的最後步驟。
處理登出
當使用者登出應用程式時,請呼叫 API clearCredentialState()
方法,清除所有憑證提供者的目前使用者憑證狀態。這會通知所有憑證提供者,應清除特定應用程式的任何已儲存憑證工作階段。
憑證提供者可能已儲存有效的憑證工作階段,並使用該工作階段限制日後的 get-credential 呼叫登入選項。舉例來說,系統可能會將有效憑證優先於其他可用的憑證。當使用者明確登出應用程式,並希望在下次登入時取得完整的登入選項時,您應呼叫此 API,讓供應商清除任何儲存的憑證工作階段。