Permite la reutilización de llaves de acceso en tus sitios con las solicitudes de origen relacionadas

Maud Nalpas
Maud Nalpas

Las llaves de acceso están vinculadas a un sitio web específico y solo se pueden usar para acceder al sitio web para el que se crearon.

Esto se especifica en el ID del grupo de confianza (ID del RP), que, para las llaves de acceso creadas para el dominio example.com, podría ser www.example.com o example.com.

Si bien los IDs de RP evitan que las llaves de acceso se usen como una sola credencial para la autenticación en todas partes, generan problemas en los siguientes casos:

  • Sitios con varios dominios: Los usuarios no pueden usar la misma llave de acceso para acceder a diferentes dominios específicos de cada país (por ejemplo, example.com y example.co.uk) administrados por la misma empresa.
  • Dominios de marca: Los usuarios no pueden usar la misma credencial en diferentes dominios que usa una sola marca (por ejemplo, acme.com y acmerewards.com).
  • Apps para dispositivos móviles: Las apps para dispositivos móviles a menudo no tienen su propio dominio, lo que dificulta la administración de credenciales.

Existen soluciones alternativas basadas en la federación de identidades y otras basadas en iframes, pero son inconvenientes en algunos casos. Las solicitudes de origen relacionadas ofrecen una solución.

Solución

Con las solicitudes de origen relacionado, un sitio web puede especificar los orígenes que tienen permiso para usar su ID de RP.

Esto permite que los usuarios reutilicen la misma llave de acceso en varios sitios que operas.

Para usar las solicitudes de origen relacionado, debes publicar un archivo JSON especial en una URL específica https://{RP ID}/.well-known/webauthn. Si example.com quiere permitir que los orígenes adicionales lo usen como ID de RP, debe publicar el siguiente archivo en https://example.com/.well-known/webauthn:.

{
  "origins": [
    "https://example.co.uk",
    "https://example.de",
    "https://example-rewards.com"
  ]
}

La próxima vez que cualquiera de estos sitios realice una llamada para la creación (navigator.credentials.create) o la autenticación (navigator.credentials.get) de una llave de acceso que use example.com como ID de RP, el navegador notará un ID de RP que no coincide con el origen solicitante. Si el navegador admite solicitudes de orígenes relacionados, primero busca un archivo webauthn en https://{RP ID}/.well-known/webauthn. Si el archivo existe, el navegador verifica si el origen que realiza la solicitud está en allowlist. Si es así, se procede a los pasos de creación o autenticación de la llave de acceso.

Si el navegador no admite las solicitudes de origen relacionado, arroja un SecurityError.

Navegadores compatibles

Browser Support

  • Chrome: 133.
  • Edge: 133.
  • Firefox: 135.
  • Safari: 17.4.

Source

En la siguiente demostración, se usan dos sitios, https://ror-1.glitch.me y https://ror-2.glitch.me. Para permitir que los usuarios accedan con la misma llave de acceso en ambos sitios, se usan solicitudes de origen relacionado para permitir que ror-2.glitch.me use ror-1.glitch.me como su ID de RP.

Demostración

https://ror-2.glitch.me implementa solicitudes de origen relacionado para usar ror-1.glitch.me como un ID de RP, por lo que tanto ror-1 como ror-2 usan ror-1.glitch.me como un ID de RP cuando se crea una llave de acceso o se realiza la autenticación con ella. También implementamos una base de datos de llaves de acceso compartida en estos sitios.

Observa la siguiente experiencia del usuario:

  • Puedes crear correctamente una llave de acceso y autenticarte con ella en ror-2, aunque su ID de RP sea ror-1 (y no ror-2).
  • Una vez que crees una llave de acceso en ror-1 o ror-2, podrás autenticarte con ella en ambos dispositivos.ror-1ror-2 Dado que ror-2 especifica ror-1 como un ID de RP, realizar una solicitud de creación o autenticación de llave de acceso desde cualquiera de estos sitios es lo mismo que realizar la solicitud en ror-1. El ID de RP es lo único que vincula una solicitud a un origen.
  • Una vez que crees una llave de acceso en ror-1 o ror-2, Chrome podrá autocompletarla en ambos.ror-1ror-2
  • Las credenciales creadas en cualquiera de estos sitios tendrán un ID de RP de ror-1.
Chrome autocompleta los campos en ambos sitios.
Gracias a las solicitudes de origen relacionado, los usuarios pueden usar la misma credencial de llave de acceso en ror-1 y ror-2. Chrome también autocompletará las credenciales.

Consulta el código:

Paso 1: Implementa una base de datos de cuentas compartidas

Si quieres que tus usuarios puedan acceder con la misma llave de acceso en site-1 y site-2, implementa una base de datos de cuentas que se comparta entre estos dos sitios.

Paso 2: Configura tu archivo JSON .well-known/webauthn en site-1

Primero, configura site-1.com de modo que permita que site-2.com lo use como un ID de RP. Para ello, crea tu archivo JSON de WebAuthn:

{
    "origins": [
        "https://site-2.com"
    ]
}

El objeto JSON debe contener una clave llamada origins cuyo valor sea un array de una o más cadenas que contengan orígenes web.

Limitación importante: Máximo de 5 etiquetas

Cada elemento de esta lista se procesará para extraer la etiqueta de eTLD + 1. Por ejemplo, las etiquetas de eTLD + 1 de example.co.uk y example.de son example. Sin embargo, la etiqueta eTLD + 1 de example-rewards.com es example-rewards. En Chrome, la cantidad máxima de etiquetas es 5.

Paso 3: Publica tu archivo JSON .well-known/webauthn en el sitio 1

Luego, publica tu archivo JSON en site-1.com/.well-known/webauthn.

Por ejemplo, en Express, se vería de la siguiente manera:

app.get("/.well-known/webauthn", (req, res) => {
  const origins = {
    origins: ["https://site-2.com"],
  };
  return res.json(origins);
});

Aquí, usamos res.json de Express, que ya establece el content-type correcto ('application/json').

Paso 4: Especifica el ID de RP en site-2

En tu base de código de site-2, establece site-1.comcomo el ID de RP donde sea necesario:

  • Tras la creación de la credencial, haz lo siguiente:
    • Establece site-1.com como el ID de RP en el options de creación de credenciales que se pasan a la llamada de frontend navigator.credentials.create y que, por lo general, se generan en el servidor.
    • Establece site-1.comcomo el ID de RP esperado, ya que ejecutas verificaciones de credenciales antes de guardarlas en tu base de datos.
  • Tras la autenticación, haz lo siguiente:
    • Establece site-1.com como el ID de RP en el options de autenticación que se pasa a la llamada de frontend navigator.credentials.get y que, por lo general, se genera en el servidor.
    • Establece site-1.comcomo el ID de RP esperado que se verificará en el servidor, ya que ejecutas verificaciones de credenciales antes de autenticar al usuario.

Solución de problemas

Ventana emergente de mensaje de error en Chrome.
Mensaje de error en Chrome cuando se crea una credencial. Este error se genera si no se encuentra el archivo `.well-known/webauthn` en `https://{RP ID}/.well-known/webauthn`.
Ventana emergente de mensaje de error en Chrome.
Mensaje de error en Chrome cuando se crea la credencial. Este error se genera si se encuentra tu archivo `.well-known/webauthn`, pero no se incluye el origen desde el que intentas crear una credencial.

Otras consideraciones

Cómo compartir llaves de acceso en sitios y apps para dispositivos móviles

Las solicitudes de origen relacionadas permiten que los usuarios reutilicen una llave de acceso en varios sitios. Para permitir que tus usuarios reutilicen una llave de acceso en un sitio web y una app para dispositivos móviles, usa las siguientes técnicas:

Comparte contraseñas entre sitios

Las solicitudes de origen relacionadas permiten que los usuarios reutilicen una llave de acceso en varios sitios. Las soluciones para compartir contraseñas en diferentes sitios varían según el administrador de contraseñas. Para el Administrador de contraseñas de Google, usa Vínculos de recursos digitales . Safari tiene un sistema diferente.

Rol de los administradores de credenciales y los agentes de usuario

Esto va más allá de tu alcance como desarrollador del sitio, pero ten en cuenta que, a largo plazo, el ID de RP no debería ser un concepto visible para el usuario en el agente de usuario o el administrador de credenciales que usan tus usuarios. En cambio, los administradores de credenciales y los agentes de usuario deben mostrar a los usuarios dónde se usaron sus credenciales. Este cambio demorará en implementarse. Una solución temporal sería mostrar tanto el sitio web actual como el sitio de registro original.