Connexion au compte associé pour Android

La connexion avec le compte associé active la fonctionnalité Se connecter avec One Tap avec Google pour les utilisateurs qui ont déjà associé leur compte Google à votre service. Les utilisateurs peuvent ainsi se connecter en un clic, sans avoir à saisir à nouveau leur nom d'utilisateur ni leur mot de passe. Cela réduit également le risque que des utilisateurs créent des comptes en double sur votre service.

La connexion au compte associé est disponible avec le parcours de connexion One Tap pour Android. Cela signifie que vous n'avez pas besoin d'importer une bibliothèque distincte si la fonctionnalité One Tap est déjà activée pour votre application.

Dans ce document, vous découvrirez comment modifier votre application Android pour qu'elle accepte la connexion via un compte associé.

Fonctionnement

  1. Vous activez l'affichage des comptes associés pendant le parcours de connexion avec One Tap.
  2. Si l'utilisateur est connecté sur Google et qu'il a associé son compte Google à son compte sur votre service, nous vous envoyons un jeton d'ID pour le compte associé.
  3. L'utilisateur voit une invite de connexion avec One Tap lui permettant de se connecter à votre service avec son compte associé.
  4. Si l'utilisateur choisit de poursuivre avec le compte associé, le jeton d'ID de l'utilisateur est renvoyé à votre application. Vous devez faire correspondre ce jeton à celui envoyé à votre serveur à l'étape 2 pour identifier l'utilisateur connecté.

Configuration

Configurer l'environnement de développement

Obtenez les derniers services Google Play sur votre hôte de développement:

  1. Ouvrez Android SDK Manager.
  1. Sous SDK Tools, recherchez Google Play services (Services Google Play).

  2. Si ces packages ne sont pas installés, sélectionnez-les tous les deux et cliquez sur Install Packages (Installer les packages).

Configurer votre application

  1. Dans le fichier build.gradle au niveau du projet, incluez le dépôt Maven de Google dans les sections buildscript et allprojects.

    buildscript {
        repositories {
            google()
        }
    }
    
    allprojects {
        repositories {
            google()
        }
    }
    
  2. Ajoutez les dépendances de l'API "Link with Google" au fichier Gradle au niveau de l'application de votre module, qui est généralement app/build.gradle:

    dependencies {
      implementation 'com.google.android.gms:play-services-auth:20.7.0'
    }
    

Modifier votre application Android pour qu'elle prenne en charge la connexion au compte associé

À la fin du flux de connexion au compte associé, un jeton d'ID est renvoyé à votre application. L'intégrité du jeton doit être vérifiée avant la connexion de l'utilisateur.

L'exemple de code ci-dessous détaille les étapes à suivre pour récupérer le jeton d'ID et connecter l'utilisateur.

  1. Créer une activité pour recevoir le résultat de l'intent Sign-In

    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”)
        }
    });
    
  2. Créer la demande de connexion

    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()
    
  3. Lancer l'intent "Sign-In Pending" (Connexion en attente)

    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);
    });
    

Vérifier l'intégrité du jeton d'ID

To verify that the token is valid, ensure that the following criteria are satisfied:

  • The ID token is properly signed by Google. Use Google's public keys (available in JWK or PEM format) to verify the token's signature. These keys are regularly rotated; examine the Cache-Control header in the response to determine when you should retrieve them again.
  • The value of aud in the ID token is equal to one of your app's client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app's backend server.
  • The value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
  • The expiry time (exp) of the ID token has not passed.
  • If you want to restrict access to only members of your G Suite domain, verify that the ID token has an hd claim that matches your G Suite domain name.

Rather than writing your own code to perform these verification steps, we strongly recommend using a Google API client library for your platform, or a general-purpose JWT library. For development and debugging, you can call our tokeninfo validation endpoint.

Utiliser une bibliothèque cliente des API Google

Il est recommandé d'utiliser la bibliothèque cliente des API Google pour Java pour valider les jetons d'ID Google dans un environnement de production.

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.");
  }

La méthode GoogleIdTokenVerifier.verify() valide la signature du jeton JWT, la revendication aud, la revendication iss et la revendication exp.

Si vous souhaitez restreindre l'accès aux seuls membres de votre domaine G Suite, vérifiez également la revendication hd en vérifiant le nom de domaine renvoyé par la méthode Payload.getHostedDomain().

Calling the tokeninfo endpoint

An easy way to validate an ID token signature for debugging is to use the tokeninfo endpoint. Calling this endpoint involves an additional network request that does most of the validation for you while you test proper validation and payload extraction in your own code. It is not suitable for use in production code as requests may be throttled or otherwise subject to intermittent errors.

To validate an ID token using the tokeninfo endpoint, make an HTTPS POST or GET request to the endpoint, and pass your ID token in the id_token parameter. For example, to validate the token "XYZ123", make the following GET request:

https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123

If the token is properly signed and the iss and exp claims have the expected values, you will get a HTTP 200 response, where the body contains the JSON-formatted ID token claims. Here's an example response:

{
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "testuser@gmail.com",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

If you are a G Suite customer, you might also be interested in the hd claim, which indicates the hosted domain of the user. This can be used to restrict access to a resource to only members of certain domains. The absence of this claim indicates that the user does not belong to a G Suite hosted domain.