Tutorial: redefinição de senha self-service em aplicativo iOS/macOS.
Aplica-se a: iOS (Swift)
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).
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)
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 delegadosonResetPasswordCodeRequired()
ouonResetPasswordStartError()
.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âmetronewState
do tipoResetPasswordCodeRequiredState
, 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)
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âncianewState
.newState.submitPassword(password: newPassword, delegate: self)
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)"
}
}