
This document explains how to migrate the Sign In With Google bottom sheet dialog from Google Identity Services (GIS) to the Credentials Manager API using the Google ID helper library.
An app that uses the Credential Manager API is configured to present the end user with a consistent Android user interface that allows the user to select from a list of saved sign-in options, including passkey-enabled accounts. This is the recommended Android API for consolidating different credential types and providers. As of Android 14, users can also leverage 3rd party password managers with the Credential Manager API.
Declare dependencies
In your module's build.gradle
file, declare a dependency using the latest
version of googleid
:
implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
Follow the instructions to set up your Google API console project. Replace the guidance on including dependencies with the instructions mentioned above.
Instantiate a Google sign-in request
To begin your implementation, instantiate a Google sign-in request. Use
GetGoogleIdOption
to retrieve a user's Google ID Token.
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();
You should first call the API with the setFilterByAuthorizedAccounts
parameter
set to true
. If there are no credentials available, then call the API again
and set setFilterByAuthorizedAccounts
to false
.
If you want to sign users in automatically when possible, enable the feature
with setAutoSelectEnabled
in your GetGoogleIdOption
request. Automatic sign
in is possible when the following criteria are met:
- The user has exactly one credential saved for your app. That is, one saved password or one saved Google Account.
- The user hasn't disabled automatic sign-in in their Google Account settings.
To improve sign-in security and avoid replay attacks, use
setNonce
to include a nonce in each request.
Learn more about generating a 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();
Sign in with Google
The steps to set up a Sign in with Google flow are as follows:
- Instantiate the
GetCredentialRequest
and add thegoogleIdOption
created above to retrieve the credentials. - Pass this request to
getCredential()
(Kotlin) orgetCredentialAsync()
(Java) call to retrieve the user's available credentials. - Once the API is successful, extract the
CustomCredential
which holds the result forGoogleIdTokenCredential
data. - The
CustomCredential
's type should be equal to the value ofGoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
. Convert the object into aGoogleIdTokenCredential
using theGoogleIdTokenCredential.createFrom
method. - If the conversion succeeds, extract the
GoogleIdTokenCredential
's ID, validate it, and authenticate the credential on your server. - If the conversion fails with a
GoogleIdTokenParsingException
, then you may need to update your Sign in with Google library version. - Catch any unrecognized custom credential types.
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 onSuccess(GetCredentialResponse result) {
handleSignIn(result);
}
@Override
public void onFailure(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");
}
}
Sign In With Google button
The Sign In With Google Button is supported by Credential Manager with the
newest Google ID helper library. To trigger the Sign In With Google button flow,
use the GetSignInWithGoogleOption
instead of GetGoogleIdOption
,
and handle the returned GoogleIdTokenCredential
the same way as before.
Sign up with Google
If no results are returned after setting setFilterByAuthorizedAccounts
to
true
while instantiating GetGoogleIdOption
request and passing to
GetCredentialsRequest
, it indicates that there are no authorized accounts to
sign in. At this point, you should set setFilterByAuthorizedAccounts(false)
and call Sign up with 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();
Once you instantiate the Google sign up request , launch the authentication flow in a similar manner as mentioned in the Sign in with Google section.
Handle sign out
When a user signs out of your app, call the API clearCredentialState()
method to clear the current user credential state and reset the internal state
of sign-in.