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, donde 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 más lenta, el proceso podría tardar uno o dos minutos:

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

Más información sobre este repositorio

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

  • functions/index.js contiene 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) en
  • src/firebase-config.js: Contiene el objeto de configuración de Firebase que se usa para inicializar tu app de chat.
  • src/index.js: Es el código JS de tu app de chat.

Obtén Firebase CLI

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

$ npm install -g firebase-tools@latest

Compila el código JavaScript con webpack, que creará el archivo 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

Cómo conectarte 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

A continuación, ejecuta el siguiente comando para crear un alias de proyecto. Reemplaza $YOUR_PROJECT_ID por el ID del proyecto de Firebase.

$ firebase use $YOUR_PROJECT_ID

Ya está todo listo para que ejecutes 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.

Inicia los emuladores

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

$ firebase emulators:start

Esto publicará tu app en http://127.0.0.1:5170 y 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) localmente en tu navegador para ver los cambios.

Deberías ver un resultado 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 Todos los emuladores listos, la app estará lista para usarse.

3. Implementa la MFA

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

En el 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 del teléfono (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 que se invocan 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 solicite que proporciones el código de MFA, lo verás en la ventana de la terminal.

Dado que los emuladores admiten por completo 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 diseñadas para que solo las use un grupo específico de usuarios. En esos casos, es posible que quieras crear requisitos personalizados para que un usuario se registre en tu app o acceda a ella.

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 comentada.

Reemplázala con este código que solo permite que los usuarios con el dominio 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 tus emuladores estén en ejecución y, en la app web en localhost:5170, sal de tu cuenta.

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

Vuelve a intentarlo con una dirección de correo electrónico que termine en example.com. La cuenta se creará correctamente.

Con las funciones de bloqueo, puedes crear las restricciones que necesites en torno a 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 app web para ayudar a los usuarios a mantener la seguridad de sus cuentas y, luego, creaste requisitos personalizados para que los usuarios se registren con funciones de bloqueo. ¡Ganaste un GIF!

un GIF de personas de la oficina haciendo el baile de levantar el techo