Compartir vía


Tutorial: Autoservicio de restablecimiento de contraseña en la aplicación iOS/macOS.

Se aplica a: Círculo verde con un símbolo de marca de verificación blanca. iOS (Swift) Círculo verde con un símbolo de marca de verificación blanca. 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).

  1. 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)
    
  2. 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 delegados onResetPasswordCodeRequired() o onResetPasswordStartError().

    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ámetro newState de tipo ResetPasswordCodeRequiredState, 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)
    
  3. Para verificar el código enviado, comience implementando el protocoloResetPasswordVerifyCodeDelegate 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 instancia newState.

    newState.submitPassword(password: newPassword, delegate: self)
    
  4. 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)"
    }
}

Paso siguiente