Funciones de autenticación avanzada

1. Configurar

Obtén el código fuente

En este codelab, comenzarás con una versión de la app de ejemplo de Friendly Chat que está casi completa, por lo que lo primero que debes hacer es clonar el código fuente:

$ git clone https://github.com/firebase/codelab-friendlychat-web --branch security

Luego, ve al directorio security-start, en el que trabajarás durante el resto de este codelab:

$ cd codelab-friendlychat-web/security-start

Ahora, instala las dependencias para poder ejecutar el código. Si tienes una conexión a Internet lenta, es posible que este proceso demore unos minutos:

$ npm install && (cd functions && npm install)

Conoce este repositorio

El directorio security-solution/ contiene el código completo de la app de ejemplo. En el directorio security-start, trabajarás en el codelab y les faltan algunas partes importantes de la implementación de la autenticación. Los archivos clave y las funciones de security-start/ y security-solution/ son los siguientes:

  • functions/index.js contiene el código de Cloud Functions y es donde escribirás funciones de bloqueo de autenticación.
  • public/: Contiene los archivos estáticos para tu app de chat
  • public/scripts/main.js, donde se compila el código JS de tu app de chat (src/index.js)
  • src/firebase-config.js: Contiene el objeto de configuración de Firebase que se usa para inicializar tu app de chat.
  • src/index.js: el código JS de tu app de chat

Cómo obtener Firebase CLI

Emulator Suite forma parte de Firebase CLI (interfaz de línea de comandos), que puedes instalar en tu máquina con el siguiente comando:

$ npm install -g firebase-tools@latest

Compila el código JavaScript con webpack, lo que creará main.js dentro del directorio public/scripts/.

webpack build

A continuación, confirma que tienes la versión más reciente de la CLI. Este codelab funciona con la versión 11.14 o una posterior.

$ firebase --version
11.14.2

Conéctate a tu proyecto de Firebase

Si no tienes un proyecto de Firebase, crea uno nuevo en Firebase console. Toma nota del ID del proyecto que elijas, ya que lo necesitarás más adelante.

Ahora, debes conectar este código a tu proyecto de Firebase. Primero, ejecuta el siguiente comando para acceder a Firebase CLI:

$ firebase login

Luego, ejecuta el siguiente comando para crear un alias para el proyecto. Reemplaza $YOUR_PROJECT_ID por el ID del proyecto de Firebase.

$ firebase use $YOUR_PROJECT_ID

Ya está todo listo para ejecutar la app.

2. Ejecuta los emuladores

En esta sección, ejecutarás la app de manera local. Esto significa que es momento de iniciar Emulator Suite.

Cómo iniciar los emuladores

Desde el directorio del código fuente del codelab, ejecuta el siguiente comando para iniciar los emuladores:

$ firebase emulators:start

De esta forma, tu app se entregará en http://127.0.0.1:5170 y se volverá a compilar el código fuente de forma continua a medida que realices cambios. Solo deberás realizar una actualización forzada (ctrl-shift-r) de forma local en tu navegador para ver los cambios.

Deberías ver algunos resultados como este:

i  emulators: Starting emulators: auth, functions, firestore, hosting, storage
✔  functions: Using node@16 from host.
i  firestore: Firestore Emulator logging to firestore-debug.log
✔  firestore: Firestore Emulator UI websocket is running on 9150.
i  hosting[demo-example]: Serving hosting files from: ./public
✔  hosting[demo-example]: Local server: http://127.0.0.1:5170
i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "[...]" for Cloud Functions...
✔  functions: Loaded functions definitions from source: beforecreated.
✔  functions[us-central1-beforecreated]: providers/cloud.auth/eventTypes/user.beforeCreate function initialized (http://127.0.0.1:5011/[...]/us-central1/beforecreated).
i  Running script: npm start
 
> security@1.0.0 start
> webpack --watch --progress
[...]
webpack 5.50.0 compiled with 1 warning in 990 ms

Una vez que veas el mensaje All emulators ready, significa que la app está lista para usarse.

3. Implementación de la MFA

La MFA se implementó parcialmente en este repositorio. Agregarás el código para inscribir primero a un usuario en la MFA y, luego, para solicitarles a los usuarios inscritos en MFA un segundo factor.

En tu editor, abre el archivo src/index.js y busca el método startEnrollMultiFactor(). Agrega el siguiente código para configurar el verificador reCAPTCHA que evitará el abuso telefónico (el verificador reCAPTCHA está configurado como invisible y no será visible para los usuarios):

async function startEnrollMultiFactor(phoneNumber) {
  const recaptchaVerifier = new RecaptchaVerifier(
    "recaptcha",
    { size: "invisible" },
    getAuth()
  );

Luego, busca el método finishEnrollMultiFactor() y agrega lo siguiente para inscribir el segundo factor:

// Completes MFA enrollment once a verification code is obtained.
async function finishEnrollMultiFactor(verificationCode) {
  // Ask user for the verification code. Then:
  const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
  const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
 
  // Complete enrollment.
  await multiFactor(getAuth().currentUser)
    .enroll(multiFactorAssertion)
    .catch(function (error) {
      alert(`Error finishing second factor enrollment. ${error}`);
      throw error;
    });
  verificationId = null;
}

A continuación, busca la función signIn y agrega el siguiente flujo de control que solicita a los usuarios inscritos en la MFA que ingresen su segundo factor:

async function signIn() {
  // Sign in Firebase using popup auth and Google as the identity provider.
  var provider = new GoogleAuthProvider();
  await signInWithPopup(getAuth(), provider)
    .then(function (userCredential) {
      // User successfully signed in and is not enrolled with a second factor.
    })
    .catch(function (error) {
      if (error.code == "auth/multi-factor-auth-required") {
        multiFactorResolver = getMultiFactorResolver(getAuth(), error);
        displaySecondFactor(multiFactorResolver.hints);
      } else {
        alert(`Error signing in user. ${error}`);
      }
    });
}

El resto de la implementación, incluidas las funciones invocadas aquí, ya está completa. Para ver cómo funcionan, explora el resto del archivo.

4. Prueba acceder con MFA en los emuladores

Ahora prueba la implementación de la MFA. Asegúrate de que los emuladores sigan ejecutándose y visita la app alojada de forma local en localhost:5170. Intenta acceder y cuando se te pida que proporciones el código MFA, verás este código en la ventana de tu terminal.

Dado que los emuladores admiten totalmente la autenticación de varios factores, tu entorno de desarrollo puede ser completamente independiente.

Para obtener más información sobre la implementación de la MFA, consulta nuestros documentos de referencia.

5. Crea una función de bloqueo

Algunas aplicaciones están pensadas para que las utilice solo un grupo específico de usuarios. En esos casos, querrás crear requisitos personalizados para que un usuario se registre o acceda a tu app.

Eso es lo que proporcionan las funciones de bloqueo: una forma de crear requisitos de autenticación personalizados. Son Cloud Functions, pero, a diferencia de la mayoría de las funciones, se ejecutan de forma síncrona cuando un usuario intenta registrarse o acceder.

Para crear una función de bloqueo, abre functions/index.js en tu editor y busca la función beforecreated con comentarios.

Reemplázala con este código que permite que solo los usuarios con un dominio de example.com creen una cuenta:

exports.beforecreated = beforeUserCreated((event) => {
  const user = event.data;
  // Only users of a specific domain can sign up.
  if (!user.email || !user.email.endsWith("@example.com")) {
    throw new HttpsError("invalid-argument", "Unauthorized email");
  }
});

6. Prueba la función de bloqueo en los emuladores

Para probar la función de bloqueo, asegúrate de que se estén ejecutando los emuladores y sal de la app web en localhost:5170.

Luego, intenta crear una cuenta con una dirección de correo electrónico que no termine en example.com. La función de bloqueo impedirá que la operación se realice correctamente.

Ahora, vuelve a intentarlo con una dirección de correo electrónico que termine en example.com. Se creará correctamente la cuenta.

Con las funciones de bloqueo, puedes crear las restricciones que necesites para la autenticación. Para obtener más información, consulta los documentos de referencia.

Resumen

Buen trabajo. Agregaste la autenticación de varios factores a una aplicación web para ayudar a los usuarios a mantener sus cuentas seguras y, luego, creaste requisitos personalizados para que los usuarios se registraran con funciones de bloqueo. Ganaste un GIF.

GIF de personas de la oficina haciendo el baile de la musculación