O guia para desenvolvedores sobre WebAuthn e implementação de chaves de acesso. Baixe a folha de referências em PDF ou use este site para ter todas as informações em um só lugar.
Lukas R.
Criado: 6 de março de 2024
Atualizado: 3 de julho de 2026

Esta página foi traduzida automaticamente. Leia a versão original em inglês aqui.
Baixe o Guia de consulta rápida de chaves de acesso gratuitamente e obtenha todos os insights.
O guia definitivo de chaves de acesso para desenvolvedores
Obtenha uma referência focada no desenvolvedor para tudo sobre chaves de acesso, cobrindo suporte de plataforma, comportamento do navegador, melhores práticas de UX e dicas de integração.

A autenticação com chaves de acesso é baseada em dois processos, também chamados de cerimônias: registro (também conhecido como fase de atestado) e login (também conhecido como fase de asserção).
Cada fase requer um desafio aleatório gerado pelo servidor, que é assinado pelo autenticador e enviado de volta ao servidor WebAuthn para verificar o usuário.
Experimente fluxos de passkeys no Passkeys Debugger.
A cerimônia de registro usa dois objetos centrais: PublicKeyCredentialCreationOptions e attestation.
A cerimônia de login usa dois objetos centrais: PublicKeyCredentialRequestOptions e assertion.
Veja quantas pessoas realmente usam passkeys.
Para o registro e login com chaves de acesso, existem quatro objetos principais:
Esta seção também explica o objeto authenticatorSelection, que é usado em 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 é o objeto central da fase de atestado (Registro). Ele é criado e retornado pelo 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": {} } }
O objeto contém estes atributos:
Assine nosso Substack de passkeys para receber as últimas novidades.
PublicKeyCredentialRequestOptions é o objeto central da fase de asserção (Login). Ele é criado e retornado pelo servidor WebAuthn.
{ "publicKeyCredentialRequestOptions": { "challenge": "pT7HMA-…dFPHk", "timeout": 500, "rpId": "passkeys.eu", "userVerification": "preferred", "allowCredentials": [], "extensions": [] } }
O objeto contém estes atributos:
Durante a Cerimônia de Atestado / Registro, o Autenticador retorna esta Resposta de Registro. Você pode testar isso por si mesmo no 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": {} }
O attestation contém alguns componentes importantes como attestationObject, algorithm e as flags de transport.
Retirado da especificação Webauthn da W3C
O attestationObject é um objeto codificado em CBOR, contendo informações sobre as credenciais recém-criadas, a chave pública e outros dados relevantes:
Leia mais sobre as extensões.
As chaves de acesso são geradas com algoritmos COSE, indicando o algoritmo usado no atributo algorithm de parsedCredentialPublicKey no objeto de atestado.
Aqui está uma visão geral dos algoritmos COSE mais relevantes:
A propriedade transports indica os mecanismos através dos quais um autenticador pode se comunicar com um cliente. Algumas combinações de valores de exemplo comuns são:
Durante a Cerimônia de Asserção / Login, o Autenticador retorna esta Resposta de Login. Você pode testar isso por si mesmo no 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" } }
A assertion contém alguns componentes importantes como flags, signature e userHandle.
Aqui está uma visão geral das flags mais relevantes e suas combinações:
A signature é usada para verificar se o usuário que está tentando fazer login possui a chave privada. A assinatura é criada concatenando o authenticatorData e o clientDataHash (ou seja, a versão SHA-256 de ClientDataJSON) e assinando o resultado com a chave privada (no autenticador). Para verificar com a chave pública, também concatenamos o authenticatorData e o clientDataHash. Se o resultado da verificação retornar verdadeiro, a autenticação será bem-sucedida.
O userHandle é o user_id real. Leia mais sobre o user_id na seção 4.1 Esquema de banco de dados.
O objeto authenticatorSelection permite que o servidor dite as configurações para o autenticador e a criação de credenciais com os seguintes valores:
Resident Keys (também chamadas de Discoverable Credential): As chaves residentes são armazenadas no autenticador e recuperadas durante a autenticação. Dessa forma, o cliente pode descobrir uma lista de chaves possíveis, e é por isso que a [Conditional UI](/blog/user-transition-passkeys-> conditional-ui) exige chaves residentes. Non-Resident Keys (também chamadas de Non-Discoverable Credential): No caso de chaves não residentes, a credencial ID é armazenada no servidor e fornecida durante a autenticação. A credencial ID é um identificador opaco cuja estrutura interna é específica da implementação — os autenticadores podem armazenar chaves privadas diretamente, usar agrupamento de chaves criptografado (key wrapping) ou derivar chaves de segredos internos. O mecanismo exato varia de acordo com a implementação do autenticador.
Aviso: Se for definido como "Preferred", o usuário ou seu dispositivo pode ignorar a verificação do usuário no processo de autenticação (leia mais neste artigo).
A Conditional UI (preenchimento automático de chave de acesso) exibe as chaves de acesso disponíveis em uma lista suspensa de seleção para o usuário, quando um usuário possui uma chave residente registrada no Relying Party. Ela melhora a usabilidade das chaves de acesso, mas exige esforços adicionais de desenvolvimento e não está disponível para todas as combinações de SO/navegador.
Como um login normal, a Conditional UI também usa os objetos PublicKeyCredentialRequestOptions e assertion.
A Conditional UI não está disponível em todas as combinações de sistemas operacionais e navegadores (ainda). Aqui está uma visão geral da cobertura atual do navegador (março de 2024):
Para obter uma visão geral atualizada, acesse este site.
Um código completo e minimalista para um método de Conditional UI é o seguinte:
<!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 { // recupera as request options (incl. o challenge) do 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>
A Conditional UI funciona apenas com chaves residentes (resident keys) / credenciais detectáveis.
Recomenda-se fornecer um endpoint de servidor diferente para iniciar o login da Conditional UI.
O cliente precisa atender a vários requisitos:
Para evitar erros, o servidor deve testar primeiro a disponibilidade dos clientes com esta função: No tráfego real, problemas de detecção e ciclo de vida costumam surgir como NotAllowedError ou AbortError. Use o guia de erros de WebAuthn para classificação de erros esperados vs. inesperados, incluindo erros de chaves de acesso nativas no Gerenciador de Credenciais (Credential Manager).
// fonte: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable#examples // A disponibilidade de `window.PublicKeyCredential` significa que o WebAuthn pode ser usado. if (window.PublicKeyCredential && PublicKeyCredential.isConditionalMediationAvailable) { // Verifica se a mediação condicional está disponível. const isCMA = await PublicKeyCredential.isConditionalMediationAvailable(); if (isCMA) { // Chama o endpoint de início de autenticação do WebAuthn let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); /* ... */ } }
O campo de entrada deve receber um token de preenchimento automático (autofill) HTML, que sinaliza ao cliente para preencher chaves de acesso na solicitação em andamento. Além de chaves de acesso, os tokens de preenchimento automático podem ser combinados com tokens existentes, por exemplo, nomes de usuário e senhas:
<label for="name">Nome de usuário:</label> <input type="text" name="name" autocomplete="username webauthn" /> <label for="password">Senha:</label> <input type="password" name="password" autocomplete="current-password webauthn" />
Não há um esquema de banco de dados obrigatório ou padronizado para servidores WebAuthn. No entanto, este exemplo de esquema de banco de dados pode ser usado para armazenar as informações necessárias e fornecer todas as funcionalidades de um servidor WebAuthn:
Os atributos em negrito são obrigatórios para uma implementação viável mínima, enquanto os outros são necessários apenas para recursos opcionais, mas úteis.
User DisplayName (user.displayName): Nome amigável e legível que normalmente é o nome completo do usuário. Ele é exibido para o usuário, mas não é usado durante a autenticação.
User Name (user.name): Nome exclusivo e legível que normalmente é um endereço de e-mail ou um nome de usuário. Ele pode ser exibido para o usuário, mas não é usado durante a autenticação.
O Relying Party ID (rpID) é um domínio armazenado na chave de acesso, garantindo que a chave de acesso só funcione para o domínio correto (URL do navegador; consulte este artigo para aplicativos nativos). Durante a autenticação, o rpID é verificado em relação à URL do navegador e é permitido apenas nestes dois casos:
Aqui estão exemplos de combinações permitidas (ou não):
Aqui está uma lista de ferramentas e sites úteis para a implementação de chaves de acesso.
chrome://device-log).Para estratégias sobre a otimização de UX de chaves de acesso além da implementação técnica, consulte nossos guias sobre práticas recomendadas de criação de chaves de acesso e práticas recomendadas de login com chaves de acesso.
Se quiser implementar chaves de acesso com apenas algumas linhas de código em qualquer aplicativo, você também pode usar o Corbado Complete (para novos aplicativos) ou o Corbado Connect (para aplicativos existentes).
Corbado é a Authentication Intelligence Platform para times de CIAM que rodam autenticação consumer em escala. Mostramos o que logs de IDP e ferramentas genéricas de analytics não enxergam: quais dispositivos, versões de SO, navegadores e gerenciadores de credenciais suportam passkeys, por que os registros não viram logins, onde o fluxo WebAuthn falha e quando uma atualização de SO ou navegador quebra silenciosamente o login — tudo sem substituir Okta, Auth0, Ping, Cognito ou seu IDP interno. Dois produtos: Corbado Observe adiciona observabilidade para passkeys e qualquer outro método de login. Corbado Connect entrega passkeys gerenciados com analytics integrado (junto ao seu IDP). VicRoads roda passkeys para mais de 5M de usuários com Corbado (+80% de ativação de passkey). Fale com um especialista em Passkeys →
A Conditional UI requer a verificação do suporte do navegador por meio de PublicKeyCredential.isConditionalMediationAvailable() antes de iniciar a autenticação. O campo de entrada (input) deve incluir o token HTML autocomplete="username webauthn" e o usuário deve ter uma chave residente (resident key / credencial detectável) registrada. Recomenda-se um endpoint de servidor separado para lidar com o fluxo de login da Conditional UI.
No mínimo, armazene a Credential ID, gerada pelo autenticador durante o registro, e o User ID (user_id), que é retornado como o userHandle no objeto de asserção. Use a Credential ID para pesquisar a conta de usuário associada e compare o userHandle para validar a autenticação. Evite usar user.name para comparação, pois ele pode mudar com o tempo.
As chaves residentes (credenciais detectáveis) são armazenadas no próprio autenticador e recuperadas durante a autenticação, o que é necessário para que a Conditional UI funcione. As chaves não residentes armazenam a ID da credencial no servidor e a enviam ao autenticador durante a autenticação. O campo residentKey em authenticatorSelection controla esse comportamento com os valores "required", "preferred" ou "discouraged".
O campo userVerification controla se o autenticador deve verificar o usuário durante o login, aceitando os valores "required", "preferred" (padrão) ou "discouraged". Quando definido como "preferred", o usuário ou seu dispositivo pode ignorar totalmente a verificação durante o processo de autenticação, o que pode enfraquecer a segurança. Defini-lo como "required" garante que a verificação sempre ocorra antes da conclusão da autenticação.
Veja como a Corbado se encaixa na sua implementação de passkeys e no stack de autenticação atual.
Explorar a Console
Artigos relacionados
Índice