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 branco. iOS (Swift) Círculo verde com um símbolo de marca de seleção branco. macOS (Swift)

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ê aprenderá a:

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

Pré-requisitos

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

Tratar 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 implementação anterior do protocolo ResetPasswordVerifyCodeDelegate, o erro foi exibido ao tratar da função de delegação 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 deve-se 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 deve-se 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