Partager via


Tutoriel : ajouter une fonctionnalité de connexion dans une application Android en utilisant l’authentification native

S’applique à : cercle vert avec un symbole de coche blanc qui indique que le contenu suivant s’applique aux locataires externes. Locataires externes (en savoir plus)

Ce tutoriel montre comment connecter et déconnecter un utilisateur dans votre application mobile Android avec un code secret à usage unique envoyé par e-mail ou un nom d’utilisateur et un mot de passe en utilisant l’authentification native.

Dans ce tutoriel, vous allez :

  • Connecter un utilisateur avec un code secret à usage unique envoyé par e-mail ou un nom d’utilisateur (e-mail) et un mot de passe.
  • Déconnecter un utilisateur.
  • Gérer l’erreur de connexion

Conditions préalables

Se connecter en tant qu'utilisateur

Pour connecter un utilisateur en utilisant le code secret à usage unique, collectez son e-mail, puis envoyez-lui un e-mail contenant un code secret à usage unique pour lui permettre de confirmer son e-mail. Lorsque l’utilisateur entre un code secret à usage unique valide, l’application le connecte.

Pour connecter un utilisateur en utilisant le nom d’utilisateur (e-mail) et le mot de passe, collectez l’e-mail et le mot de passe de l’utilisateur. Si le nom d’utilisateur et le mot de passe sont valides, l’application connecte l’utilisateur.

Pour connecter un utilisateur, vous devez :

  1. Créer une interface utilisateur pour :

    • Collecter une adresse e-mail de l’utilisateur. Ajouter une validation à vos entrées pour vérifier que l’utilisateur entre une adresse e-mail valide.
    • Collecter un mot de passe si vous vous inscrivez avec un nom d’utilisateur (e-mail) et un mot de passe.
    • Récupérez un code d'accès à usage unique par e-mail auprès de l'utilisateur si vous vous connectez avec un code d'accès à usage unique par e-mail.
    • Renvoyez un code secret à usage unique (recommandé) si vous vous connectez avec un code secret à usage unique par e-mail.
  2. Dans votre IU, ajoutez un bouton dont l’événement de sélection démarre une connexion, comme indiqué dans l’extrait de code suivant :

     CoroutineScope(Dispatchers.Main).launch {
         val parameters = NativeAuthSignInParameters(username = email)
         // Assign 'password' param if you sign in with username (email) and password
         // parameters.password = password
         val actionResult: SignInResult = authClient.signIn(parameters)
    
         if (actionResult is SignInResult.CodeRequired) {
             val nextState = actionResult.nextState
             val submitCodeActionResult = nextState.submitCode(
                 code = code
             )
             if (submitCodeActionResult is SignInResult.Complete) {
                 // Handle sign in success
                 val accountState = submitCodeActionResult.resultValue
    
                 val getAccessTokenParameters = NativeAuthGetAccessTokenParameters()
                 val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters)
    
                 if (accessTokenResult is GetAccessTokenResult.Complete) {
                     val accessToken = accessTokenResult.resultValue.accessToken
                     val idToken = accountState.getIdToken()
                 }
             }
         }
     }
    

    Si l’utilisateur n’est pas obligé de soumettre un code secret, par exemple lorsqu’il se connecte avec une adresse e-mail et un mot de passe, utilisez l’extrait de code suivant :

    CoroutineScope(Dispatchers.Main).launch {
        val parameters = NativeAuthSignInParameters(username = email)
        parameters.password = password
        val actionResult: SignInResult = authClient.signIn(parameters)
    
        if (actionResult is SignInResult.Complete) -> {
            // Handle sign in success
            val accountState = actionResult.resultValue
    
            val getAccessTokenParameters = NativeAuthGetAccessTokenParameters()
            val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters)
    
            if (accessTokenResult is GetAccessTokenResult.Complete) {
                val accessToken = accessTokenResult.resultValue.accessToken
                val idToken = accountState.getIdToken()
            }
        }
    }
    
    • Pour démarrer le flux de connexion, utilisez la méthode signIn(parameters) du Kit de développement logiciel (SDK).
    • Instance de la classe NativeAuthSignInParameters contenant le username qui est l’adresse e-mail que vous collectez auprès de l’utilisateur.
    • Si la méthode de connexion nécessite un nom d’utilisateur (e-mail) et un mot de passe, le paramètre de la méthode, password, est alors le mot de passe que vous collectez auprès de l’utilisateur.
    • Dans le scénario le plus courant, le signIn(parameters) retourne un résultat, SignInResult.CodeRequired, ce qui indique que le SDK attend que l’application envoie le code secret à usage unique envoyé à l’adresse e-mail de l’utilisateur.
    • L’objet SignInResult.CodeRequired contient une référence au nouvel état, que nous pouvons récupérer via actionResult.nextState.
    • Le nouvel état nous donne accès à deux nouvelles méthodes :
      • submitCode() soumet le code secret à usage unique envoyé par e-mail que l’application collecte auprès de l’utilisateur.
      • resendCode() renvoie le code secret à usage unique envoyé par e-mail si l’utilisateur ne reçoit pas le code.

Gérer les erreurs de connexion

Pendant la connexion, toutes les actions n’aboutissent pas. Par exemple, c’est le cas si l’utilisateur tente de se connecter avec une adresse e-mail qui n’existe pas ou s’il envoie un code non valide.

Gérer les erreurs au début du processus de connexion

Pour gérer les erreurs dans la méthode signIn(parameters), utilisez l’extrait de code suivant :

 val parameters = NativeAuthSignInParameters(username = email)
 // Assign 'password' param if you sign in with username (email) and password
 // parameters.password = password
val actionResult: SignInResult = authClient.signIn(parameters)

if (actionResult is SignInResult.CodeRequired) {
    // Next step: submit code
} else if (actionResult is SignInError) {
    // Handle sign in errors
    when {
         actionResult.isUserNotFound() -> {
             // Handle "user not found" error
         }
         actionResult.isAuthNotSupported() -> {
             // Handle "authentication type not support" error
         }
         actionResult.isInvalidCredentials() -> {
             // Handle specific errors
         }
         else -> {
             // Handle other errors
         }
     }
}
  • SignInError indique un résultat d’action infructueux, retourné par signIn(parameters). Le résultat de l’action n’inclut donc pas de référence au nouvel état.
  • Si actionResult is SignUpError, le kit Android SDK fournit des méthodes utilitaires qui vous permettent d’analyser les erreurs spécifiques de manière plus détaillée :
    • La méthode isUserNotFound() vérifie si l’utilisateur se connecte avec un nom d’utilisateur (adresse e-mail) qui n’existe pas.
    • La méthode isBrowserRequired() vérifie si un navigateur (secours web) est nécessaire pour effectuer le flux d’authentification. Ce scénario se produit quand l’authentification native n’est pas suffisante pour effectuer le flux d’authentification. Par exemple, un administrateur configure l’adresse e-mail et le mot de passe en tant que méthode d’authentification, mais l’application ne parvient pas à envoyer password en tant que type de demande, ou ne le prend tout simplement pas en charge. Suivez les étapes décrites dans Prise en charge du secours web dans l’application Android pour gérer ce scénario quand il se produit.
    • La méthode isAuthNotSupported() vérifie si l’application envoie un type de demande que Microsoft Entra ne prend pas en charge, c’est-à-dire une valeur de type de demande autre que oob et password. Découvrez plus en détail les types de demandes.
    • Pour une connexion par nom d’utilisateur (e-mail) et mot de passe, la méthode isInvalidCredentials() vérifie si la combinaison nom d’utilisateur et mot de passe est incorrecte.

Gérer les erreurs liées au code soumis

Pour gérer les erreurs de la méthode submitCode(), utilisez l’extrait de code suivant :

val submitCodeActionResult = nextState.submitCode(
    code = code
)
if (submitCodeActionResult is SignInResult.Complete) {
    // Sign in flow complete, handle success state.
} else if (submitCodeActionResult is SubmitCodeError && submitCodeActionResult.isInvalidCode()) {
    // Handle "invalid code" error
}
  • L’erreur SubmitCodeError indique un résultat d’action infructueux, retourné par submitCode(). Le résultat de l’action n’inclut donc pas de référence au nouvel état.
  • isInvalidCode() vérifie l’erreur spécifique. Dans ce cas, la référence à l’état précédent doit être utilisée pour effectuer de nouveau l’action.

Pour récupérer le nouveau code secret à usage unique envoyé par e-mail, utilisez l’extrait de code suivant :

val submitCodeActionResult = nextState.submitCode(
    code = code
)
if (submitCodeActionResult is SignInError && submitCodeActionResult.isInvalidCode) {
    // Inform the user that the submitted code was incorrect or invalid, then ask them to input a new email one-time passcode
    val newCode = retrieveNewCode()
    nextState.submitCode(
        code = newCode
    )
}

Vous avez mené à bien toutes les étapes nécessaires pour connecter correctement un utilisateur sur votre application. Créez et exécutez votre application. En principe, vous devez pouvoir fournir une adresse e-mail, recevoir un code à cette adresse et utiliser ce code pour connecter l’utilisateur.

Lire les revendications de jeton d'identification

Une fois que votre application a acquis un jeton d’ID, vous pouvez récupérer les revendications associées au compte actif. Pour ce faire, utilisez l’extrait de code suivant.

val preferredUsername = accountState.getClaims()?.get("preferred_username")
val city = accountState.getClaims()?.get("City")
val givenName = accountState.getClaims()?.get("given_name")
//custom attribute
val loyaltyNumber = accountState.getClaims()?.get("loyaltyNumber")

La clé que vous utilisez pour accéder à la valeur de revendication est le nom que vous spécifiez lorsque vous ajoutez l'attribut utilisateur en tant que revendication de jeton.

Pour savoir comment ajouter des attributs intégrés et personnalisés aux revendications de jeton, consultez l’article Ajouter des attributs utilisateur aux revendications de jeton.

Déconnecter un utilisateur

Pour déconnecter un utilisateur, vous devez supprimer le compte stocké dans le cache.

  1. Créez votre interface utilisateur (IU) personnalisé comprenant :

    • Un bouton de déconnexion que l’utilisateur sélectionne pour envoyer une demande de déconnexion.
  2. Pour déconnecter un utilisateur, utilisez le code suivant :

    private fun performSignOut(accountState: AccountState) {
         CoroutineScope(Dispatchers.Main).launch {
             val accountResult = authClient.getCurrentAccount()
             if (accountResult is GetAccountResult.AccountFound) {
                 val signOutResult = accountResult.resultValue.signOut()
                 if (signOutResult is SignOutResult.Complete) {
                     // Show sign out successful UI
                 }
             }
         }
     }
    

Gérer les erreurs de déconnexion

La déconnexion doit se dérouler sans erreur. Si des erreurs se produisent, inspectez le résultat de l’erreur à l’aide de l’extrait de code suivant :

val actionResult = accountResult.signOut()
if (actionResult is SignOutResult.Complete) {
    // Show sign out successful UI
} else {
    // Handle errors
}

Veillez à inclure les instructions import. Android Studio devrait inclure automatiquement les instructions d'importation pour vous.

Vous avez mené à bien toutes les étapes nécessaires pour déconnecter correctement un utilisateur sur votre application. Créez et exécutez votre application. Si tout va bien, vous devriez pouvoir sélectionner le bouton de déconnexion pour vous déconnecter avec succès.

Configurer un fournisseur de revendications personnalisé

Si vous souhaitez ajouter des revendications à partir d’un système externe au jeton émis pour votre application, utilisez un fournisseur de revendications personnalisé. Un fournisseur de revendications personnalisé est constitué d’une extension d’authentification personnalisée qui appelle une API REST externe pour récupérer des revendications provenant de systèmes externes.

Suivez les étapes détaillées dans Configurer un fournisseur de revendications personnalisé pour ajouter des revendications à partir d’un système externe dans vos jetons de sécurité.

Activer la connexion avec un alias ou un nom d’utilisateur

Vous pouvez autoriser les utilisateurs qui se connectent avec une adresse e-mail et un mot de passe à se connecter avec un nom d’utilisateur et un mot de passe. Le nom d'utilisateur, également connu sous le nom d'identifiant de connexion alternatif, peut être un ID client, un numéro de compte ou un autre identifiant que vous choisissez d'utiliser comme nom d'utilisateur.

Vous pouvez affecter manuellement des noms d’utilisateur au compte d’utilisateur via le Centre d’administration Microsoft Entra ou l’automatiser dans votre application via l’API Microsoft Graph.

Utilisez les étapes de connexion avec un alias ou un nom d’utilisateur pour permettre à vos utilisateurs de se connecter en utilisant un nom d'utilisateur dans votre application:

  1. Activez le nom d’utilisateur dans la connexion.
  2. Créez des utilisateurs avec un nom d’utilisateur dans le Centre d’administration ou mettez à jour les utilisateurs existants en ajoutant un nom d’utilisateur. Vous pouvez également automatiser la création et la mise à jour des utilisateurs dans votre application à l’aide de l’API Microsoft Graph.