Connecter les utilisateurs avec leurs identifiants enregistrés

Utilisez le client de connexion One Tap pour demander à l'utilisateur l'autorisation de récupérer l'un des identifiants 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 avec Google à l'aide de Chrome, de la saisie automatique Android ou de Smart Lock pour les mots de passe.

UI 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 UI ne s'affiche, et vous pouvez lui offrir une expérience normale hors connexion.

Où dois-je utiliser la connexion avec One Tap ?

Si votre application nécessite que les utilisateurs se connectent, affichez l'interface utilisateur 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", car l'UI One Tap peut être configurée pour n'afficher que les identifiants précédemment utilisés par l'utilisateur pour se connecter. Cela peut constituer un rappel pour les utilisateurs qui se connectent de façon peu fréquente lors de leur dernière connexion, ce qui les empêche 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 exemple, si les utilisateurs peuvent parcourir le contenu de votre application lorsqu'ils sont déconnectés, mais qu'ils ne peuvent publier des commentaires ou ajouter des articles à un panier qu'après s'être connectés, cela constitue un contexte judicieux pour la connexion avec One Tap.

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

Avant de commencer

1. Configurer le client de connexion One Tap

Vous pouvez configurer le client de connexion One Tap pour que les utilisateurs se connectent avec des mots de passe ou des comptes Google enregistrés, ou l'un de ces deux éléments. Nous vous recommandons d'utiliser les deux options pour permettre la création de compte en un seul geste pour les nouveaux utilisateurs et la connexion automatique ou d'un simple geste pour autant d'utilisateurs connus que possible.

Si votre application utilise la connexion par mot de passe, utilisez setPasswordRequestOptions() pour activer les demandes d'identifiants de 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 filtrer par compte autorisé. 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 s'ils ne savent pas s'ils possèdent 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 critères suivants sont remplis:

    • 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 cela soit 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 la présence d'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 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 à l'extérieur de celle-ci. Il peut s'agir d'une simple propriété booléenne de votre activité. (voir la section Arrêter d'afficher l'interface utilisateur de One Tap ci-dessous).

3. Afficher l'interface de connexion avec One Tap

Si l'utilisateur n'est pas connecté et n'a pas déjà refusé d'utiliser la connexion avec One Tap, appelez la méthode beginSignIn() de l'objet client et associez des écouteurs au 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 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 cet écouteur, récupérez l'intent en attente à partir du résultat Task et transmettez-le à startIntentSenderForResult() pour démarrer l'interface utilisateur de connexion One Tap.

Si l'utilisateur n'a pas enregistré d'identifiants, le client One Tap appelle l'écouteur d'échec. Dans ce cas, aucune action n'est requise. Vous pouvez simplement continuer à présenter l'expérience de l'application déconnectée. Toutefois, si vous proposez l'inscription avec One Tap, vous pouvez commencer cette procédure ici pour créer facilement un compte. 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 One Tap sera transmise à votre application à l'aide de la méthode onActivityResult() de votre activité. Si l'utilisateur a choisi de se connecter, les identifiants seront enregistrés. Si l'utilisateur a refusé de se connecter, soit en fermant l'interface utilisateur One Tap, soit en appuyant en dehors de celle-ci, le résultat est renvoyé avec 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 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 auront 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 nom d'utilisateur/mot de passe a été récupérée, utilisez-les pour vous connecter de la même manière que si l'utilisateur les avait fournies 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 rejeu, vérifiez la valeur de la réponse sur votre serveur backend. Consultez S'authentifier avec 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 de One Tap

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

Il est important de limiter le débit des invites de connexion One Tap. Si vous ne le faites pas et que l'utilisateur annule plusieurs invites d'affilée, le client One Tap n'affichera pas d'invite pendant les prochaines 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. En appelant le signOut(), vous désactivez 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 qui représentent les comptes Google de vos utilisateurs. Découvrez comment utiliser ces jetons sur le backend.

Si vous êtes compatible avec Google Sign-In, vous pouvez également utiliser le client One Tap pour ajouter des processus simples de création de compte à votre application.