Compartilhar via


Tutorial: redefinição de senha self-service em aplicativo iOS/macOS.

Aplica-se a: Círculo verde com um símbolo de marca de seleção branca que indica que o conteúdo a seguir se aplica a locatários externos. Locatários externos (saiba mais)

Este tutorial demonstra como dar aos usuários a capacidade de alterar ou redefinir a senha, sem envolvimento do administrador ou do suporte técnico.

Neste tutorial, você:

  • Adicionar redefinição de senha self-service.
  • Tratar erros.

Pré-requisitos

Insira uma nova senha

Para redefinir a senha de um usuário existente, é necessário validar o endereço de email usando uma senha de uso único (OTP).

  1. Para validar o email, o método resetPassword(parameters:delegate) é chamado da instância do SDK usando o seguinte snippet de código:

    let parameters = MSALNativeAuthResetPasswordParameters(username: email)
    nativeAuth.resetPassword(parameters: parameters, delegate: self)
    
  2. Para implementar o protocolo ResetPasswordStartDelegate como uma extensão da nossa classe, use o seguinte snippet de código:

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

    A chamada para resetPassword(parameters:delegate) resulta em uma chamada para métodos delegados onResetPasswordCodeRequired() ou onResetPasswordStartError().

    No cenário mais comum, onResetPasswordCodeRequired(newState:sentTo:channelTargetType:codeLength) será chamado para indicar que um código foi enviado para verificar o endereço de email do usuário. Acompanhado de alguns detalhes, como local de envio do código e número de dígitos que ele contém, esse método delegado também tem um parâmetro newState do tipo ResetPasswordCodeRequiredState, que fornece acesso a dois novos métodos:

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

    Para enviar o código fornecido pelo usuário, use:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    
  3. Para verificar o código enviado, comece implementando o protocolo ResetPasswordVerifyCodeDelegate como uma extensão para sua classe usando o seguinte snippet de código:

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

    No cenário mais comum, uma chamada para onPasswordRequired(newState) é recebida, indicando que é possível fornecer a nova senha usando a instância newState.

    newState.submitPassword(password: newPassword, delegate: self)
    
  4. Para implementar o protocolo ResetPasswordRequiredDelegate como uma extensão da nossa classe, use o seguinte snippet de código:

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

    No cenário mais comum, uma chamada para onResetPasswordCompleted(newState) é recebida, indicando que o fluxo de redefinição de senha foi concluído.

Gerenciar erros

Na implementação anterior do protocolo ResetPasswordStartDelegate, o erro foi exibido ao tratar da função de delegação onResetPasswordStartError(error).

É possível aprimorar a experiência do usuário tratando o tipo de erro específico da seguinte maneira:

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

Tratar erros com estados

Alguns erros incluem uma referência a um novo estado. Por exemplo, se o usuário inserir um código de verificação de email incorreto, o manipulador de erros incluirá uma referência a um ResetPasswordCodeRequiredState que poderá ser usado para enviar um novo código de verificação.

Na nossa implementação anterior do protocolo ResetPasswordVerifyCodeDelegate, nós simplesmente exibimos o erro ao lidar com a função de delegado onResetPasswordError(error:newState).

É possível melhorar a experiência do usuário solicitando ao usuário que insira o código correto e envie-o novamente da seguinte maneira:

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

Outro exemplo em que o manipulador de erros inclui uma referência a um novo estado é quando o usuário insere uma senha inválida. Nesse caso, o manipulador de erros inclui uma referência a um ResetPasswordRequiredState que pode ser usado para enviar uma senha nova. Veja um exemplo:

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

Entrar após a redefinição de senha

O SDK fornece aos desenvolvedores a capacidade de conectar um usuário depois de redefinir sua senha sem precisar fornecer o nome de usuário ou verificar o endereço de email por meio de uma senha de uso único.

Para conectar um usuário após a redefinição de senha bem-sucedida, use o método signIn(parameters:delegate) do novo estado SignInAfterResetPasswordState retornado na função 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)
    }
}

O signIn(parameters:delegate) aceita um parâmetro delegado e devemos implementar os métodos necessários no protocolo SignInAfterResetPasswordDelegate.

No cenário mais comum, recebemos uma chamada a onSignInCompleted(result), indicando que o usuário se conectou. O resultado pode ser usado para recuperar o 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)
    }
}

O getAccessToken(parameters:delegate) aceita um parâmetro delegado e devemos implementar os métodos necessários no protocolo CredentialsDelegate.

No cenário mais comum, recebemos uma chamada a onAccessTokenRetrieveCompleted(result), indicando que o usuário obteve um 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)"
    }
}

Próxima etapa