Cómo creamos la pestaña WebAuthn de Herramientas para desarrolladores de Chrome

Fawaz Mahoma
Fawaz Mohammad
Nina Satragno
Nina Satragno

La API de Web Authentication, también conocida como WebAuthn, permite que los servidores utilicen criptografía de clave pública (en lugar de contraseñas) para registrar y autenticar a los usuarios. Para ello, habilita la integración entre estos servidores y los autenticadores sólidos. Estos autenticadores pueden ser dispositivos físicos exclusivos (p.ej., llaves de seguridad) o estar integrados en plataformas (p.ej., lectores de huellas digitales). Puedes obtener más información sobre WebAuthn aquí en webauthn.guide.

Problemas para desarrolladores

Antes de este proyecto, WebAuthn no era compatible con la depuración nativa en Chrome. Un desarrollador que compilaba una app que usaba WebAuth requería acceso a autenticadores físicos. Esto era especialmente difícil por dos motivos:

  1. Existen muchos tipos diferentes de autenticadores. Para depurar la amplitud de configuraciones y capacidades, el desarrollador necesitó tener acceso a muchos autenticadores diferentes, a veces costosos.

  2. Los autenticadores físicos son seguros por su diseño. Por lo tanto, suele ser imposible inspeccionar su estado.

Para facilitar este proceso, quisimos agregar compatibilidad con la depuración directamente en las Herramientas para desarrolladores de Chrome.

Solución: una nueva pestaña de WebAuthn

La pestaña Herramientas para desarrolladores de WebAuthn facilita la depuración de WebAuthn, ya que permite a los desarrolladores emular estos autenticadores, personalizar sus capacidades e inspeccionar sus estados.

Nueva pestaña de WebAuthn

Implementación

El proceso de agregar compatibilidad con la depuración a WebAuthn fue un proceso de dos partes.

Proceso de dos partes

Parte 1: Agrega el dominio de WebAuthn al protocolo de las Herramientas para desarrolladores de Chrome

Primero, implementamos un nuevo dominio en el protocolo de Herramientas para desarrolladores de Chrome (CDP) que se conecta a un controlador que se comunica con el backend de WebAuthn.

El CDP conecta el frontend de Herramientas para desarrolladores con Chromium. En nuestro caso, usamos los actos de dominio de WebAuthn para conectar la pestaña WebAuthn Herramientas para desarrolladores y la implementación de WebAuthn de Chromium.

El dominio de WebAuthn permite habilitar e inhabilitar el entorno virtual del Autenticador, que desconecta el navegador del descubrimiento real del Autenticador y, en su lugar, conecta un descubrimiento virtual.

También exponemos métodos en el dominio que actúan como una capa delgada para las interfaces existentes del Autenticador virtual y Virtual Discovery, que forman parte de la implementación de WebAuthn de Chromium. Estos métodos incluyen agregar y quitar autenticadores, así como crear, obtener y borrar sus credenciales registradas.

(Lee el código).

Parte 2: Creación de la pestaña para el usuario

En segundo lugar, creamos una pestaña orientada al usuario en el frontend de las Herramientas para desarrolladores. La pestaña consta de una vista y un modelo. Un agente generado automáticamente conecta el dominio con la pestaña.

Si bien hay 3 componentes necesarios, solo debemos preocuparnos por dos de ellos: el model y la model. El tercer componente (el agente) se genera automáticamente después de agregar el dominio. En pocas palabras, el agente es la capa que lleva las llamadas entre el frontend y la CDP.

El modelo

El modelo es la capa de JavaScript que conecta el agente y la vista. En nuestro caso, el modelo es bastante simple. Toma comandos de la vista, compila las solicitudes de modo que sean consumibles por el CDP y, luego, las envía a través del agente. Estas solicitudes suelen ser unidireccionales y no se envía información a la vista.

Sin embargo, a veces pasamos una respuesta del modelo para proporcionar un ID a un autenticador recién creado o mostrar las credenciales almacenadas en un autenticador existente.

(Lee el código).

La vista

Nueva pestaña de WebAuthn

Usamos la vista para proporcionar la interfaz de usuario que un desarrollador puede encontrar cuando accede a Herramientas para desarrolladores. Contiene los elementos siguientes:

  1. Una barra de herramientas para habilitar el entorno del autenticador virtual
  2. Una sección para agregar autenticadores
  3. Una sección para autenticadores creados.

(Lee el código).

Barra de herramientas para habilitar el entorno del autenticador virtual

barra de herramientas

Dado que la mayoría de las interacciones del usuario se producen con un autenticador a la vez en lugar de toda la pestaña, la única funcionalidad que proporcionamos en la barra de herramientas es activar y desactivar el entorno virtual.

¿Por qué esto es necesario? Es importante que el usuario tenga que activar o desactivar explícitamente el entorno, ya que al hacerlo se desconectará el navegador del descubrimiento real de Autenticador. Por lo tanto, mientras esté activado, no se reconocerán los autenticadores físicos conectados, como un lector de huellas digitales.

Decidimos que un botón de activación explícito implica una mejor experiencia del usuario, especialmente para quienes navegan a la pestaña WebAuthn sin esperar que se inhabilite el descubrimiento real.

Agregando la sección Autenticadors

Agregando la sección Autenticadors

Después de habilitar el entorno del autenticador virtual, le presentamos al desarrollador un formato intercalado que le permite agregar un autenticador virtual. En este formulario, proporcionamos opciones de personalización que permiten al usuario decidir el protocolo y los métodos de transporte del autenticador, así como si el autenticador admite claves residentes y verificación del usuario.

Una vez que el usuario hace clic en Add, estas opciones se agrupan y se envían al modelo que realiza la llamada para crear un autenticador. Una vez que se haya completado, el frontend recibirá una respuesta y, luego, modificará la IU para incluir el autenticador recién creado.

La vista del Autenticador

La vista del Autenticador

Cada vez que se emula un autenticador, se agrega una sección a la vista del autenticador para representarlo. Cada sección del autenticador incluye un nombre, un ID, opciones de configuración, botones para quitar el autenticador o configurarlo como activo, y una tabla de credenciales.

El nombre del Autenticador

El nombre del autenticador se puede personalizar y, de forma predeterminada, es "Autenticador", concatenado con los últimos 5 caracteres de su ID. Originalmente, el nombre del autenticador era su ID completo y no se podía cambiar. Implementamos nombres personalizables para que el usuario pueda etiquetar el autenticador según sus capacidades, el autenticador físico que debe emular o cualquier sobrenombre que sea un poco más fácil de procesar que un ID de 36 caracteres.

Tabla de credenciales

Agregamos una tabla a cada sección de autenticador que muestra todas las credenciales registradas por un autenticador. Dentro de cada fila, proporcionamos información sobre una credencial, así como botones para quitarla o exportarla.

Actualmente, recopilamos la información para completar estas tablas sondeando la CDP para obtener las credenciales registradas de cada autenticador. En el futuro, planeamos agregar un evento para la creación de credenciales.

El botón Activar

También agregamos un botón de selección Activo a cada sección del autenticador. El autenticador actualmente activo será el único que escuche y registre credenciales. Sin esto, el registro de credenciales con varios autenticadores no es determinista, lo que sería una falla fatal cuando se intente probar WebAuthn con ellos.

Implementamos el estado activo con el método SetUserPresence en los autenticadores virtuales. El método SetUserPresence establece si las pruebas de presencia del usuario se ejecutan correctamente para un autenticador determinado. Si la desactivamos, un autenticador no podrá escuchar las credenciales. Por lo tanto, si nos aseguramos de que esté activado como máximo para un autenticador (el que esté configurado como activo) e inhabilitamos la presencia del usuario para todos los demás, podemos forzar un comportamiento determinista.

Un desafío interesante que enfrentamos al agregar el botón activo fue evitar una condición de carrera. Considera la siguiente situación:

  1. El usuario hace clic en el botón de selección Activo para el Autenticador X y envía una solicitud a la CDP para establecer X como activo. Está seleccionado el botón de selección Activo para X y se anula la selección de todos los demás.

  2. Inmediatamente después, el usuario hace clic en el botón de selección Activo para el Autenticador Y y envía una solicitud a la CDP para establecer Y como activo. Está seleccionado el botón de selección Activo para Y, y los demás, incluido X, no están seleccionados.

  3. En el backend, se completa y resuelve la llamada para establecer que Y como activo. Ahora Y está activo, pero no todos los demás autenticadores.

  4. En el backend, se completa y resuelve la llamada para establecer X como activo. X ahora está activo, mientras que todos los demás autenticadores, incluido Y, no.

Ahora, la situación resultante es la siguiente: X es el autenticador activo. Sin embargo, el botón de selección Activo para X no está seleccionado. Y no es el autenticador activo. Sin embargo, el botón de selección Activo para Y está seleccionado. Existe un desacuerdo entre el frontend y el estado real de los autenticadores. Obviamente, eso es un problema.

Nuestra solución: establecer una comunicación seudo bidireccional entre los botones de selección y el autenticador activo. Primero, mantenemos una variable activeId en la vista para hacer un seguimiento del ID del autenticador actualmente activo. Luego, esperamos a que la llamada establezca un autenticador activo para mostrar y luego establezcamos activeId en el ID de ese autenticador. Por último, repasamos cada sección de autenticador. Si el ID de esa sección es igual a activeId, configuraremos el botón como seleccionado. De lo contrario, dejaremos de seleccionar el botón.

A continuación, te mostramos cómo se ve:


 async _setActiveAuthenticator(authenticatorId) {
   await this._clearActiveAuthenticator();
   await this._model.setAutomaticPresenceSimulation(authenticatorId, true);
   this._activeId = authenticatorId;
   this._updateActiveButtons();
 }
 
 _updateActiveButtons() {
   const authenticators = this._authenticatorsView.getElementsByClassName('authenticator-section');
   Array.from(authenticators).forEach(authenticator => {
     authenticator.querySelector('input.dt-radio-button').checked =
         authenticator.getAttribute('data-authenticator-id') === this._activeId;
   });
 }
 
 async _clearActiveAuthenticator() {
   if (this._activeId) {
     await this._model.setAutomaticPresenceSimulation(this._activeId, false);
   }
   this._activeId = null;
 }

Métricas de uso

Queríamos hacer un seguimiento del uso de esta función. Al principio, se nos ocurrieron dos opciones.

  1. Cuenta cada vez que se abrió la pestaña WebAuthn en Herramientas para desarrolladores. Esta opción podría generar un recuento excesivo, ya que alguien podría abrir la pestaña sin usarla.

  2. Haz un seguimiento de la cantidad de veces que se activó la casilla de verificación “Habilitar el entorno del autenticador virtual” en la barra de herramientas. Esta opción también tenía un posible problema de recuento excesivo, ya que algunos pueden activar y desactivar el entorno varias veces en la misma sesión.

En última instancia, decidimos usar la segunda, pero restringimos el recuento por medio de una verificación para comprobar si el entorno ya se había habilitado en la sesión. Por lo tanto, solo aumentaríamos el recuento en 1, sin importar cuántas veces el desarrollador activó el entorno. Esto funciona porque se crea una nueva sesión cada vez que se vuelve a abrir la pestaña, lo que restablece la verificación y permite que la métrica se vuelva a aumentar.

Resumen

¡Gracias por leer esta información! Si tienes alguna sugerencia para mejorar la pestaña WebAuthn, informa un error.

Aquí encontrarás algunos recursos para obtener más información sobre WebAuthn:

Descarga los canales de vista previa

Considera usar Chrome Canary, Dev o Beta como tu navegador de desarrollo predeterminado. Estos canales de vista previa te brindan acceso a las funciones más recientes de Herramientas para desarrolladores, prueban las API de vanguardia de la plataforma web y te permiten encontrar problemas en tu sitio antes que los usuarios.

Cómo comunicarte con el equipo de Herramientas para desarrolladores de Chrome

Usa las siguientes opciones para hablar sobre las nuevas funciones y los cambios en la publicación, o cualquier otro aspecto relacionado con Herramientas para desarrolladores.

  • Envíanos una sugerencia o un comentario a través de crbug.com.
  • Informa un problema en Herramientas para desarrolladores con Más opciones   Más   > Ayuda > Informar problemas de Herramientas para desarrolladores en esta herramienta.
  • Envía un tweet a @ChromeDevTools.
  • Deje comentarios en las Novedades de los videos de YouTube de Herramientas para desarrolladores o en las sugerencias de Herramientas para desarrolladores los videos de YouTube.