Udostępnij za pośrednictwem


Samouczek: samoobsługowe resetowanie hasła w aplikacji systemu iOS/macOS

Dotyczy: Biały okrąg z szarym symbolem X. Dzierżawcy Workforce Zielony okrąg z białym znakiem wyboru. Najemcy zewnętrzni (dowiedzieć się więcej)

W tym samouczku pokazano, jak zapewnić użytkownikom możliwość zmiany lub zresetowania hasła bez udziału administratora ani działu pomocy technicznej.

W tym samouczku nauczysz się następujących rzeczy:

  • Dodaj samoobsługowe resetowanie hasła.
  • Zajmij się błędami.

Warunki wstępne

Resetowanie hasła

Aby zresetować hasło istniejącego użytkownika, musimy zweryfikować adres e-mail przy użyciu jednorazowego kodu dostępu (OTP).

  1. Aby zweryfikować wiadomość e-mail, wywołujemy metodę resetPassword(parameters:delegate) z wystąpienia zestawu SDK przy użyciu następującego fragmentu kodu:

    let parameters = MSALNativeAuthResetPasswordParameters(username: email)
    nativeAuth.resetPassword(parameters: parameters, delegate: self)
    
  2. Aby zaimplementować protokół ResetPasswordStartDelegate jako rozszerzenie klasy, użyj następującego fragmentu kodu:

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

    Wywołanie resetPassword(parameters:delegate) powoduje wywołanie metod delegatów onResetPasswordCodeRequired() lub onResetPasswordStartError().

    W najbardziej typowym scenariuszu onResetPasswordCodeRequired(newState:sentTo:channelTargetType:codeLength) zostanie wywołany, aby wskazać, że kod został wysłany w celu zweryfikowania adresu e-mail użytkownika. Oprócz pewnych informacji, gdzie kod został wysłany i ile cyfr zawiera, ta metoda delegata zawiera także parametr newState typu ResetPasswordCodeRequiredState, który daje nam dostęp do dwóch nowych metod:

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

    Aby przesłać kod dostarczony przez użytkownika, użyj:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    
  3. Aby sprawdzić przesłany kod, zacznij od zaimplementowania protokołu ResetPasswordVerifyCodeDelegate jako rozszerzenia klasy przy użyciu następującego fragmentu kodu:

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

    W najbardziej typowym scenariuszu otrzymujemy wywołanie onPasswordRequired(newState) informujące, że możemy podać nowe hasło za pomocą instancji newState.

    newState.submitPassword(password: newPassword, delegate: self)
    
  4. Aby zaimplementować protokół ResetPasswordRequiredDelegate jako rozszerzenie klasy, użyj następującego fragmentu kodu:

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

    W najbardziej typowym scenariuszu otrzymujemy wywołanie onResetPasswordCompleted(newState) wskazujące, że przepływ resetowania hasła został ukończony.

Obsługa błędów

We wcześniejszej implementacji protokołu ResetPasswordStartDelegate wyświetlany jest błąd, gdy obsłużyliśmy funkcję delegata onResetPasswordStartError(error).

Możemy ulepszyć środowisko użytkownika, obsługując określony typ błędu w następujący sposób:

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

Obsługa błędów z uwzględnieniem stanów

Niektóre błędy obejmują odwołanie do nowego stanu. Jeśli na przykład użytkownik wprowadzi nieprawidłowy kod weryfikacyjny wiadomości e-mail, program obsługi błędów zawiera odwołanie do ResetPasswordCodeRequiredState, którego można użyć do przesłania nowego kodu weryfikacyjnego.

W poprzedniej implementacji protokołu ResetPasswordVerifyCodeDelegate po prostu wyświetliliśmy błąd, gdy obsłużyliśmy funkcję delegata onResetPasswordError(error:newState).

Możemy ulepszyć środowisko użytkownika, prosząc użytkownika o wprowadzenie poprawnego kodu i ponowne przesłanie go w następujący sposób:

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

Innym przykładem, w którym program obsługi błędów zawiera odwołanie do nowego stanu, jest wprowadzenie przez użytkownika nieprawidłowego hasła. W takim przypadku program obsługi błędów zawiera odwołanie do ResetPasswordRequiredState, którego można użyć do przesłania nowego hasła. Oto przykład:

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

Zaloguj się po zresetowaniu hasła

Zestaw SDK zapewnia deweloperom możliwość logowania użytkownika po zresetowaniu hasła bez konieczności podawania nazwy użytkownika lub weryfikowania adresu e-mail za pomocą jednorazowego kodu dostępu.

Aby zalogować użytkownika po pomyślnym zresetowaniu hasła, użyj metody signIn(parameters:delegate) z nowego stanu SignInAfterResetPasswordState zwróconego w funkcji 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"
        let parameters = MSALNativeAuthSignInAfterResetPasswordParameters()
        newState.signIn(parameters: parameters, delegate: self)
    }
}

signIn(parameters:delegate) akceptuje parametr delegata i musimy zaimplementować wymagane metody w protokole SignInAfterResetPasswordDelegate.

W najbardziej typowym scenariuszu otrzymujemy wywołanie onSignInCompleted(result) wskazujące, że użytkownik się zalogował. Wynik może służyć do odzyskiwania 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
        let parameters = MSALNativeAuthGetAccessTokenParameters()
        result.getAccessToken(parameters: parameters, delegate: self)
    }
}

getAccessToken(parameters:delegate) akceptuje parametr delegata i musimy zaimplementować wymagane metody w protokole CredentialsDelegate.

W najczęstszym scenariuszu otrzymujemy wywołanie onAccessTokenRetrieveCompleted(result) wskazujące, że użytkownik uzyskał 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)"
    }
}

Następny krok