Connecter les utilisateurs avec leurs identifiants enregistrés

Utilisez le client de connexion en un clic pour demander à l'utilisateur l'autorisation de récupérer l'un des identifiants qu'il a précédemment utilisés pour se connecter à votre application. Ces identifiants peuvent être un compte Google ou une combinaison nom d'utilisateur/mot de passe qu'il a enregistrée auprès de Google à l'aide de Chrome, de la saisie automatique Android ou de Smart Lock pour les mots de passe.

Interface utilisateur de la connexion en un clic

Une fois les identifiants récupérés, vous pouvez les utiliser pour connecter l'utilisateur à votre application sans friction.

Si l'utilisateur n'a enregistré aucun identifiant, aucune interface utilisateur n'est présentée, et vous pouvez fournir votre expérience normale de déconnexion.

Dans quel cas dois-je utiliser la connexion avec One Tap ?

Si votre application nécessite que les utilisateurs se connectent, affichez l'UI One Tap sur votre écran de connexion. Cela peut être utile même si vous disposez déjà d'un bouton "Se connecter avec Google" : comme l'interface utilisateur One Tap peut être configurée pour n'afficher que les identifiants que l'utilisateur utilisait précédemment pour se connecter, elle peut servir de rappel aux utilisateurs qui se connectent rarement à la façon dont ils se sont connectés la dernière fois et les empêcher de créer accidentellement des comptes avec votre application.

Si la connexion est facultative pour votre application, envisagez d'utiliser la connexion avec One Tap sur tous les écrans dont l'expérience est améliorée par la connexion. Par exemple, si les utilisateurs peuvent parcourir du contenu avec votre application lorsqu'ils ne sont pas connectés, mais qu'ils ne peuvent publier des commentaires ou ajouter des articles à un panier qu'après s'être connectés, il s'agit d'un contexte approprié pour la connexion en un seul geste.

Les applications facultatives de connexion doivent également utiliser la connexion avec One Tap sur leurs écrans de connexion, pour les raisons indiquées ci-dessus.

Avant de commencer

1. Configurer le client de connexion avec One Tap

Vous pouvez configurer le client de connexion avec One Tap pour qu'il connecte les utilisateurs avec des mots de passe ou des comptes Google enregistrés, ou les deux. (Nous vous recommandons de prendre en charge les deux options pour permettre la création de compte en un seul geste pour les nouveaux utilisateurs et la connexion automatique ou en un seul geste pour autant d'utilisateurs que possible.)

Si votre application utilise la connexion par mot de passe, utilisez setPasswordRequestOptions() pour activer les requêtes d'identifiants par mot de passe.

Si votre application utilise Google Sign-In, utilisez setGoogleIdTokenRequestOptions() pour activer et configurer les requêtes de jetons d'ID Google:

  • Définissez l'ID client du serveur sur l'ID que vous avez créé dans la console des API Google. Notez qu'il s'agit de l'ID client de votre serveur, et non de votre ID client Android.

  • Configurez le client pour qu'il filtre les comptes autorisés. Lorsque vous activez cette option, le client One Tap invite uniquement les utilisateurs à se connecter à votre application avec les comptes Google qu'ils ont déjà utilisés. Cela peut aider les utilisateurs à se connecter lorsqu'ils ne savent pas s'ils ont déjà un compte ou quel compte Google ils ont utilisé, et les empêche de créer accidentellement des comptes avec votre application.

  • Si vous souhaitez que les utilisateurs soient connectés automatiquement lorsque cela est possible, activez la fonctionnalité avec setAutoSelectEnabled(). La connexion automatique est possible lorsque les conditions suivantes sont remplies:

    • L'utilisateur ne dispose que d'un seul identifiant enregistré pour votre application. Autrement dit, un mot de passe ou un compte Google enregistré.
    • L'utilisateur n'a pas désactivé la connexion automatique dans les paramètres de compte Google.
  • Bien que facultatif, nous vous recommandons vivement d'utiliser un nonce pour améliorer la sécurité de la connexion et éviter les attaques par rejeu. Utilisez setNonce pour inclure un nonce dans chaque requête. Consultez la section Obtenir un nonce de SafetyNet pour obtenir des suggestions et des informations supplémentaires sur la génération d'un nonce.

Java

public class YourActivity extends AppCompatActivity {
  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signInRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signInRequest = BeginSignInRequest.builder()
              .setPasswordRequestOptions(PasswordRequestOptions.builder()
                      .setSupported(true)
                      .build())
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.default_web_client_id))
                      // Only show accounts previously used to sign in.
                      .setFilterByAuthorizedAccounts(true)
                      .build())
              // Automatically sign in when exactly one credential is retrieved.
              .setAutoSelectEnabled(true)
              .build();
      // ...
  }
  // ...
}

Kotlin

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signInRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signInRequest = BeginSignInRequest.builder()
            .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder()
                .setSupported(true)
                .build())
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Only show accounts previously used to sign in.
                    .setFilterByAuthorizedAccounts(true)
                    .build())
            // Automatically sign in when exactly one credential is retrieved.
            .setAutoSelectEnabled(true)
            .build()
        // ...
    }
    // ...
}

2. Vérifier si un utilisateur est connecté

Si votre activité peut être utilisée par un utilisateur connecté ou déconnecté, vérifiez son état avant d'afficher l'UI de connexion en un seul geste.

Vous devez également vérifier si l'utilisateur a déjà refusé d'utiliser la connexion en un seul geste en fermant l'invite ou en appuyant en dehors de celle-ci. Il peut s'agir d'une propriété booléenne de votre activité. (voir Arrêter l'affichage de l'UI One Tap ci-dessous) ;

3. Afficher l'UI de connexion avec One Tap

Si l'utilisateur n'est pas connecté et qu'il n'a pas encore refusé d'utiliser la connexion en un seul geste, appelez la méthode beginSignIn() de l'objet client et associez des écouteurs à l'Task qu'il renvoie. Les applications le font généralement dans la méthode onCreate() de l'activité ou après les transitions d'écran lorsque vous utilisez une architecture à activité unique.

Le client One Tap appelle l'écouteur de succès si l'utilisateur a enregistré des identifiants pour votre application. Dans l'écouteur de succès, obtenez l'intent en attente à partir du résultat Task et transmettez-le à startIntentSenderForResult() pour démarrer l'UI de connexion One Tap.

Si l'utilisateur ne dispose d'aucun identifiant enregistré, le client One Tap appelle l'écouteur d'échec. Dans ce cas, aucune action n'est nécessaire: vous pouvez simplement continuer à présenter l'expérience de l'application lorsque l'utilisateur n'est pas connecté. Toutefois, si vous acceptez l'inscription en un clic, vous pouvez démarrer ce flux ici pour une expérience de création de compte fluide. Consultez Créer des comptes en un seul geste.

Java

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No saved credentials found. Launch the One Tap sign-up flow, or
                // do nothing and continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Kotlin

oneTapClient.beginSignIn(signInRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0, null)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No saved credentials found. Launch the One Tap sign-up flow, or
        // do nothing and continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. Gérer la réponse de l'utilisateur

La réponse de l'utilisateur à l'invite de connexion avec un seul geste sera transmise à votre application à l'aide de la méthode onActivityResult() de votre activité. Si l'utilisateur a choisi de se connecter, les identifiants sont enregistrés. Si l'utilisateur a refusé de se connecter, en fermant l'UI One Tap ou en appuyant en dehors de celle-ci, le résultat est renvoyé avec le code RESULT_CANCELED. Votre application doit gérer les deux possibilités.

Se connecter avec les identifiants récupérés

Si l'utilisateur a choisi de partager des identifiants avec votre application, vous pouvez les récupérer en transmettant les données d'intent de onActivityResult() à la méthode getSignInCredentialFromIntent() du client One Tap. Les identifiants comportent une propriété googleIdToken non nulle si l'utilisateur a partagé des identifiants de compte Google avec votre application, ou une propriété password non nulle si l'utilisateur a partagé un mot de passe enregistré.

Utilisez les identifiants pour vous authentifier auprès du backend de votre application.

  • Si une paire de nom d'utilisateur et de mot de passe a été récupérée, utilisez-la pour vous connecter de la même manière que si l'utilisateur les avait fournies manuellement.
  • Si des identifiants de compte Google ont été récupérés, utilisez le jeton d'ID pour vous authentifier auprès de votre backend. Si vous avez choisi d'utiliser un nonce pour éviter les attaques par rejeu, vérifiez la valeur de la réponse sur votre serveur backend. Consultez la section S'authentifier auprès d'un backend à l'aide de jetons d'ID.

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  String username = credential.getId();
                  String password = credential.getPassword();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  } else if (password != null) {
                      // Got a saved username and password. Use them to authenticate
                      // with your backend.
                      Log.d(TAG, "Got password.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    val username = credential.id
                    val password = credential.password
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        password != null -> {
                            // Got a saved username and password. Use them to authenticate
                            // with your backend.
                            Log.d(TAG, "Got password.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token or password!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
                }
            }
        }
    }
    // ...
}

Arrêter d'afficher l'UI One Tap

Si l'utilisateur a refusé de se connecter, l'appel à getSignInCredentialFromIntent() génère une ApiException avec un code d'état CommonStatusCodes.CANCELED. Dans ce cas, vous devez désactiver temporairement l'UI de connexion en un seul geste pour ne pas ennuyer vos utilisateurs avec des invites répétées. L'exemple suivant permet d'y parvenir en définissant une propriété sur l'activité, qu'il utilise pour déterminer s'il doit proposer à l'utilisateur la connexion en un seul geste. Toutefois, vous pouvez également enregistrer une valeur dans SharedPreferences ou utiliser une autre méthode.

Il est important d'implémenter votre propre limitation de débit pour les invites de connexion en un seul geste. Si vous ne le faites pas et qu'un utilisateur annule plusieurs requêtes de suite, le client One Tap ne l'invitera pas pendant les 24 heures suivantes.

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

5. Gérer la déconnexion

Lorsqu'un utilisateur se déconnecte de votre application, appelez la méthode signOut() du client One Tap. L'appel de signOut() désactive la connexion automatique jusqu'à ce que l'utilisateur se reconnecte.

Même si vous n'utilisez pas la connexion automatique, cette étape est importante, car elle garantit que lorsque les utilisateurs se déconnectent de votre application, l'état d'authentification de toutes les API de services Play que vous utilisez est également réinitialisé.

Étapes suivantes

Si vous avez configuré le client One Tap pour récupérer les identifiants Google, votre application peut désormais obtenir des jetons d'ID Google représentant les comptes Google de vos utilisateurs. Découvrez comment utiliser ces jetons côté backend.

Si vous acceptez Google Sign-In, vous pouvez également utiliser le client One Tap pour ajouter des flux de création de compte fluides à votre application.