Partager via


Tutoriel : ajouter une fonctionnalité de connexion et de déconnexion dans une application iOS/macOS en utilisant l’authentification native

S’applique à : Cercle vert avec un symbole de coche blanche. iOS (Swift) Cercle vert avec un symbole de coche blanche. macOS (Swift)

Ce tutoriel montre comment connecter et déconnecter un utilisateur dans votre application mobile iOS/macOS 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 apprendre à :

  • 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

Prérequis

Connecter un utilisateur

Pour connecter un utilisateur via le flux Envoyer un code secret à usage unique par e-mail, capturez l’adresse e-mail et envoyez un e-mail contenant un code secret à usage unique pour que l’utilisateur vérifie son e-mail. Lorsque l’utilisateur entre un code secret à usage unique valide, l’application le connecte.

Pour connecter un utilisateur à l’aide du flux Adresse e-mail et mot de passe, capturez l’e-mail et le mot de passe. 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.
    • Collectez un code secret à usage unique par e-mail auprès de l’utilisateur si vous vous connectez avec un code secret à usage unique.
    • Ajoutez un bouton pour permettre à l’utilisateur de renvoyer un code secret à usage unique si vous vous connectez avec l’envoi par e-mail de code secret à usage unique.
  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 :

        @IBAction func signInPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "email not set"
            return
        }
    
        nativeAuth.signIn(username: email, delegate: self)
    }
    

    Pour connecter un utilisateur à l’aide du flux Envoyer par e-mail un code secret à usage unique, nous utilisons l’extrait de code suivant :

    nativeAuth.signIn(username: email, delegate: self)
    

    La méthode signIn(username:delegate), qui répond de manière asynchrone en appelant l’une des méthodes sur l’objet délégué transmis, doit implémenter le protocole SignInStartDelegate. Nous transmettons l’adresse e-mail que l’utilisateur fournit dans le formulaire de soumission par e-mail et transmettons self en tant que délégués.

    Pour connecter un utilisateur à l’aide du flux Adresse e-mail et mot de passe, utilisez les extraits de code suivants :

    nativeAuth.signIn(username: email, password: password, delegate: self)
    

    Dans la méthode signIn(username:password:delegate), vous transmettez l’adresse e-mail que l’utilisateur nous a fournie, son mot de passe et transmettez l’objet délégué conforme au protocole SignInStartDelegate. Pour cet exemple, nous transmettons self.

  3. Pour implémenter le protocole SignInStartDelegate lorsque vous utilisez le flux Envoyer par e-mail un code secret à usage unique, utilisez l’extrait de code suivant :

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCodeRequired(
            newState: MSAL.SignInCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    }
    

    La signIn(username:delegate) entraîne un appel aux méthodes déléguées. Dans le scénario le plus probable, la méthode onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength) est appelée pour indiquer qu’un code a été envoyé pour vérifier l’adresse e-mail de l’utilisateur. Outre les détails de l’emplacement depuis lequel le code a été envoyé et le nombre de chiffres qu’il contient, cette méthode déléguée dispose également d’un newState paramètre de type SignInCodeRequiredState, ce qui nous donne accès aux deux nouvelles méthodes suivantes :

    • submitCode(code:delegate)
    • resendCode(delegate)

    Utilisez la méthode submitCode(code:delegate) pour envoyer le code secret à usage unique fourni par l’utilisateur sous forme de code secret à usage unique, utilisez l’extrait de code suivant :

    newState.submitCode(code: userSuppliedCode, delegate: self)
    

    La submitCode(code:delegate) accepte le mot de passe unique et le paramètre délégué. Après avoir envoyé le code, vous devez vérifier le code secret à usage unique en implémentant le protocole SignInVerifyCodeDelegate.

    Pour implémenter le protocole SignInVerifyCodeDelegate en tant qu’extension de votre classe, utilisez l’extrait de code suivant :

    extension ViewController: SignInVerifyCodeDelegate {
        func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
            resultTextView.text = "Signed in successfully."
            result.getAccessToken(delegate: self)
        }
    }
    

    Dans le scénario le plus courant, nous recevons un appel à onSignInCompleted(result) indiquant que l’utilisateur s’est connecté. Le résultat peut être utilisé pour récupérer access token.

    La méthode getAccessToken(delegate) accepte un paramètre délégué et nous devons implémenter les méthodes requises dans le protocole CredentialsDelegate.

    Dans le scénario le plus courant, nous recevons un appel à onAccessTokenRetrieveCompleted(result) indiquant que l’utilisateur a obtenu un access token.

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    
  4. Pour implémenter le protocole SignInStartDelegate lorsque vous utilisez le flux Adresse e-mail et mot de passe, utilisez l’extrait de code suivant :

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
            // User successfully signed in
        }
    }
    

    Dans le scénario le plus courant, nous recevons un appel à onSignInCompleted(result) indiquant que l’utilisateur s’est connecté. Le résultat peut être utilisé pour récupérer access token.

    La méthode getAccessToken(delegate) accepte un paramètre délégué et nous devons implémenter les méthodes requises dans le protocole CredentialsDelegate.

    Dans le scénario le plus courant, nous recevons un appel à onAccessTokenRetrieveCompleted(result) indiquant que l’utilisateur a obtenu un access token.

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    

Gérer les erreurs de connexion

Lors de la connexion, certaines actions peuvent échouer. Par exemple, l’utilisateur peut tenter de se connecter avec une adresse e-mail qui n’existe pas ou s’il envoie un code non valide.

  1. Pour gérer les erreurs dans la méthode signIn(username) ou signIn(username, password), utilisez l’extrait de code suivant :

    func onSignInStartError(error: MSAL.SignInStartError) {
        if error.isUserNotFound || error.isInvalidUsername {
            resultTextView.text = "Invalid username"
        } else {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    }
    
  2. Pour gérer les erreurs de la méthode submitCode(), utilisez l’extrait de code suivant :

    func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
        if error.isInvalidCode {
            // Inform the user that the submitted code was incorrect and ask for a new code to be supplied
            let userSuppliedCode = retrieveNewCode()
            newState?.submitCode(code: userSuppliedCode, delegate: self)
        } else {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    }
    

    Si l’utilisateur entre un code de vérification d’e-mail incorrect, le gestionnaire d’erreurs inclut une référence à un SignInCodeRequiredState qui peut être utilisé pour envoyer un nouveau code mis à jour. Dans notre implémentation antérieure du protocole SignInVerifyCodeDelegate, nous n’affichions l’erreur que lorsque nous gérions la fonction onSignInVerifyCodeError(error:newState) déléguée.

Lire les revendications de jeton d’ID

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 :

func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
   let claims = result.account.accountClaims
   let preferredUsername = claims?["preferred_username"] as? String
}

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

Découvrez comment ajouter des attributs intégrés et personnalisés aux revendications de jeton, dans l’article Ajouter des attributs utilisateur aux revendications de jeton.

Déconnecter l’utilisateur

Pour déconnecter un utilisateur, utilisez la référence au MSALNativeAuthUserAccountResult que vous avez reçu dans le rappel onSignInCompleted , ou utilisez getNativeAuthUserAccount() pour obtenir un compte connecté à partir du cache et stocker une référence dans la variable membre accountResult.

  1. Configurez le groupe de trousseaux pour votre projet, comme décrit ici.

  2. Ajoutez une nouvelle variable membre à votre ViewController classe : var accountResult: MSALNativeAuthUserAccountResult?.

  3. Mettez à jour viewDidLoad pour récupérer n’importe quel compte mis en cache en ajoutant cette ligne après que nativeAuth soit initialisée correctement : accountResult = nativeAuth.getNativeAuthUserAccount().

  4. Mettez à jour le gestionnaire signInCompleted pour stocker le résultat du compte :

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. Ajoutez un bouton Déconnexion et utilisez le code suivant pour déconnecter l’utilisateur :

    @IBAction func signOutPressed(_: Any) {
        guard let accountResult = accountResult else {
            print("Not currently signed in")
            return
        }
    
        accountResult.signOut()
    
        self.accountResult = nil
    
        resultTextView.text = "Signed out"
    }
    

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. Normalement, vous devriez pouvoir sélectionner le bouton de déconnexion et faire aboutir la déconnexion.

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é.