Compartir vía


Tutorial: Incorporación de inicio de sesión y cierre de sesión en la aplicación iOS/macOS mediante la autenticación nativa

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)

En este tutorial se muestra cómo iniciar sesión y cerrar sesión de un usuario con código de acceso de un solo uso de correo electrónico o nombre de usuario y contraseña en la aplicación móvil de iOS/macOS mediante la autenticación nativa.

En este tutorial, aprenderá a:

  • Inicie sesión en un usuario mediante el código de acceso de un solo uso de correo electrónico o el nombre de usuario (correo electrónico) y la contraseña.
  • Cierre de sesión de usuarios.
  • Control de errores de inicio de sesión

Requisitos previos

Inicio de sesión de los usuarios

Para que un usuario inicie sesión mediante el flujo de Códigos de acceso de un solo uso de correo electrónico, capture el correo electrónico y envíe un correo electrónico que contenga un código de acceso de un solo uso para que el usuario compruebe su correo electrónico. Cuando el usuario escribe un código de acceso de un solo uso válido, la aplicación hace que inicie sesión.

Para iniciar la sesión de un usuario mediante el flujo Correo electrónico con contraseña, capture el correo electrónico y la contraseña. Si el nombre de usuario y la contraseña son válidos, la aplicación inicia sesión en el usuario.

Para iniciar sesión en un usuario, debe hacer lo siguiente:

  1. Cree una interfaz de usuario (UI) para:

    • Recopilar un correo electrónico del usuario. Agregar validación a las entradas para asegurarse de que el usuario escribe una dirección de correo electrónico válida.
    • Recopilar una contraseña si inicia sesión con el nombre de usuario (correo electrónico) y la contraseña.
    • Recopile un código de acceso de un solo uso de correo electrónico del usuario si inicia sesión con el código de acceso de un solo uso por correo electrónico.
    • Agregue un botón para permitir que el usuario vuelva a enviar el código de acceso de un solo uso si inicia sesión con el código de acceso de un solo uso de correo electrónico.
  2. En la interfaz de usuario, agregue un botón, cuyo evento select inicia un inicio de sesión como se muestra en el siguiente fragmento de código:

        @IBAction func signInPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "email not set"
            return
        }
    
        nativeAuth.signIn(username: email, delegate: self)
    }
    

    Para iniciar sesión a un usuario mediante el flujo de código de acceso de un solo uso de correo electrónico, utilizamos el siguiente fragmento de código:

    nativeAuth.signIn(username: email, delegate: self)
    

    El método signIn(username:delegate), que responde de forma asincrónica llamando a uno de los métodos del objeto delegado pasado, debe implementar el protocolo SignInStartDelegate. Pasamos la dirección de correo electrónico que el usuario proporciona en el formulario de envío de correo electrónico y pasamos self como delegado.

    Para iniciar sesión un usuario mediante flujo de correo electrónico con contraseña, usamos el siguiente fragmento de código:

    nativeAuth.signIn(username: email, password: password, delegate: self)
    

    En el método signIn(username:password:delegate), pasa la dirección de correo electrónico con la que el usuario nos proporcionó, su contraseña y pasa el objeto delegado que se ajusta al protocolo SignInStartDelegate. En este ejemplo, pasamos self.

  3. Para implementar el protocolo SignInStartDelegate al usar el flujo de código de acceso de un solo uso de correo electrónico, use el siguiente fragmento de código:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCodeRequired(
            newState: MSAL.SignInCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    }
    

    Da signIn(username:delegate) como resultado una llamada a métodos delegados. En el escenario más común, onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength) se llama a para indicar que se ha enviado un código para comprobar 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 SignInCodeRequiredState, que nos da acceso a los dos nuevos métodos siguientes:

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

    Use submitCode(code:delegate) para enviar el código de acceso de un solo uso que el usuario proporciona en el formulario de código de acceso de un solo uso, use el siguiente fragmento de código:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    

    submitCode(code:delegate) acepta el código de acceso único y el parámetro de delegado. Después de enviar el código, debe comprobar el código de acceso de un solo uso mediante la implementación del protocolo SignInVerifyCodeDelegate.

    Para implementar protocolo SignInVerifyCodeDelegate como extensión para nuestra clase, use el siguiente fragmento de código:

    extension ViewController: SignInVerifyCodeDelegate {
        func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
            resultTextView.text = "Signed in successfully."
            result.getAccessToken(delegate: self)
        }
    }
    

    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.

    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)"
        }
    }
    
    
  4. Para implementar el protocolo SignInStartDelegate al usar flujo de correo electrónico con contraseña, use el siguiente fragmento de código:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
            // User successfully signed in
        }
    }
    

    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.

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

Control de errores de inicio de sesión

Durante el inicio de sesión, no todas las acciones se realizan correctamente. Por ejemplo, el usuario podría intentar iniciar sesión con una dirección de correo electrónico que no existe o enviar un código no válido.

  1. Para controlar errores en el método signIn(username) o signIn(username, password), use el siguiente fragmento de código:

    func onSignInStartError(error: MSAL.SignInStartError) {
        if error.isUserNotFound || error.isInvalidUsername {
            resultTextView.text = "Invalid username"
        } else {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    }
    
  2. Para controlar errores en submitCode() método, use el siguiente fragmento de código:

    func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
        if error.isInvalidCode {
            // Inform the user that the submitted code was incorrect and ask for a new code to be supplied
            let userSuppliedCode = retrieveNewCode()
            newState?.submitCode(code: userSuppliedCode, delegate: self)
        } else {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    }
    

    Si el usuario escribe un código de verificación de correo electrónico incorrecto, el controlador de errores incluye una referencia a un objeto SignInCodeRequiredState que se puede usar para enviar un código actualizado. En la implementación anterior del protocolo SignInVerifyCodeDelegate, simplemente se muestra el error al controlar la función de delegado onSignInVerifyCodeError(error:newState).

Lectura de las notificaciones del token de identificador

Una vez que la aplicación adquiere un token de identificador, puede recuperar las notificaciones asociadas a la cuenta actual. Para ello, use el siguiente fragmento de código:

func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
   let claims = result.account.accountClaims
   let preferredUsername = claims?["preferred_username"] as? String
}

La clave que se usa para acceder al valor de notificación es el nombre que especifique al agregar el atributo de usuario como notificación de token.

Aprenda a agregar atributos incorporados y personalizados como notificaciones de token en el artículo Agregar atributos de usuario a notificaciones de token.

Cerrar la sesión del usuario

Para cerrar la sesión de un usuario, use la referenciaMSALNativeAuthUserAccountResult que ha recibido en la devolución de llamadaonSignInCompleted, o use getNativeAuthUserAccount() para obtener cualquier cuenta con sesión iniciada de la memoria caché y almacenar una referencia en la variable miembro accountResult.

  1. Configure el grupo de llaves para el proyecto como se describe aquí.

  2. Agregue una nueva variable miembro a la clase ViewController: var accountResult: MSALNativeAuthUserAccountResult?.

  3. Actualice viewDidLoad para recuperar cualquier cuenta almacenada en caché agregando esta línea después nativeAuth para inicializarse correctamente: accountResult = nativeAuth.getNativeAuthUserAccount().

  4. Actualice el controlador signInCompleted para almacenar el resultado de la cuenta:

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. Agregue un botón cerrar sesión y use el código siguiente para cerrar la sesión del usuario:

    @IBAction func signOutPressed(_: Any) {
        guard let accountResult = accountResult else {
            print("Not currently signed in")
            return
        }
    
        accountResult.signOut()
    
        self.accountResult = nil
    
        resultTextView.text = "Signed out"
    }
    

Ha completado correctamente todos los pasos necesarios para cerrar la sesión de un usuario en la aplicación. Compile y ejecute su aplicación. Si todo es correcto, deberías poder seleccionar el botón cerrar sesión para cerrar la sesión correctamente.

Configuración del proveedor de notificaciones personalizado

Si quieres agregar notificaciones de un sistema externo al token emitido a la aplicación, usa un proveedor de notificaciones personalizado. Un proveedor de notificaciones personalizado se compone de una extensión de autenticación personalizada que llama a una API REST externa para obtener notificaciones de sistemas externos.

Sigue los pasos descritos en Configuración de un proveedor de notificaciones personalizado para agregar notificaciones desde un sistema externo a los tokens de seguridad.