Linked Account Sign-In enables One Tap Sign In With Google for users that already have their Google Account linked to your service. This improves the experience for users as they can sign in with one click, without re-entering their username and password. It also reduces the chances of users creating duplicate accounts on your service.
Linked Account Sign-In is available as part of the One Tap Sign-In flow for Android. This means you don't need to import a separate library if your app already has the One Tap feature enabled.
In this document, you will learn how to modify your Android app to support Linked Account Sign-In.
How it works
- You opt in to show linked accounts during the One Tap Sign-In flow.
- If the user is signed in on Google and has linked their Google Account with their account on your service, an ID token will be returned for the linked account.
- The user is shown a One Tap sign-in prompt with an option to sign in to your service with their linked account.
- If the user chooses to continue with the linked account, the user's ID token is returned to your app. You match this against the token that was sent to your server in step 2 to identify the logged in user.
Setup
Set up your development environment
Get the latest Google Play services on your development host:
- Open the Android SDK Manager.
Under SDK Tools, find Google Play services.
If the status for these packages is not Installed, select them both and click Install Packages.
Configure your app
In your project-level
build.gradle
file, include Google's Maven repository in both yourbuildscript
andallprojects
sections.buildscript { repositories { google() } } allprojects { repositories { google() } }
Add the dependencies for the "Link with Google" API to your module's app-level gradle file, which is usually
app/build.gradle
:dependencies { implementation 'com.google.android.gms:play-services-auth:21.3.0' }
Modify your Android app to support Linked Account Sign-In
At the end of the Linked Account Sign-In flow, an ID token is returned to your app. The ID token's integrity should be verified before signing the user in.
The following code sample details the steps to retrieve, verify the ID token, and subsequently sign the user in.
Create an activity to receive the result of the Sign-In intent
Kotlin
private val activityResultLauncher = registerForActivityResult( ActivityResultContracts.StartIntentSenderForResult()) { result -> if (result.resultCode == RESULT_OK) { try { val signInCredentials = Identity.signInClient(this) .signInCredentialFromIntent(result.data) // Review the Verify the integrity of the ID token section for // details on how to verify the ID token verifyIdToken(signInCredential.googleIdToken) } catch (e: ApiException) { Log.e(TAG, "Sign-in failed with error code:", e) } } else { Log.e(TAG, "Sign-in failed") } }
Java
private final ActivityResultLauncher<IntentSenderResult> activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), result -> { If (result.getResultCode() == RESULT_OK) { try { SignInCredential signInCredential = Identity.getSignInClient(this) .getSignInCredentialFromIntent(result.getData()); verifyIdToken(signInCredential.getGoogleIdToken()); } catch (e: ApiException ) { Log.e(TAG, "Sign-in failed with error:", e) } } else { Log.e(TAG, "Sign-in failed") } });
Build the sign in request
Kotlin
private val tokenRequestOptions = GoogleIdTokenRequestOptions.Builder() .supported(true) // Your server's client ID, not your Android client ID. .serverClientId(getString("your-server-client-id") .filterByAuthorizedAccounts(true) .associateLinkedAccounts("service-id-of-and-defined-by-developer", scopes) .build()
Java
private final GoogleIdTokenRequestOptions tokenRequestOptions = GoogleIdTokenRequestOptions.Builder() .setSupported(true) .setServerClientId("your-service-client-id") .setFilterByAuthorizedAccounts(true) .associateLinkedAccounts("service-id-of-and-defined-by-developer", scopes) .build()
Launch the Sign-In Pending intent
Kotlin
Identity.signInClient(this) .beginSignIn( BeginSignInRequest.Builder() .googleIdTokenRequestOptions(tokenRequestOptions) .build()) .addOnSuccessListener{result -> activityResultLauncher.launch(result.pendingIntent.intentSender) } .addOnFailureListener {e -> Log.e(TAG, "Sign-in failed because:", e) }
Java
Identity.getSignInClient(this) .beginSignIn( BeginSignInRequest.Builder() .setGoogleIdTokenRequestOptions(tokenRequestOptions) .build()) .addOnSuccessListener(result -> { activityResultLauncher.launch( result.getPendingIntent().getIntentSender()); }) .addOnFailureListener(e -> { Log.e(TAG, "Sign-in failed because:", e); });
Verify the integrity of the ID token
Use a Google API Client Library
Using the Java Google API Client Library is the recommended way to validate Google ID tokens in a production environment.
Java
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
...
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
// Specify the CLIENT_ID of the app that accesses the backend:
.setAudience(Collections.singletonList(CLIENT_ID))
// Or, if multiple clients access the backend:
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
.build();
// (Receive idTokenString by HTTPS POST)
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken != null) {
Payload payload = idToken.getPayload();
// Print user identifier
String userId = payload.getSubject();
System.out.println("User ID: " + userId);
// Get profile information from payload
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
// Use or store profile information
// ...
} else {
System.out.println("Invalid ID token.");
}
The GoogleIdTokenVerifier.verify()
method verifies the JWT signature, the
aud
claim, the iss
claim, and themexp
claim.
If you need to validate that the ID token represents a Google Workspace or Cloud
organization account, you can verify the hd
claim by checking the domain name
returned by the Payload.getHostedDomain()
method.