En este documento, se explica qué es userVerification
en WebAuthn y los comportamientos del navegador que se producen cuando se especifica userVerification
durante la creación o la autenticación de la llave de acceso.
¿Qué es la "verificación del usuario" en WebAuthn?
Las llaves de acceso se basan en la criptografía de clave pública. Cuando se crea una llave de acceso, se genera un par de claves públicas y privadas, el proveedor de la llave de acceso almacena la clave privada y la clave pública se devuelve al servidor de la parte que confía (RP) para que la almacene. El servidor puede autenticar a un usuario verificando una firma firmada por la misma llave de acceso con la clave pública vinculada. La marca "usuario presente" (UP) en una credencial de clave pública demuestra que alguien interactuó con el dispositivo durante la autenticación.
La verificación del usuario es una capa de seguridad opcional que busca confirmar que la persona correcta estuvo presente durante la autenticación, no solo alguna persona, como lo afirma la presencia del usuario. En los smartphones, esto se suele hacer con el mecanismo de bloqueo de pantalla, ya sea biométrico o con un PIN o una contraseña. El indicador "UV" que se devuelve en los datos del autenticador durante el registro y la autenticación con llave de acceso indica si se realizó la verificación del usuario.


Cómo se validan UP y UV en el servidor
Los parámetros booleanos de presencia del usuario (UP) y usuario verificado (UV) se indican al servidor en el campo de datos del autenticador. Durante la autenticación, se puede validar el contenido del campo de datos del autenticador verificando la firma con la clave pública almacenada. Siempre que la firma sea válida, el servidor puede considerar que las marcas son auténticas.
![Representación de la estructura de datos de autenticación. De izquierda a derecha, cada sección de la estructura de datos indica "HASH DE ID DE RP" (32 bytes), "MARCADORES" (1 byte), "CONTADOR" (4 bytes, uint32 big-endian), "CRED. DE CERTIFICACIÓN" DATA" (longitud variable si está presente) y "EXTENSIONS" (longitud variable si está presente [CBOR]). La sección "FLAGS" se expande para mostrar una lista de posibles marcas, etiquetadas de izquierda a derecha: "ED", "AT", "0", "BS", "BE", "UV", "0" y "UP".](https://web-dot-devsite-v2-prod-3p.appspot.com/static/articles/webauthn-user-verification/image/fig-3.png?hl=es)
Durante el registro y la autenticación con llave de acceso, el servidor debe examinar si la marca UP es true
o false
, y si la marca UV es true
o false
, según el requisito.
Cómo especificar el parámetro userVerification
Según la especificación de WebAuthn, la RP puede solicitar una verificación del usuario con un parámetro userVerification
tanto en la creación como en la aserción de credenciales. Acepta 'preferred'
, 'required'
o 'discouraged'
, que significan lo siguiente, respectivamente:
'preferred'
(predeterminado): Se prefiere usar un método de verificación del usuario en el dispositivo, pero se puede omitir si no está disponible. La credencial de respuesta contiene un valor de la marca UV detrue
si se realizó la verificación del usuario yfalse
si no se realizó la UV.'required'
: Se requiere invocar un método de verificación del usuario disponible en el dispositivo. Si no hay uno disponible, la solicitud falla de forma local. Esto significa que la credencial de respuesta siempre se devuelve con la marca de UV establecida entrue
.'discouraged'
: No se recomienda usar un método de verificación del usuario. Sin embargo, según el dispositivo, es posible que se realice la verificación del usuario de todos modos, y la marca UV puede contenertrue
ofalse
.
Código de muestra para la creación de llaves de acceso:
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
userVerification: 'preferred'
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
Código de muestra para la autenticación con llave de acceso:
const publicKeyCredentialRequestOptions = {
challenge: /* Omitted challenge data... */,
rpId: 'example.com',
userVerification: 'preferred'
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions
});
¿Qué opción deberías elegir para userVerification
?
El valor de userVerification
que debes usar depende de los requisitos de tu aplicación y de las necesidades de la experiencia del usuario.
Cuándo usar userVerification='preferred'
Usa userVerification='preferred'
si priorizas la experiencia del usuario por sobre la protección.
Existen entornos en los que la verificación del usuario genera más fricción que protección. Por ejemplo, en macOS donde Touch ID no está disponible (porque el dispositivo no lo admite, está deshabilitado o el dispositivo está en modo clamshell), se le solicita al usuario que ingrese su contraseña del sistema. Esto genera fricción, y es posible que el usuario abandone la autenticación por completo. Si eliminar la fricción es más importante para ti, usa userVerification='preferred'
.

Con userVerification='preferred'
, la marca de verificación del usuario es true
si la verificación del usuario se realiza correctamente y false
si se omite. Por ejemplo, en macOS, donde Touch ID no está disponible, se le pide al usuario que haga clic en un botón para omitir la verificación del usuario, y la credencial de clave pública incluye una marca de UV false
.
Luego, la marca de UV puede ser un indicador en tu análisis de riesgo. Si el intento de acceso parece riesgoso debido a otros factores, es posible que desees presentar desafíos de acceso adicionales al usuario si no se realizó la verificación del usuario.
Cuándo usar userVerification='required'
Usa userVerification='required'
si crees que tanto el UP como el UV son absolutamente necesarios.
Un inconveniente de esta opción es que el usuario puede experimentar más fricción al acceder. Por ejemplo, en macOS, donde Touch ID no está disponible, se le pide al usuario que ingrese la contraseña del sistema.
Con userVerification='required'
, puedes asegurarte de que la verificación del usuario se realice en el dispositivo. Asegúrate de que el servidor verifique que la marca de UV sea true
.
Conclusión
Al aprovechar la verificación del usuario, las partes que confían en las llaves de acceso pueden evaluar la probabilidad de que el propietario del dispositivo acceda. Pueden elegir si requieren la verificación del usuario o si la hacen opcional, según la importancia del mecanismo de acceso alternativo en el flujo del usuario. Asegúrate de que el servidor verifique los indicadores UP y UV para la autenticación del usuario con llave de acceso.