This guide describes how to implement Sign in with Google and covers the following steps:
- Add dependencies to your app.
- Instantiate
CredentialManager. - Create the bottom sheet flow.
- Create the button flow.
- Handle the sign-in response.
- Handle errors.
- Handle sign-out.
Add dependencies to your app
In your module's build.gradle file, declare dependencies using the latest
version of Credential Manager, Play Services Auth, and
googleid:
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>" }
Instantiate Credential Manager
Use your app or activity context to create a CredentialManager object.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
Create the bottom sheet flow
The bottom sheet is Credential Manager's inbuilt UI. Using this UI creates a consistent experience across all authentication methods, such as passwords, passkeys, and Sign in with Google.
Configure the sign-in request for previously authorized accounts
Attempt a Google sign-in request with GetGoogleIdOption to
retrieve the user's Google ID Token.
The following snippets check if the account is an authorized account.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(WEB_CLIENT_ID)
.setAutoSelectEnabled(true)
.setNonce(generateSecureRandomNonce())
.build()
The request googleIdOption object is configured as follows:
Filter previously authorized accounts: To retrieve the authorized accounts that have previously been used to sign in to your app, set
setFilterByAuthorizedAccountstotrue.Note that the default value for
setFilterByAuthorizedAccountsistrue, implying that the default behavior for the bottom sheet UI is to display only previously authorized accounts.Set the server client ID: Set the
setServerClientIdparameter. ThewebClientIdis the Web Client ID you set up for OAuth in your Google Cloud Project while completing the prerequisites.Enable Automatic Sign-in (optional): To enable Automatic Sign-in for returning users, use
setAutoSelectEnabled(true)andsetFilterByAuthorizedAccounts(true). For your app users, this removes unnecessary friction if they were already previously signed in.Automatic Sign-in is only possible when the following criteria are met:
- There is only a single authorized account on the device and that authorized account was previously used to sign into the app on the device. Multiple authorized accounts on the device disable automatic sign-in.
- The user has not explicitly signed out of the app during their previous session.
- The user hasn't disabled Automatic Sign-in in their Google Account settings.
Set a nonce (optional): To enable enhanced security, set a nonce for server-side verification. To prevent replay attacks, you can include a nonce for server-side verification with
setNonce(). Ensure that your server-side code validates that the request and response nonces are identical.To generate the nonce, use a function similar to the following function that generates a cryptographically strong random nonce of a specified length and encodes it using
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)
}
Request sign-in
Check if the user has an authorized account on the device by calling the
getCredential method:
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
}
}
Configure the sign-in request if no authorized accounts are available
If there are no authorized users for your app on the device, CredentialManager
returns a NoCredentialException. In this scenario, disable the authorized
accounts filter so that the user can use another account to sign up.
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(WEB_CLIENT_ID)
.setNonce(generateSecureRandomNonce())
.build()
Next, request sign-in similarly to how you did for authorized accounts.
Create the button flow
Use a button if you want users to be able to Sign in with Google for the following conditions:
- The user dismissed the Credential Manager bottom sheet UI.
- There are no Google Accounts on the device.
- The existing accounts on the device require reauthentication.
Create the button UI
While this can be done with a Jetpack Compose button, you can use a preapproved brand icon from the Sign in with Google Branding Guidelines page.
Create the sign-in flow
Create a Google sign-in request with
GetSignInWithGoogleOption to retrieve a Google ID Token.
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
.build()
Next, request sign-in similarly to how you did for the bottom sheet UI.
Create the shared sign in function for the bottom sheet and button
To handle the sign-in, complete the following steps:
- Use CredentialManager's
getCredential()function. If the response is successful, extract theCustomCredential, which should be of typeGoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL. Convert the object into a
GoogleIdTokenCredentialusing theGoogleIdTokenCredential.createFrom()method.Validate the credential on your relying party server.
Make sure that you handle errors appropriately.
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")
}
}
}
Handle errors
Review the errors listed in Troubleshooting to ensure your code handles all the possible error scenarios.
Handle sign-out
It is important to provide a mechanism for your users to sign out of your app. For example, a user might have multiple Google Accounts on the device and decide to sign in from a different account. You can provide this in your, for example, settings page.
A credential provider might store an active credential session and use it to limit sign-in options for future sign-in requests. For example, it can prioritize the active credential over any other available credential.
When a user signs out of your app, call the API clearCredentialState()
method to clear the current user credential state from all credential providers.
This will notify all credential providers that any stored credential session for
the given app should be cleared, providing users with full sign-in options the
next time.