Partager via


Tutoriel : réinitialisation de mot de passe en libre-service dans l’application iOS/macOS

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 permettre aux utilisateurs de changer ou de réinitialiser leur mot de passe, sans intervention d’un administrateur ou du support technique.

Dans ce tutoriel, vous allez apprendre à :

  • Ajoutez la réinitialisation de mot de passe en libre-service.
  • Gérer les erreurs.

Prérequis

Réinitialiser le mot de passe

Pour réinitialiser le mot de passe d’un utilisateur existant, nous devons valider l’adresse e-mail à l’aide d’un mot de passe à usage unique (OTP).

  1. Pour valider l’e-mail, nous appelons la méthode resetPassword(username:delegate) à partir de l’instance du Kit de développement logiciel (SDK) à l’aide de l’extrait de code suivant :

    nativeAuth.resetPassword(username: email, delegate: self)
    
  2. Pour implémenter le protocole ResetPasswordStartDelegate en tant qu’extension de notre classe, utilisez l’extrait de code suivant :

    extension ViewController: ResetPasswordStartDelegate {
        func onResetPasswordCodeRequired(
            newState: MSAL.ResetPasswordCodeRequiredState,
            sentTo: String,
            channelTargetType: MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    
        func onResetPasswordStartError(error: MSAL.ResetPasswordStartError) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    }
    

    L’appel à resetPassword(username:delegate) entraîne un appel à la méthode déléguée onResetPasswordCodeRequired() ou onResetPasswordStartError().

    Dans le scénario le plus probable, la méthode onResetPasswordCodeRequired(newState:sentTo:channelTargetType:codeLength) sera 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 paramètre newState de type ResetPasswordCodeRequiredState, ce qui nous donne accès à deux nouvelles méthodes :

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

    Pour soumettre le code que l’utilisateur nous a fourni, utilisez :

    newState.submitCode(code: userSuppliedCode, delegate: self)
    
  3. Pour vérifier le code envoyé, commencez par implémenter le protocole ResetPasswordVerifyCodeDelegate en tant qu’extension à votre classe à l’aide de l’extrait de code suivant :

    extension ViewController: ResetPasswordVerifyCodeDelegate {
    
        func onResetPasswordVerifyCodeError(
            error: MSAL.VerifyCodeError,
            newState: MSAL.ResetPasswordCodeRequiredState?
        ) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    
        func onPasswordRequired(newState: MSAL.ResetPasswordRequiredState) {
            // use newState instance to submit the new password
        }
    }
    

    Dans le scénario le plus courant, nous recevons un appel à onPasswordRequired(newState) indiquant que nous pouvons fournir le nouveau mot de passe à l’aide de l’instance newState .

    newState.submitPassword(password: newPassword, delegate: self)
    
  4. Pour implémenter le protocole ResetPasswordRequiredDelegate en tant qu’extension de notre classe, utilisez l’extrait de code suivant :

    extension ViewController: ResetPasswordRequiredDelegate {
    
        func onResetPasswordRequiredError(
            error: MSAL.PasswordRequiredError,
            newState: MSAL.ResetPasswordRequiredState?
        ) {
            resultTextView.text = "Error submitting new password: \(error.errorDescription ?? "no description")"
        }
    
        func onResetPasswordCompleted(newState: SignInAfterResetPasswordState) {
            resultTextView.text = "Password reset completed"
        }
    }
    

    Dans le scénario le plus courant, nous recevons un appel à onResetPasswordCompleted(newState) indiquant que le flux de réinitialisation de mot de passe est terminé.

Gérer les erreurs

Dans notre implémentation antérieure du protocole ResetPasswordStartDelegate, nous affichions l’erreur lorsque nous gérions la fonction onResetPasswordStartError(error) déléguée.

Nous pouvons améliorer l’expérience utilisateur en gérant le type d’erreur spécifique comme suit :

func onResetPasswordStartError(error: MSAL.ResetPasswordStartError) {
    if error.isInvalidUsername {
        resultTextView.text = "Invalid username"
    } else if error.isUserNotFound {
        resultTextView.text = "User not found"
    } else if error.isUserDoesNotHavePassword {
        resultTextView.text = "User is not registered with a password"
    } else {
        resultTextView.text = "Error during reset password flow in: \(error.errorDescription ?? "no description")"
    }
}

Gérer les erreurs avec des états

Certaines erreurs incluent une référence à un nouvel état. Par exemple, si l’utilisateur entre un code de vérification d’e-mail incorrect, le gestionnaire d’erreurs inclut une référence à un ResetPasswordCodeRequiredState qui peut être utilisé pour envoyer un nouveau code de vérification.

Dans notre implémentation précédente du protocole ResetPasswordVerifyCodeDelegate, nous n’affichions l’erreur que lorsque nous gérions la fonction onResetPasswordError(error:newState) déléguée.

Nous pouvons améliorer l’expérience utilisateur en demandant à l’utilisateur d’entrer le code approprié et de le soumettre de nouveau comme suit :

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

Un autre exemple où le gestionnaire d’erreurs inclut une référence à un nouvel état est lorsque l’utilisateur entre un mot de passe non valide. Dans ce cas, le gestionnaire d’erreurs inclut une référence à un ResetPasswordRequiredState qui peut être utilisé pour envoyer un nouveau mot de passe. Voici un exemple :

func onResetPasswordRequiredError(
    error: MSAL.PasswordRequiredError,
    newState: MSAL.ResetPasswordRequiredState?
) {
    if error.isInvalidPassword {
        // Inform the user that the submitted password was invalid and ask for a new password to be supplied.
        let newPassword = retrieveNewPassword()
        newState?.submitPassword(password: newPassword, delegate: self)
    } else {
        resultTextView.text = "Error submitting password: \(error.errorDescription ?? "no description")"
    }
}

Se connecter après la réinitialisation du mot de passe

Le kit de développement logiciel (SDK) permet aux développeurs de connecter un utilisateur après avoir réinitialisé leur mot de passe, sans avoir à fournir le nom d’utilisateur ou à vérifier l’adresse e-mail via un code secret à usage unique.

Pour connecter un utilisateur après une réinitialisation de mot de passe réussie, utilisez la méthode signIn(delegate) à partir du nouvel état SignInAfterResetPasswordState retourné dans la fonction onResetPasswordCompleted(newState) :

extension ViewController: ResetPasswordRequiredDelegate {

    func onResetPasswordRequiredError(
        error: MSAL.PasswordRequiredError,
        newState: MSAL.ResetPasswordRequiredState?
    ) {
        resultTextView.text = "Error submitting new password: \(error.errorDescription ?? "no description")"
    }

    func onResetPasswordCompleted() {
        resultTextView.text = "Password reset completed"
        newState.signIn(delegate: self)
    }
}

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

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.

extension ViewController: SignInAfterSignUpDelegate {
    func onSignInAfterSignUpError(error: SignInAfterSignUpError) {
        resultTextView.text = "Error signing in after password reset"
    }

    func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
        // User successfully signed in
        result.getAccessToken(delegate: self)
    }
}

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)"
    }
}

Étape suivante