Connexion à un compte associé pour Android

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

La connexion à un compte associé est disponible dans le cadre du 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 à un compte associé.

Fonctionnement

  1. Vous choisissez d'afficher les comptes associés pendant la procédure de connexion One Tap.
  2. Si l'utilisateur est connecté sur Google et a associé son compte Google à son compte sur votre service, un jeton d'ID est renvoyé pour le compte associé.
  3. L'utilisateur reçoit une invite de connexion One Tap avec une option lui permettant de se connecter à votre service avec son compte associé.
  4. Si l'utilisateur choisit de continuer avec le compte associé, son jeton d'ID est renvoyé à votre application. Vous le comparez au jeton envoyé à votre serveur à l'étape 2 pour identifier l'utilisateur connecté.

Préparation

Configurer l'environnement de développement

Installez 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.

  2. Si l'état de ces packages n'est pas installé, sélectionnez-les 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 de votre module, qui est généralement app/build.gradle:

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

Modifier votre application Android pour qu'elle soit compatible avec la connexion à un compte associé

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

L'exemple de code suivant détaille les étapes à suivre pour récupérer, vérifier le jeton d'ID, puis 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"

    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

Pour vérifier que le jeton est valide, assurez-vous que les critères suivants sont remplis:

  • Le jeton d'ID est correctement signé par Google. Utilisez les clés publiques de Google (disponibles au format JWK ou PEM) pour vérifier la signature du jeton. Ces clés sont régulièrement alternées. Examinez l'en-tête Cache-Control dans la réponse pour déterminer quand vous devez les récupérer à nouveau.
  • La valeur de aud dans le jeton d'ID est égale à l'un des ID client de votre application. Cette vérification est nécessaire pour éviter que les jetons d'identification émis pour une application malveillante soient utilisés pour accéder aux données du même utilisateur sur le serveur backend de votre application.
  • La valeur de iss dans le jeton d'ID est égale à accounts.google.com ou https://accounts.google.com.
  • Le délai d'expiration (exp) du jeton d'ID n'a pas été dépassé.
  • Si vous devez vérifier que le jeton d'ID représente un compte d'organisation Google Workspace ou Cloud, vous pouvez vérifier la revendication hd, qui indique le domaine hébergé de l'utilisateur. Cette clé doit être utilisée lorsque vous restreignez l'accès à une ressource aux seuls membres de certains domaines. L'absence de cette revendication indique que le compte n'appartient pas à un domaine hébergé par Google.

Plutôt que d'écrire votre propre code pour effectuer ces étapes de validation, nous vous recommandons vivement d'utiliser une bibliothèque cliente de l'API Google pour votre plate-forme ou une bibliothèque JWT à usage général. Pour le développement et le débogage, vous pouvez appeler notre point de terminaison de validation tokeninfo.

Utiliser une bibliothèque cliente des API Google

L'utilisation de la bibliothèque cliente des API Google pour Java est la méthode recommandée 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 JWT, les revendications aud et iss, ainsi que la revendication exp.

Si vous devez confirmer que le jeton d'ID représente un compte d'organisation Google Workspace ou Cloud, vous pouvez valider la revendication hd en vérifiant le nom de domaine renvoyé par la méthode Payload.getHostedDomain().

Appeler le point de terminaison tokeninfo

Un moyen simple de valider une signature de jeton d'ID pour le débogage consiste à utiliser le point de terminaison tokeninfo. L'appel de ce point de terminaison implique une requête réseau supplémentaire qui effectue la majeure partie de la validation pendant que vous testez la validation et l'extraction de la charge utile appropriées dans votre propre code. Il n'est pas adapté à l'utilisation dans le code de production, car les requêtes peuvent être limitées ou soumises à des erreurs intermittentes.

Pour valider un jeton d'ID à l'aide du point de terminaison tokeninfo, envoyez une requête HTTPS POST ou GET au point de terminaison, puis transmettez votre jeton d'ID dans le paramètre id_token. Par exemple, pour valider le jeton "XYZ123", envoyez la requête GET suivante:

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

Si le jeton est correctement signé et que les revendications iss et exp ont les valeurs attendues, vous obtiendrez une réponse HTTP 200, dont le corps contient les revendications de jeton d'ID au format JSON. Voici un exemple de réponse :

{
 // 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"
}

Si vous devez vérifier que le jeton d'ID représente un compte Google Workspace, vous pouvez vérifier la revendication hd, qui indique le domaine hébergé de l'utilisateur. Cette clé doit être utilisée lorsque vous restreignez l'accès à une ressource aux seuls membres de certains domaines. L'absence de cette revendication indique que le compte n'appartient pas à un domaine hébergé par Google Workspace.