Поделиться через


Руководство по самостоятельному сбросу пароля в приложении iOS/macOS

Область применения: Зеленый круг с символом белой галочки. iOS (Swift) Зеленый круг с символом белой галочки. macOS (Swift) (Swift)

В этом руководстве показано, как предоставить пользователям возможность изменять или сбрасывать пароль без участия администратора или службы технической поддержки.

В этом руководстве описано следующее:

  • Добавьте самостоятельный сброс пароля.
  • Обработка ошибок.

Необходимые компоненты

Введите новый пароль

Чтобы сбросить пароль существующего пользователя, необходимо проверить адрес электронной почты с помощью однократного секретного кода (OTP).

  1. Чтобы проверить электронную почту, мы вызываем resetPassword(parameters:delegate) метод из экземпляра пакета SDK с помощью следующего фрагмента кода:

    let parameters = MSALNativeAuthResetPasswordParameters(username: email)
    nativeAuth.resetPassword(parameters: parameters, delegate: self)
    
  2. Чтобы реализовать ResetPasswordStartDelegate протокол в качестве расширения для нашего класса, используйте следующий фрагмент кода:

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

    Вызов, который приводит к вызову resetPassword(parameters:delegate) методов либо onResetPasswordCodeRequired()onResetPasswordStartError() к делегатам.

    В наиболее распространенном сценарии onResetPasswordCodeRequired(newState:sentTo:channelTargetType:codeLength) будет вызван вызов, чтобы указать, что код отправлен для проверки адреса электронной почты пользователя. Наряду с некоторыми сведениями о том, где был отправлен код, и сколько цифр он содержит, этот метод делегата также имеет newState параметр типа ResetPasswordCodeRequiredState, который предоставляет нам доступ к двум новым методам:

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

    Чтобы отправить код, предоставленный пользователем, используйте следующую команду:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    
  3. Чтобы проверить отправленный код, начните с реализации ResetPasswordVerifyCodeDelegate протокола в качестве расширения для класса с помощью следующего фрагмента кода:

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

    В наиболее распространенном сценарии мы получаем вызов onPasswordRequired(newState) , указывающий, что мы можем предоставить новый пароль с помощью экземпляра newState .

    newState.submitPassword(password: newPassword, delegate: self)
    
  4. Чтобы реализовать ResetPasswordRequiredDelegate протокол в качестве расширения для нашего класса, используйте следующий фрагмент кода:

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

    В наиболее распространенном сценарии мы получаем вызов, указывающий onResetPasswordCompleted(newState) , что поток сброса пароля завершен.

Обработка ошибок

В предыдущей ResetPasswordStartDelegate реализации протокола мы отображали ошибку при обработке функции делегата onResetPasswordStartError(error) .

Мы можем улучшить взаимодействие с пользователем, обрабатывая конкретный тип ошибки следующим образом:

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

Обработка ошибок с состояниями

Некоторые ошибки включают ссылку на новое состояние. Например, если пользователь вводит неправильный код проверки электронной почты, обработчик ошибок содержит ссылку на ResetPasswordCodeRequiredState объект, который можно использовать для отправки нового кода проверки.

В предыдущей ResetPasswordVerifyCodeDelegate реализации протокола мы просто отображали ошибку при обработке функции делегата onResetPasswordError(error:newState) .

Мы можем улучшить взаимодействие с пользователем, попросите пользователя ввести правильный код и повторно отправить его следующим образом:

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

Другой пример, когда обработчик ошибок включает ссылку на новое состояние, когда пользователь вводит недопустимый пароль. В этом случае обработчик ошибок содержит ссылку на объект ResetPasswordRequiredState , который можно использовать для отправки нового пароля. Приведем пример:

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

Вход после сброса пароля

Пакет SDK предоставляет разработчикам возможность входа пользователя после сброса пароля без необходимости предоставлять имя пользователя или проверять адрес электронной почты через одноразовый секретный код.

Чтобы войти в систему после успешного сброса пароля, используйте signIn(parameters:delegate) метод из нового состояния SignInAfterResetPasswordState , возвращенного в 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) параметр делегата, и мы должны реализовать необходимые методы в протоколе SignInAfterResetPasswordDelegate .

В наиболее распространенном сценарии мы получаем вызов, указывающий onSignInCompleted(result) , что пользователь вошел в систему. Результат можно использовать для извлечения 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) параметр делегата, и мы должны реализовать необходимые методы в протоколе CredentialsDelegate .

В наиболее распространенном сценарии мы получаем вызов, onAccessTokenRetrieveCompleted(result) указывающий, что пользователь получил .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)"
    }
}

Следующий шаг