Connecter les utilisateurs avec leurs identifiants enregistrés

Utilisez le client de connexion One Tap pour demander l'autorisation à l'utilisateur de récupérer l'un des identifiants qu'il avait déjà utilisés pour se connecter à votre application. Ces identifiants peuvent correspondre à un compte Google ou à une combinaison nom d'utilisateur/mot de passe enregistrée avec Google via Chrome, la saisie automatique Android ou Smart Lock pour les mots de passe.

Interface de connexion en un geste

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

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

Où dois-je utiliser la connexion One Tap ?

Si votre application nécessite que les utilisateurs se connectent, affichez l'interface utilisateur One Tap sur l'écran de connexion. Cela peut être utile même si vous avez déjà un bouton "Se connecter avec Google". En effet, comme l'interface utilisateur One Tap peut être configurée pour n'afficher que les identifiants que l'utilisateur avait l'habitude de se connecter, elle peut rappeler aux utilisateurs qui se connectent rarement la dernière fois qu'ils se sont connectés, et les empêcher de créer accidentellement de nouveaux comptes avec votre application.

Si la connexion est facultative pour votre application, envisagez d'utiliser la connexion One Tap sur tous les écrans dotés d'une expérience améliorée en vous connectant. Par exemple, si les utilisateurs peuvent parcourir le contenu avec votre application sans être connectés, mais ne peuvent publier des commentaires ou ajouter des articles à un panier qu'après s'être connectés, il s'agit d'un contexte logique pour la connexion en un geste.

Pour les raisons indiquées ci-dessus, les applications facultatives doivent également utiliser la connexion One Tap sur l'écran de connexion.

Avant de commencer

1. Configurer le client de connexion One Tap

Vous pouvez configurer le client de connexion One Tap pour connecter les utilisateurs avec des mots de passe, des comptes Google enregistrés ou les deux. Nous vous recommandons d'activer les deux afin d'activer la création de compte en un geste pour les nouveaux utilisateurs et la connexion automatique ou en un geste pour autant d'utilisateurs connus que possible.

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

Si votre application utilise Google Sign-In, utilisez setGoogleIdTokenRequestOptions() pour activer et configurer les requêtes de jeton 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 filtrer par compte autorisé. Lorsque vous activez cette option, le client One Tap ne invite les utilisateurs qu'à 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 disposent déjà d'un compte ou le compte Google qu'ils ont utilisé, et les empêcher de créer accidentellement des comptes avec votre application.

  • Si vous souhaitez connecter les utilisateurs automatiquement lorsque cela est possible, activez la fonctionnalité avec setAutoSelectEnabled(). La connexion automatique est possible lorsque les critères suivants sont remplis:

    • L'utilisateur a un seul identifiant enregistré pour votre application, c'est-à-dire un mot de passe ou un compte Google enregistré.
    • L'utilisateur n'a pas désactivé la connexion automatique dans les paramètres de son compte Google.
  • Bien que facultatif, nous vous recommandons vivement d'utiliser un nonce pour améliorer la sécurité de connexion et éviter les attaques par relecture. Utilisez setNonce pour inclure un nonce dans chaque requête. Pour en savoir plus sur la génération d'un nonce, consultez la section Obtenir un nonce de SafetyNet.

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. Rechercher un utilisateur connecté

Si votre activité peut être utilisée par un utilisateur connecté ou déconnecté, vérifiez l'état de l'utilisateur avant d'afficher l'interface utilisateur de connexion avec One Tap.

Vous devez également savoir si l'utilisateur a déjà refusé d'utiliser la connexion avec One Tap en fermant l'invite ou en appuyant dessus. Il peut s'agir d'une simple propriété booléenne de votre activité. (Reportez-vous à la section Arrêter d'afficher l'interface utilisateur One Tap ci-dessous.)

3. Afficher l'interface utilisateur de connexion avec One Tap

Si l'utilisateur n'est pas connecté et qu'il n'a pas déjà refusé l'utilisation de la connexion One Tap, appelez la méthode beginSignIn() de l'objet client et associez des écouteurs à l'objet Task renvoyé. Les applications le font généralement dans la méthode onCreate() de Activity ou après une transition d'écran lorsqu'elles utilisent une architecture à activité unique.

Le client One Tap appelle l'écouteur de réussite si l'utilisateur dispose d'identifiants enregistrés pour votre application. Dans l'écouteur de réussite, récupérez l'intent en attente à partir du résultat Task et transmettez-le à startIntentSenderForResult() pour démarrer l'interface utilisateur de connexion avec One Tap.

Si l'utilisateur n'a pas d'identifiants enregistrés, le client One Tap appelle l'écouteur d'échec. Dans ce cas, aucune action n'est requise de votre part: vous pouvez continuer à présenter l'application lorsque vous êtes déconnecté. Toutefois, si vous proposez l'inscription en un seul geste, vous pouvez lancer cette procédure pour créer facilement votre compte. Consultez Créer des comptes d'un simple 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 en un geste sera signalée à votre application à l'aide de la méthode onActivityResult() de votre activité. Si l'utilisateur a choisi de se connecter, les identifiants associés seront enregistrés. Si l'utilisateur a refusé de se connecter, en fermant l'interface utilisateur One Tap ou en appuyant en dehors de celle-ci, le résultat affiche le code RESULT_CANCELED. Votre application doit gérer ces deux possibilités.

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

Si l'utilisateur a choisi de partager les 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 ont une propriété googleIdToken non nulle si l'utilisateur a partagé les identifiants d'un 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 nom d'utilisateur/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 fournis manuellement.
  • Si les identifiants du 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 relecture, vérifiez la valeur de 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) {
                    // ...
                }
            }
        }
    }
    // ...
}

Ne plus afficher l'interface utilisateur One Tap

Si l'utilisateur a refusé de se connecter, l'appel de getSignInCredentialFromIntent() génère une erreur ApiException avec un code d'état CommonStatusCodes.CANCELED. Dans ce cas, vous devez désactiver temporairement l'interface utilisateur de connexion avec One Tap pour que les utilisateurs n'aient pas à répéter des invites. Pour ce faire, l'exemple suivant met en œuvre une propriété sur l'activité, qui permet de déterminer si l'utilisateur peut se connecter en un seul geste. Toutefois, vous pouvez également enregistrer une valeur dans SharedPreferences ou utiliser une autre méthode.

Il est important de définir vous-même la limitation du débit des invites de connexion avec One Tap. Si un utilisateur annule plusieurs invites de suite, le client One Tap ne le demandera pas pendant 24 heures.

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 des 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 vos comptes Google. Découvrez comment utiliser ces jetons sur le backend.

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