Agregue autenticación multifactor TOTP a su aplicación web

Si actualizó a Firebase Authentication con Identity Platform, puede agregar autenticación multifactor (MFA) con contraseña de un solo uso basada en tiempo (TOTP) a su aplicación.

Firebase Authentication con Identity Platform le permite usar un TOTP como factor adicional para MFA. Cuando habilita esta función, los usuarios que intentan iniciar sesión en su aplicación ven una solicitud de TOTP. Para generarlo deben utilizar una aplicación de autenticación capaz de generar códigos TOTP válidos, como Google Authenticator .

Antes de que empieces

  1. Habilite al menos un proveedor que admita MFA. Tenga en cuenta que todos los proveedores , excepto los siguientes, admiten MFA:

    • autenticación telefónica
    • autenticación anónima
    • Tokens de autenticación personalizados
    • Centro de juegos de Apple
  2. Asegúrese de que su aplicación verifique las direcciones de correo electrónico de los usuarios. MFA requiere verificación por correo electrónico. Esto evita que actores malintencionados se registren en un servicio con una dirección de correo electrónico que no les pertenece y luego bloqueen al propietario real de la dirección de correo electrónico agregando un segundo factor.

  3. Si aún no lo has hecho, instala el SDK de JavaScript de Firebase .

    TOTP MFA solo es compatible con el SDK web modular, versiones v9.19.1 y superiores.

Habilitar TOTP MFA

Para habilitar TOTP como segundo factor, utilice el SDK de administración o llame al punto final REST de configuración del proyecto.

Para utilizar el SDK de administrador, haga lo siguiente:

  1. Si aún no lo has hecho, instala el SDK de Firebase Admin Node.js.

    TOTP MFA solo se admite en las versiones 11.6.0 y superiores del SDK de Firebase Admin Node.js.

  2. Ejecute lo siguiente:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: {
                          NUM_ADJ_INTERVALS
                      },
                  }
              }]
          }
    })
    

    Reemplace lo siguiente:

    • NUM_ADJ_INTERVALS : el número de intervalos de ventana de tiempo adyacentes desde los cuales aceptar TOTP, de cero a diez. El valor predeterminado es cinco.

      Los TOTP funcionan garantizando que cuando dos partes (el probador y el validador) generen OTP dentro del mismo período de tiempo (normalmente de 30 segundos de duración), generen la misma contraseña. Sin embargo, para adaptarse a la variación del reloj entre las partes y el tiempo de respuesta humana, puede configurar el servicio TOTP para que también acepte TOTP de ventanas adyacentes.

Para habilitar TOTP MFA usando la API REST, ejecute lo siguiente:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": "NUM_ADJ_INTERVALS"
            }
          }]
       }
    }'

Reemplace lo siguiente:

  • PROJECT_ID : el ID del proyecto.
  • NUM_ADJ_INTERVALS : el número de intervalos de ventana de tiempo, de cero a diez. El valor predeterminado es cinco.

    Los TOTP funcionan garantizando que cuando dos partes (el probador y el validador) generen OTP dentro del mismo período de tiempo (normalmente de 30 segundos de duración), generen la misma contraseña. Sin embargo, para adaptarse a la variación del reloj entre las partes y el tiempo de respuesta humana, puede configurar el servicio TOTP para que también acepte TOTP de ventanas adyacentes.

Elija un patrón de inscripción

Puede elegir si su aplicación requiere autenticación multifactor y cómo y cuándo inscribir a sus usuarios. Algunos patrones comunes incluyen los siguientes:

  • Inscriba el segundo factor del usuario como parte del registro. Utilice este método si su aplicación requiere autenticación multifactor para todos los usuarios.

  • Ofrezca una opción que se pueda omitir para inscribir un segundo factor durante el registro. Si desea fomentar, pero no exigir, la autenticación multifactor en su aplicación, puede utilizar este enfoque.

  • Brinde la posibilidad de agregar un segundo factor desde la cuenta del usuario o la página de administración de perfil, en lugar de la pantalla de registro. Esto minimiza la fricción durante el proceso de registro y al mismo tiempo hace que la autenticación multifactor esté disponible para los usuarios sensibles a la seguridad.

  • Requerir agregar un segundo factor de manera incremental cuando el usuario desee acceder a funciones con mayores requisitos de seguridad.

Inscribir usuarios en TOTP MFA

Después de habilitar TOTP MFA como segundo factor para su aplicación, implemente la lógica del lado del cliente para inscribir usuarios en TOTP MFA:

  1. Importe las clases y funciones de MFA requeridas:

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. Vuelva a autenticar al usuario.

  3. Genere un secreto TOTP para el usuario autenticado:

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. Muestre el secreto al usuario y solicítele que lo ingrese en su aplicación de autenticación.

    Con muchas aplicaciones de autenticación, los usuarios pueden agregar rápidamente nuevos secretos TOTP escaneando un código QR que representa un URI de clave compatible con Google Authenticator . Para generar un código QR para este propósito, genere el URI con generateQrCodeUrl() y luego codifíquelo usando la biblioteca de códigos QR de su elección. Por ejemplo:

    const totpUri = totpSecret.generateQrCodeUrl(
        currentUser.email,
        "Your App's Name"
    );
    await QRExampleLib.toCanvas(totpUri, qrElement);
    

    Independientemente de si muestra un código QR, muestre siempre la clave secreta para admitir aplicaciones de autenticación que no pueden leer códigos QR:

    // Also display this key:
    const secret = totpSecret.secretKey;
    

    Después de que el usuario agregue su secreto a su aplicación de autenticación, esta comenzará a generar TOTP.

  5. Solicite al usuario que escriba el TOTP que se muestra en su aplicación de autenticación y lo utilice para finalizar la inscripción en MFA:

    // Ask the user for a verification code from the authenticator app.
    const verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
      totpSecret,
      verificationCode
    );
    await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
    

Iniciar sesión usuarios con un segundo factor

Para iniciar sesión de usuarios con TOTP MFA, utilice el siguiente código:

  1. Importe las clases y funciones de MFA requeridas:

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. Llame a uno de los métodos signInWith - como lo haría si no estuviera usando MFA. (Por ejemplo, signInWithEmailAndPassword() ). Si el método arroja un error auth/multi-factor-auth-required , inicie el flujo MFA de su aplicación.

    try {
        const userCredential = await signInWithEmailAndPassword(
            getAuth(),
            email,
            password
        );
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch (error) {
        switch (error.code) {
            case "auth/multi-factor-auth-required":
                // Initiate your second factor sign-in flow. (See next step.)
                // ...
                break;
            case ...:  // Handle other errors, such as wrong passwords.
                break;
        }
    }
    
  3. El flujo MFA de su aplicación primero debe pedirle al usuario que elija el segundo factor que desea usar. Puede obtener una lista de segundos factores admitidos examinando la propiedad de hints de una instancia MultiFactorResolver :

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. Si el usuario elige usar TOTP, solicítele que escriba el TOTP que se muestra en su aplicación de autenticación y utilícelo para iniciar sesión:

    switch (mfaResolver.hints[selectedIndex].factorId) {
        case TotpMultiFactorGenerator.FACTOR_ID:
            const otpFromAuthenticator = // OTP typed by the user.
            const multiFactorAssertion =
                TotpMultiFactorGenerator.assertionForSignIn(
                    mfaResolver.hints[selectedIndex].uid,
                    otpFromAuthenticator
                );
            try {
                const userCredential = await mfaResolver.resolveSignIn(
                    multiFactorAssertion
                );
                // Successfully signed in!
            } catch (error) {
                // Invalid or expired OTP.
            }
            break;
        case PhoneMultiFactorGenerator.FACTOR_ID:
            // Handle SMS second factor.
            break;
        default:
            // Unsupported second factor?
            break;
    }
    

Darse de baja de TOTP MFA

Esta sección describe cómo manejar la cancelación de la inscripción de un usuario en TOTP MFA.

Si un usuario se ha registrado en varias opciones de MFA y se da de baja de la opción habilitada más recientemente, recibe un auth/user-token-expired y se cierra su sesión. El usuario debe iniciar sesión nuevamente y verificar sus credenciales existentes (por ejemplo, una dirección de correo electrónico y una contraseña).

Para cancelar la inscripción del usuario, controlar el error y activar la reautenticación, utilice el siguiente código:

import {
    EmailAuthProvider,
    TotpMultiFactorGenerator,
    getAuth,
    multiFactor,
    reauthenticateWithCredential,
} from "firebase/auth";

try {
    // Unenroll from TOTP MFA.
    await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch  (error) {
    if (error.code === 'auth/user-token-expired') {
        // If the user was signed out, re-authenticate them.

        // For example, if they signed in with a password, prompt them to
        // provide it again, then call `reauthenticateWithCredential()` as shown
        // below.

        const credential = EmailAuthProvider.credential(email, password);
        await reauthenticateWithCredential(
            currentUser,
            credential
        );
    }
}

Que sigue