La guía para desarrolladores sobre WebAuthn y la implementación de claves de acceso. Descargue la hoja de trucos en PDF o utilice este sitio web.
Lukas R.
Creado: 6 de marzo de 2024
Actualizado: 3 de julio de 2026

Esta página se tradujo automáticamente. Lee la versión original en inglés aquí.
Descargue la hoja de trucos de claves de acceso completa de forma gratuita y obtenga toda la información.
Guía definitiva para desarrolladores de claves de acceso
Obtenga una referencia enfocada en desarrolladores para todo lo relacionado con las claves de acceso, cubriendo soporte de plataforma, comportamiento del navegador, mejores prácticas de UX y consejos de integración.

La autenticación con claves de acceso se basa en los dos procesos, también llamados ceremonias, registro (también conocido como la fase de atestación) e inicio de sesión (también conocido como la fase de aserción).
Cada fase requiere un desafío aleatorio generado por el servidor, que es firmado por el autenticador y enviado de vuelta al servidor WebAuthn para verificar al usuario.
Experimenta con flujos de passkeys en Passkeys Debugger.
La ceremonia de registro utiliza dos objetos centrales: PublicKeyCredentialCreationOptions y atestación.
La ceremonia de inicio de sesión utiliza dos objetos centrales: PublicKeyCredentialRequestOptions y aserción.
Consulta cuántas personas usan passkeys realmente.
Para el registro y el inicio de sesión con claves de acceso, hay cuatro objetos principales:
Esta sección también explica el objeto authenticatorSelection, que se utiliza en PublicKeyCredentialCreationOptions.
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
We hit 80% mobile passkey activation across 5M+ users without replacing our IDP.
See how VicRoads scaled passkeys to 5M+ users — alongside their existing IDP.
Read the case studyPublicKeyCredentialCreationOptions es el objeto central de la fase de atestación (Registro). Es creado y devuelto por el servidor WebAuthn.
{ "PublicKeyCredentialCreationOptions": { "rp": { "id": "passkeys.eu", "name": "Corbado Passkeys Demo" }, "user": { "displayName": "john.doe", "id": "dXNyLZ….DU10Tc", "name": "john@doe.com" }, "challenge": "888fix4Bus...pHHr3Y", "pubKeyCredParams": [ { "alg": -7, "type": "public-key" }, { "alg": -257, "type": "public-key" } ], "excludeCredentials": [], "authenticatorSelection": { "authenticatorAttachment": "platform", "residentKey": "required", "userVerification": "required" }, "attestation": "none", "extensions": {} } }
El objeto contiene estos atributos:
Suscríbete a nuestro Substack de passkeys para recibir las últimas noticias.
PublicKeyCredentialRequestOptions es el objeto central de la fase de aserción (Inicio de sesión). Es creado y devuelto por el servidor WebAuthn.
{ "publicKeyCredentialRequestOptions": { "challenge": "pT7HMA-…dFPHk", "timeout": 500, "rpId": "passkeys.eu", "userVerification": "preferred", "allowCredentials": [], "extensions": [] } }
El objeto contiene estos atributos:
Durante la ceremonia de atestación / registro, el autenticador devuelve esta respuesta de registro. Puede probar esto usted mismo en el Passkeys Debugger.
{ "authenticatorAttachment": "platform", "id": "JKZbixUfKN_aZtimefYT-OjH5dw", "rawId": "JKZbixUfKN_aZtimefYT-OjH5dw", "response": { "attestationObject": { "fmt": "none", "attStmt": {}, "authData": { "rpIdHash": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkM", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": true, "extensionData": false }, "counter": 0, "aaguid": { "raw": "fbfc3007-154e-4ecc-8c0b-6e020557d7bd", "name": "iCloud Keychain" }, "credentialID": "JKZbixUfKN_aZtimefYT-OjH5dw", "credentialPublicKey": "pQECAyYgASFYIPWLalDzyxIDmAADvfK8iNM5To50kh7TyPH-teEz8RMdIlgg3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA", "parsedCredentialPublicKey": { "keyType": "EC2 (2)", "algorithm": "ES256 (-7)", "curve": 1, "x": "9YtqUPPLEgOYAAO98ryI0zlOjnSSHtPI8f614TPxEx0", "y": "3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA" } } }, "clientDataJSON": { "type": "webauthn.create", "challenge": "k2p6f-upzP_hc6NZvmMAxiI0VSTeQIeXXVRGW62LTj0", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false }, "transports": ["hybrid", "internal"], "authenticatorData": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkNdAAAAAPv8MAcVTk7MjAtuAgVX170AFCSmW4sVHyjf2mbYpnn2E_jox-XcpQECAyYgASFYIPWLalDzyxIDmAADvfK8iNM5To50kh7TyPH-teEz8RMdIlgg3D7bPIWQJ8z-WFn3zdYZzJw9c7mhPdmflQqD9vV7efA", "publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9YtqUPPLEgOYAAO98ryI0zlOjnSSHtPI8f614TPxEx3cPts8hZAnzP5YWffN1hnMnD1zuaE92Z-VCoP29Xt58A", "publicKeyAlgorithm": -7 }, "type": "public-key", "clientExtensionResults": {} }
La atestación contiene algunos componentes importantes como attestationObject, algorithm y los indicadores de transport.
Tomado de la especificación WebAuthn del W3C
El attestationObject es un objeto codificado en CBOR, que contiene información sobre las credenciales recién creadas, la clave pública y otros datos relevantes:
Lea más sobre las extensiones.
Las claves de acceso se generan con algoritmos COSE, indicando el algoritmo utilizado en el atributo de algoritmo de parsedCredentialPublicKey en el objeto de atestación.
Aquí hay una descripción general de los algoritmos COSE más relevantes:
La propiedad transports indica los mecanismos a través de los cuales un autenticador puede comunicarse con un cliente. Algunas combinaciones de valores comunes de muestra son:
Durante la ceremonia de aserción / inicio de sesión, el autenticador devuelve esta respuesta de inicio de sesión. Puede probar esto usted mismo en el Passkeys Debugger.
{ "id": "JKZbixUfKN_aZtimefYT-OjH5dw", "rawId": "JKZbixUfKN_aZtimefYT-OjH5dw", "type": "public-key", "authenticatorAttachment": "platform", "response": { "authenticatorData": { "rpIdHash": "PpZrl-Wqt-OFfBpyy2SraN1m7LT0GZORwGA7-6ujYkM", "flags": { "userPresent": true, "userVerified": true, "backupEligible": true, "backupStatus": true, "attestedData": false, "extensionData": false }, "counter": 0 }, "clientDataJSON": { "type": "webauthn.get", "challenge": "GCVkITWbe2l2dttsn_DgJYvH9QPHPDo0ygWgcgI6B7U", "origin": "https://www.passkeys-debugger.io", "crossOrigin": false, "other_keys_can_be_added_here": "do not compare clientDataJSON against a template. See https://goo.gl/yabPex" }, "signature": "MEQCIA-orC8N2KKWOxyY17BWP8lB-Be5to9btXRnJZf2SLhXAiBGxJe5Eu5LwOTbsyzAYmIXHOhlC3pN7s7Q1fRLvEW57g", "userHandle": "_FKz1uwqmR_3yGq6hJntzoIFwFC_d1u_53YRELh0KlE" } }
La aserción contiene algunos componentes importantes como indicadores, firma y userHandle.
Aquí hay una descripción general de los indicadores más relevantes y sus combinaciones:
La firma se utiliza para verificar que el usuario que intenta iniciar sesión realmente tiene la clave privada. La firma se crea concatenando el authenticatorData y el clientDataHash (es decir, la versión SHA-256 de ClientDataJSON) y firmando el resultado con la clave privada (en el autenticador). Para verificar con la clave pública, también concatenamos authenticatorData y clientDataHash. Si el resultado de la verificación devuelve verdadero, la autenticación es exitosa.
El userHandle es el user_id real. Lea más sobre el user_id en la sección 4.1 Esquema de base de datos.
El objeto authenticatorSelection permite al servidor dictar configuraciones para el autenticador y la creación de credenciales con los siguientes valores:
Claves residentes (también llamadas credenciales descubribles): Las claves residentes se almacenan en el autenticador y se recuperan durante la autenticación. De esta manera, el cliente puede descubrir una lista de claves posibles, que es la razón por la que Conditional UI requiere claves residentes. Claves no residentes (también llamadas credenciales no descubribles): En el caso de claves no residentes, el ID de la credencial se almacena en el servidor y se proporciona durante la autenticación. El ID de la credencial es un identificador opaco cuya estructura interna es específica de la implementación: los autenticadores pueden almacenar claves privadas directamente, usar envoltura de claves encriptadas o derivar claves de secretos internos. El mecanismo exacto varía según la implementación del autenticador.
Advertencia: Si se establece en "Preferred", el usuario o su dispositivo pueden omitir la verificación de usuario en el proceso de autenticación (lea más en este artículo).
Conditional UI (autocompletado de claves de acceso) muestra las claves de acceso disponibles en un menú desplegable de selección para el usuario, cuando un usuario tiene una clave residente registrada en el relying party. Mejora la usabilidad de las claves de acceso, pero requiere esfuerzos de desarrollo adicionales y no está disponible para todas las combinaciones de sistemas operativos / navegadores.
Al igual que un inicio de sesión regular, Conditional UI también utiliza los objetos PublicKeyCredentialRequestOptions y aserción
Conditional UI no está disponible en todas las combinaciones de sistemas operativos y navegadores (todavía). Aquí hay una descripción general de la cobertura actual del navegador (marzo de 2024):
Para obtener una descripción general actualizada, consulte este sitio web.
Un código minimalista completo para un método de Conditional UI se ve así:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Conditional UI</title> </head> <body> <input type="text" id="username" autocomplete="username webauthn" /> <script> async function passkeyLogin() { try { // recuperar las opciones de solicitud (incl. el desafío) del servidor WebAuthn let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); const userData = await WebAuthnClient.sendSignedChallenge(credential); window.location.href = "/logged-in"; } catch (error) { console.log(error); } } passkeyLogin(); </script> </body> </html>
Conditional UI solo funciona con claves residentes / credenciales descubribles
Se recomienda proporcionar un punto final de servidor diferente para iniciar el inicio de sesión de Conditional UI.
El cliente debe cumplir con varios requisitos:
Para evitar errores, el servidor debe probar primero la disponibilidad del cliente con esta función:
En tráfico real, los problemas de detección y ciclo de vida a menudo surgen como NotAllowedError o AbortError. Use esta guía de errores de WebAuthn para la clasificación de lo esperado frente a lo inesperado, incluidos los errores de claves de acceso nativas del administrador de credenciales.
// fuente: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable#examples // La disponibilidad de `window.PublicKeyCredential` significa que WebAuthn se puede usar. if (window.PublicKeyCredential && PublicKeyCredential.isConditionalMediationAvailable) { // Comprobar si la mediación condicional está disponible. const isCMA = await PublicKeyCredential.isConditionalMediationAvailable(); if (isCMA) { // Llamar al punto final de inicio de autenticación WebAuthn let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); /* ... */ } }
El campo de entrada debe recibir un token de autocompletado HTML que indique al cliente que popule las claves de acceso en la solicitud en curso. Además de las claves de acceso, los tokens de autocompletado se pueden emparejar con tokens existentes, por ejemplo, nombres de usuario y contraseñas:
<label for="name">Nombre de usuario:</label> <input type="text" name="name" autocomplete="username webauthn" /> <label for="password">Contraseña:</label> <input type="password" name="password" autocomplete="current-password webauthn" />
No existe un esquema de base de datos obligatorio o estandarizado para los servidores WebAuthn. Sin embargo, este esquema de base de datos de ejemplo se puede usar para almacenar la información requerida y proporcionar todas las funcionalidades de un servidor WebAuthn:
Los atributos en negrita son obligatorios para una implementación viable mínima, mientras que los demás solo son necesarios para funciones opcionales pero útiles.
User DisplayName (user.displayName): Nombre legible y amigable para el usuario que generalmente es el nombre completo del usuario. Se muestra al usuario, pero no se usa durante la autenticación.
User Name (user.name): Nombre único y legible que generalmente es una dirección de correo electrónico o un nombre de usuario. Se puede mostrar al usuario, pero no se usa durante la autenticación.
El Relying Party ID (rpID) es un dominio almacenado dentro de la clave de acceso, que garantiza que la clave de acceso solo funcione para el dominio correcto (URL del navegador, consulte este artículo para aplicaciones nativas). Durante la autenticación, el rpID se compara con la URL del navegador y solo se permite en estos dos casos:
Aquí hay ejemplos de combinaciones (no) permitidas:
Aquí hay una lista de herramientas y sitios web útiles para implementar claves de acceso.
chrome://device-log)Para conocer estrategias sobre cómo optimizar la experiencia del usuario (UX) de sus claves de acceso más allá de la implementación técnica, consulte nuestras guías sobre las mejores prácticas de creación de claves de acceso y las mejores prácticas de inicio de sesión con claves de acceso.
Si desea implementar claves de acceso con solo unas pocas líneas de código en cualquier aplicación, también puede usar Corbado Complete (para nuevas aplicaciones) o Corbado Connect (para aplicaciones existentes)
Corbado es la Authentication Intelligence Platform para equipos de CIAM que gestionan autenticación de consumidores a gran escala. Te ayudamos a ver lo que los logs de tu IDP y las herramientas de analytics genéricas no muestran: qué dispositivos, versiones de SO, navegadores y gestores de credenciales soportan passkeys, por qué los registros no se convierten en inicios de sesión, dónde falla el flujo de WebAuthn y cuándo una actualización de SO o navegador rompe el login en silencio — todo sin reemplazar Okta, Auth0, Ping, Cognito o tu IDP propio. Dos productos: Corbado Observe aporta observabilidad para passkeys y cualquier otro método de login. Corbado Connect añade passkeys gestionados con analytics integrado (junto a tu IDP). VicRoads ejecuta passkeys para más de 5M de usuarios con Corbado (+80 % de activación de passkey). Habla con un experto en Passkeys →
Conditional UI requiere verificar el soporte del navegador mediante PublicKeyCredential.isConditionalMediationAvailable() antes de iniciar la autenticación. El campo de entrada debe incluir el token HTML autocomplete="username webauthn" y el usuario debe tener una clave residente (credencial descubrible) registrada. Se recomienda un endpoint de servidor separado para manejar el flujo de inicio de sesión de Conditional UI.
Como mínimo, almacene el Credential ID, generado por el autenticador durante el registro, y el User ID (user_id), que se devuelve como userHandle en el objeto de aserción. Utilice el Credential ID para buscar la cuenta de usuario asociada y compare el userHandle para validar la autenticación. Evite usar user.name para la comparación, ya que puede cambiar con el tiempo.
Las claves residentes (credenciales descubribles) se almacenan en el propio autenticador y se recuperan durante la autenticación, lo cual es necesario para que funcione Conditional UI. Las claves no residentes almacenan el Credential ID en el servidor y lo envían al autenticador durante la autenticación. El campo residentKey en authenticatorSelection controla este comportamiento con los valores "required", "preferred" o "discouraged".
El campo userVerification controla si el autenticador debe verificar al usuario durante el inicio de sesión, aceptando los valores "required", "preferred" (predeterminado) o "discouraged". Cuando se establece en "preferred", el usuario o su dispositivo pueden omitir la verificación por completo durante el proceso de autenticación, lo que podría debilitar la seguridad. Establecerlo en "required" garantiza que la verificación siempre se realice antes de que se complete la autenticación.
Mira cómo Corbado encaja con tu despliegue de passkeys y tu stack de autenticación actual.
Explorar la Console
Artículos relacionados
Tabla de contenidos