Connecter les utilisateurs avec leurs identifiants enregistrés

Utilisez le client de connexion avec One Tap 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 avec Google à l'aide de la saisie automatique Chrome, Android ou 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 UI n'est présentée et vous pouvez fournir votre expérience normale en mode déconnecté.

Où 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". En effet, l'UI One Tap peut être configurée pour n'afficher que les identifiants que l'utilisateur a déjà utilisés pour se connecter. Elle peut ainsi rappeler aux utilisateurs qui se connectent rarement comment ils se sont connectés la dernière fois 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 avec One Tap sur n'importe quel écran 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 sont déconnectés, mais ne peuvent publier des commentaires ou ajouter des articles à un panier qu'après s'être connectés, cela constitue un contexte approprié pour la connexion avec One Tap.

Les applications avec connexion facultative doivent également utiliser la connexion avec One Tap sur leurs écrans de connexion, pour les raisons mentionné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 que les utilisateurs se connectent avec des mots de passe enregistrés, des comptes Google enregistrés ou les deux. (Il est recommandé de prendre en charge les deux pour permettre aux nouveaux utilisateurs de créer un compte en un clic et aux utilisateurs connus de se connecter automatiquement ou en un clic.)

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 jeton d'identité Google :

  • Définissez l'ID client du serveur sur l'ID que vous avez créé dans la console Google APIs. 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 des comptes Google qu'ils ont déjà utilisés. Cela peut aider les utilisateurs à se connecter correctement lorsqu'ils ne savent pas s'ils ont déjà un compte ou quel compte Google ils ont utilisé. Cela les empêche également de créer accidentellement de nouveaux 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 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 relecture. Utilisez setNonce pour inclure un nonce dans chaque requête. Pour obtenir des suggestions et plus d'informations 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. Vérifier si un utilisateur est connecté

Si votre Activity peut être utilisée par un utilisateur connecté ou déconnecté, vérifiez l'état de l'utilisateur avant d'afficher l'UI 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 en dehors de celle-ci. Il peut s'agir d'une simple propriété booléenne de votre activité. (Consultez Arrêter d'afficher l'UI One Tap ci-dessous.)

3. Afficher l'UI de connexion avec One Tap

Si l'utilisateur n'est pas connecté et n'a pas encore refusé d'utiliser la connexion en un clic, appelez la méthode beginSignIn() de l'objet client et associez des écouteurs à l'objet 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 appellera l'écouteur de réussite si l'utilisateur a des 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'UI de connexion avec One Tap.

Si l'utilisateur n'a 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 déconnectée de l'application. 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 d'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 One Tap sera communiquée à votre application à l'aide de la méthode onActivityResult() de votre Activity. Si l'utilisateur a choisi de se connecter, le résultat sera un identifiant enregistré. Si l'utilisateur refuse de se connecter, soit en fermant l'UI One Tap, soit en appuyant en dehors de celle-ci, le résultat renverra 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 ses 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. L'identifiant aura une propriété googleIdToken non nulle si l'utilisateur a partagé un identifiant 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-la pour vous connecter de la même manière que si l'utilisateur l'avait fournie manuellement.
  • Si les identifiants du compte Google ont été récupérés, utilisez le jeton d'identité 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 la réponse sur votre serveur backend. Consultez S'authentifier auprès d'un backend à l'aide de jetons d'identité.

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érera une ApiException avec un code d'état CommonStatusCodes.CANCELED. Dans ce cas, vous devez désactiver temporairement l'UI de connexion avec One Tap pour ne pas ennuyer vos utilisateurs avec des invites répétées. L'exemple suivant y parvient en définissant une propriété sur l'Activity, qu'il 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 mettre en œuvre votre propre limitation du débit des invites de connexion avec One Tap. Si vous ne le faites pas et qu'un utilisateur annule plusieurs invites 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 connecte à nouveau.

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 Play Services 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'identité Google qui représentent les comptes Google de vos utilisateurs. Découvrez comment utiliser ces jetons sur le 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.