Tutorial: Autoservicio de restablecimiento de contraseña en la aplicación iOS/macOS.
Se aplica a: iOS (Swift) macOS (Swift)
Este tutorial muestra cómo dar a los usuarios la posibilidad de cambiar o restablecer su contraseña, sin intervención del administrador o del servicio de asistencia.
En este tutorial, aprenderá a:
- Agregue el autoservicio de restablecimiento de contraseña.
- Control de errores.
Requisitos previos
Restablecimiento de contraseña
Para restablecer la contraseña de un usuario existente, tenemos que validar la dirección de correo electrónico mediante un código de un solo uso (OTP).
Para validar el correo electrónico, llamamos al método
resetPassword(username:delegate)
desde la instancia SDK utilizando el siguiente fragmento de código:nativeAuth.resetPassword(username: email, delegate: self)
Para implementar el protocolo de
ResetPasswordStartDelegate
como una extensión de nuestra clase, use el siguiente fragmento 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")" } }
La llamada
resetPassword(username:delegate)
da como resultado una llamada a métodos delegadosonResetPasswordCodeRequired()
oonResetPasswordStartError()
.En el escenario más común
onResetPasswordCodeRequired(newState:sentTo:channelTargetType:codeLength)
se llamará para indicar que se ha enviado un código para verificar la dirección de correo electrónico del usuario. Junto con algunos detalles de dónde se ha enviado el código y cuántos dígitos contiene, este método delegado también tiene un parámetronewState
de tipoResetPasswordCodeRequiredState
, que nos da acceso a dos nuevos métodos:submitCode(code:delegate)
resendCode(delegate)
Para enviar el código que el usuario nos proporcionó, utilice:
newState.submitCode(code: userSuppliedCode, delegate: self)
Para verificar el código enviado, comience implementando el protocolo
ResetPasswordVerifyCodeDelegate
como una extensión de su clase utilizando el siguiente fragmento 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 } }
En el escenario más común, recibimos una llamada para
onPasswordRequired(newState)
indicar que podemos proporcionar la nueva contraseña utilizando la instancianewState
.newState.submitPassword(password: newPassword, delegate: self)
Para implementar el protocolo de
ResetPasswordRequiredDelegate
como una extensión de nuestra clase, use el siguiente fragmento 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" } }
En el escenario más común, recibimos una llamada para
onResetPasswordCompleted(newState)
indicar que el flujo de restablecimiento de contraseña ha finalizado.
Control de errores
En la implementación anterior del protocolo ResetPasswordStartDelegate
, se muestra el error al controlar la función de delegadoonResetPasswordStartError(error)
.
Podemos mejorar la experiencia del usuario controlando el tipo de error específico de la siguiente manera:
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")"
}
}
Control de errores con estados
Algunos errores incluyen una referencia a un nuevo estado. Por ejemplo, si el usuario introduce un código de verificación de correo electrónico incorrecto, el controlador de errores incluye una referencia a ResetPasswordCodeRequiredState
que puede utilizarse para enviar un nuevo código de verificación.
En nuestra implementación anterior del protocolo ResetPasswordVerifyCodeDelegate
, simplemente mostrábamos el error cuando manejábamos la función delegada onResetPasswordError(error:newState)
.
Podemos mejorar la experiencia del usuario pidiéndole que introduzca el código correcto y volviéndolo a enviar de la siguiente manera:
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")"
}
}
Otro ejemplo en el que el controlador de errores incluye una referencia a un nuevo estado es cuando el usuario introduce una contraseña no válida. En este caso, el controlador de errores incluye una referencia a ResetPasswordRequiredState
que se puede utilizar para enviar una nueva contraseña. Este es un ejemplo:
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")"
}
}
Iniciar sesión después del restablecimiento de contraseña
El SDK ofrece a los desarrolladores la posibilidad de iniciar la sesión de un usuario después de restablecer su contraseña sin tener que proporcionar el nombre de usuario, o de verificar la dirección de correo electrónico mediante una contraseña de un solo uso.
Para iniciar sesión en un usuario después de restablecer la contraseña con éxito, utilice el método signIn(delegate)
del nuevo estado SignInAfterResetPasswordState
devuelto en la función 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"
newState.signIn(delegate: self)
}
}
signIn(delegate)
acepta un parámetro delegado y debemos implementar los métodos necesarios en el protocolo SignInAfterResetPasswordDelegate
.
En el escenario más común, recibimos una llamada a onSignInCompleted(result)
que indica que el usuario ha iniciado sesión. El resultado se puede usar para recuperar 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
result.getAccessToken(delegate: self)
}
}
getAccessToken(delegate)
acepta un parámetro delegado y debemos implementar los métodos necesarios en el protocolo CredentialsDelegate
.
En el escenario más común, recibimos una llamada a onAccessTokenRetrieveCompleted(result)
para indicar que el usuario obtuvo un 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)"
}
}