Implémenter Se connecter avec Google

Ce guide explique comment implémenter la fonctionnalité Se connecter avec Google et couvre les étapes suivantes :

  • Ajoutez des dépendances à votre application.
  • Instanciez CredentialManager.
  • Créez le flux de la bottom sheet.
  • Créez le flux du bouton.
  • Gérez la réponse de connexion.
  • Gérer les erreurs.
  • Gérer la déconnexion

Ajouter des dépendances à votre application

Dans le fichier build.gradle de votre module, déclarez des dépendances à l'aide de la dernière version de Credential Manager, Play Services Auth et googleid :

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha02")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02")
    implementation("com.google.android.libraries.identity.googleid:googleid:<latest version>")
}

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha02"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02"
    implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}

Instancier Credential Manager

Utilisez le contexte de votre application ou de votre activité pour créer un objet CredentialManager.

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

Créer le flux de la bottom sheet

La bottom sheet est l'UI intégrée de Credential Manager. Cette UI offre une expérience cohérente pour toutes les méthodes d'authentification, telles que les mots de passe, les clés d'accès et Se connecter avec Google.

Configurer la demande de connexion pour les comptes précédemment autorisés

Tentez d'envoyer une requête de connexion Google avec GetGoogleIdOption pour récupérer le jeton d'ID Google de l'utilisateur.

Les extraits suivants vérifient si le compte est un compte autorisé.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(true)
    .setServerClientId(WEB_CLIENT_ID)
    .setAutoSelectEnabled(true)
    .setNonce(generateSecureRandomNonce())
    .build()

L'objet de requête googleIdOption est configuré comme suit :

  • Filtrer les comptes précédemment autorisés : pour récupérer les comptes autorisés qui ont déjà été utilisés pour se connecter à votre application, définissez setFilterByAuthorizedAccounts sur true.

    Notez que la valeur par défaut de setFilterByAuthorizedAccounts est true, ce qui signifie que le comportement par défaut de l'interface utilisateur de la bottom sheet consiste à n'afficher que les comptes précédemment autorisés.

  • Définissez l'ID client du serveur : définissez le paramètre setServerClientId. webClientId est l'ID client Web que vous avez configuré pour OAuth dans votre projet Google Cloud lors de l'exécution des conditions préalables.

  • Activer la connexion automatique (facultatif) : pour activer la connexion automatique pour les utilisateurs connus, utilisez setAutoSelectEnabled(true) et setFilterByAuthorizedAccounts(true). Pour les utilisateurs de votre application, cela évite les frictions inutiles s'ils étaient déjà connectés.

    La connexion automatique n'est possible que lorsque les conditions suivantes sont remplies :

    • Il n'y a qu'un seul compte autorisé sur l'appareil, et ce compte autorisé a déjà été utilisé pour se connecter à l'application sur l'appareil. La présence de plusieurs comptes autorisés sur l'appareil désactive la connexion automatique.
    • L'utilisateur ne s'est pas explicitement déconnecté de l'application lors de sa session précédente.
    • L'utilisateur n'a pas désactivé la connexion automatique dans les paramètres de son compte Google.
  • Définir un nonce (facultatif) : pour renforcer la sécurité, définissez un nonce pour la validation côté serveur. Pour éviter les attaques par rejeu, vous pouvez inclure un nonce pour la validation côté serveur avec setNonce(). Assurez-vous que votre code côté serveur valide que les nonces de requête et de réponse sont identiques.

    Pour générer le nonce, utilisez une fonction semblable à la suivante, qui génère un nonce aléatoire sécurisé d'une longueur spécifiée et l'encode à l'aide de Base64 :

fun generateSecureRandomNonce(byteLength: Int = 32): String {
    val randomBytes = ByteArray(byteLength)
    SecureRandom().nextBytes(randomBytes)
    return Base64.encodeToString(randomBytes, Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING)
}

Demander une connexion

Vérifiez si l'utilisateur dispose d'un compte autorisé sur l'appareil en appelant la méthode getCredential :

val request: GetCredentialRequest = GetCredentialRequest.Builder()
    .addCredentialOption(googleIdOption)
    .build()

// Use an activity-based context to avoid undefined system UI
// launching behavior.
val mutableContext = MutableContextWrapper(activityContext)
coroutineScope {
    try {
        val result = credentialManager.getCredential(
            request = request,            
            context = mutableContext // Use MutableContextWrapper to avoid memory leak during configuration changes
        )
        handleSignIn(result)
    } catch (e: GetCredentialException) {
        // Handle failures
    }
}

Configurer la demande de connexion si aucun compte autorisé n'est disponible

Si aucun utilisateur n'est autorisé à accéder à votre application sur l'appareil, CredentialManager renvoie NoCredentialException. Dans ce cas, désactivez le filtre des comptes autorisés pour que l'utilisateur puisse s'inscrire avec un autre compte.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
    .setFilterByAuthorizedAccounts(false)
    .setServerClientId(WEB_CLIENT_ID)
    .setNonce(generateSecureRandomNonce())
    .build()

Ensuite, demandez la connexion de la même manière que pour les comptes autorisés.

Créer le flux du bouton

Utilisez un bouton si vous souhaitez que les utilisateurs puissent se connecter avec Google dans les conditions suivantes :

  • L'utilisateur a fermé l'UI de la bottom sheet de Credential Manager.
  • Aucun compte Google n'est enregistré sur l'appareil.
  • Les comptes existants sur l'appareil nécessitent une réauthentification.

Créer l'UI du bouton

Bien que cela soit possible avec un bouton Jetpack Compose, vous pouvez utiliser une icône de marque préapprouvée de la page Consignes relatives à la marque Se connecter avec Google.

Créer le flux de connexion

Créez une demande de connexion Google avec GetSignInWithGoogleOption pour récupérer un jeton d'ID Google.

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
    serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
    .build()

Ensuite, demandez la connexion de la même manière que pour l'UI de la bottom sheet.

Créer la fonction de connexion partagée pour la bottom sheet et le bouton

Pour gérer la connexion, procédez comme suit :

  1. Utilisez la fonction getCredential() de CredentialManager. Si la réponse est positive, extrayez CustomCredential, qui doit être de type GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.
  2. Convertissez l'objet en GoogleIdTokenCredential à l'aide de la méthode GoogleIdTokenCredential.createFrom().

  3. Validez l'identifiant sur votre serveur de partie de confiance.

  4. Assurez-vous de gérer les erreurs de manière appropriée.

fun handleSign(result: GetCredentialResponse) {
    // Handle the successfully returned credential.
    val credential = result.credential

    when (credential) {
        is CustomCredential -> {
            if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
                try {
                    // Use googleIdTokenCredential and extract the ID for server-side validation.
                    val googleIdTokenCredential = GoogleIdTokenCredential
                        .createFrom(credential.data)
                } catch (e: GoogleIdTokenParsingException) {
                    Log.e(TAG, "Received an invalid google id token response", e)
                }
            } else {
                // Catch any unrecognized credential type here.
                Log.e(TAG, "Unexpected type of credential")
            }
        }

        else -> {
            // Catch any unrecognized credential type here.
            Log.e(TAG, "Unexpected type of credential")
        }
    }
}

Gérer les erreurs

Passez en revue les erreurs listées dans Dépannage pour vous assurer que votre code gère tous les scénarios d'erreur possibles.

Gérer la déconnexion

Il est important de fournir un mécanisme permettant à vos utilisateurs de se déconnecter de votre application. Par exemple, un utilisateur peut avoir plusieurs comptes Google sur l'appareil et décider de se connecter à partir d'un autre compte. Vous pouvez l'indiquer, par exemple, sur la page des paramètres.

Un fournisseur d'identifiants peut stocker une session d'identifiants active et l'utiliser pour limiter les options de connexion pour les futures demandes de connexion. Par exemple, il peut donner la priorité aux identifiants actifs par rapport à tous les autres identifiants disponibles.

Lorsqu'un utilisateur se déconnecte de votre application, appelez la méthode clearCredentialState() de l'API pour effacer l'état actuel des identifiants utilisateur de tous les fournisseurs d'identifiants. Tous les fournisseurs d'identifiants seront alors informés que toute session d'identifiants stockée pour l'application donnée doit être effacée, ce qui permettra aux utilisateurs de disposer de toutes les options de connexion la prochaine fois.