Crie uma experiência de login que aproveite as chaves de acesso e ainda acomode os usuários de senhas.
Este guia explica como usar o preenchimento automático de formulários para permitir que os usuários façam login com chaves de acesso e senhas. O uso do preenchimento automático de formulários cria uma experiência de login unificada, simplificando a transição de senhas para o método de autenticação de chaves de acesso mais seguro e fácil de usar.
Aprenda a implementar a interface condicional da WebAuthn para oferecer suporte a usuários de chaves de acesso e senhas com o mínimo de atrito nos formulários de login atuais.
Por que usar o preenchimento automático de formulários para fazer login com uma chave de acesso?
As chaves de acesso permitem que os usuários façam login em sites usando impressão digital, reconhecimento facial ou PIN do dispositivo.
Se todos os usuários tivessem chaves de acesso, o fluxo de autenticação poderia ser um único botão de login. Ao tocar no botão, o usuário poderia verificar a conta diretamente com o bloqueio de tela e fazer login.
No entanto, a transição de senhas para chaves de acesso apresenta desafios. Os sites precisam oferecer suporte a usuários de senhas e chaves de acesso durante esse período. Esperar que os usuários se lembrem de quais sites usam chaves de acesso e pedir que eles escolham um método de login antecipadamente cria uma experiência ruim para o usuário.
As chaves de acesso também são uma tecnologia nova, e explicar isso claramente pode ser difícil. Usar a interface de preenchimento automático conhecida ajuda a resolver o desafio da transição e a necessidade de familiaridade do usuário.
Usar a interface condicional
Para oferecer suporte eficaz aos usuários de chaves de acesso e senhas, inclua chaves de acesso nas sugestões de preenchimento automático do formulário. Essa abordagem usa a interface condicional, um recurso do padrão WebAuthn.
Quando o usuário se concentra no campo de entrada de nome de usuário, uma caixa de diálogo de preenchimento automático aparece, sugerindo chaves de acesso armazenadas e senhas salvas. O usuário pode selecionar uma chave de acesso ou uma senha e fazer login usando o bloqueio de tela do dispositivo, se escolher uma chave de acesso.
Isso permite que os usuários façam login no seu site com o formulário de login atual, mas com o benefício de segurança adicional das chaves de acesso se eles tiverem uma.
Como a autenticação de chave de acesso funciona
Para fazer a autenticação com uma chave de acesso, use a API WebAuthn.
Os quatro componentes de um fluxo de autenticação de chave de acesso são:
- Back-end: armazena os detalhes da conta do usuário, incluindo a chave pública.
- Front-end: se comunica com o navegador e busca os dados necessários do back-end.
- Navegador: executa seu JavaScript e interage com a API WebAuthn.
- Provedor de chaves de acesso: cria e armazena a chave de acesso. Normalmente, é um gerenciador de senhas, como o Gerenciador de senhas do Google, ou uma chave de segurança.

O processo de autenticação de chaves de acesso segue este fluxo:
- O usuário acessa a página de login, e o front-end solicita uma tarefa de autenticação do back-end.
- O back-end gera e retorna uma solicitação da WebAuthn associada à conta do usuário.
- O front-end chama
navigator.credentials.get()
com o desafio para iniciar a autenticação usando o navegador. - O navegador, interagindo com o provedor de chaves de acesso, solicita que o usuário selecione uma chave de acesso (geralmente usando uma caixa de diálogo de preenchimento automático acionada pelo foco no campo de login) e verifique a identidade usando o bloqueio de tela do dispositivo ou a biometria.
- Depois da verificação do usuário, o provedor de chave de acesso assina o desafio, e o navegador retorna a credencial de chave pública resultante (incluindo a assinatura) para o front-end.
- O front-end envia essa credencial para o back-end.
- O back-end verifica a assinatura da credencial com a chave pública armazenada do usuário. Se a verificação for bem-sucedida, o back-end vai fazer login do usuário.
Autenticar com uma chave de acesso usando o preenchimento automático de formulários
Para iniciar a autenticação de chave de acesso usando o preenchimento automático de formulários, faça uma chamada condicional
de get
do WebAuthn quando a página de login for carregada. Essa chamada para
navigator.credentials.get()
inclui a opção mediation: 'conditional'
.
Uma solicitação condicional para a API navigator.credentials.get()
da WebAuthn não mostra a interface imediatamente. Em vez disso, ele
espera em um estado pendente até que o usuário interaja com o comando de preenchimento automático
do campo de nome de usuário. Se o usuário selecionar uma chave de acesso, o navegador vai resolver a promessa pendente
com uma credencial para fazer login no usuário, ignorando o envio tradicional
de formulários. Se o usuário escolher uma senha, a promessa não será resolvida
e o fluxo de login de senha padrão continuará.rm. A responsabilidade
de fazer o login do usuário é da página.
Fazer anotações no campo de entrada do formulário
Para ativar o preenchimento automático de chave de acesso, adicione o atributo autocomplete
ao campo
input
de nome de usuário do formulário. Inclua username
e webauthn
como
valores separados por espaços.
<input type="text" name="username" autocomplete="username webauthn" autofocus>
Adicionar autofocus
a esse campo aciona automaticamente o comando de preenchimento automático na
carregamento da página, mostrando as senhas e chaves-senha disponíveis imediatamente.
Detecção de recursos
Antes de invocar uma chamada condicional da API WebAuthn, verifique se:
- O navegador oferece suporte para WebAuthn com
PublicKeyCredential
.
- O navegador oferece suporte à IU condicional
do WebAuthn com
PublicKeyCredential.isConditionalMediationAvailable()
.
O snippet a seguir mostra como verificar se o navegador oferece suporte a esses recursos:
// Availability of window.PublicKeyCredential means WebAuthn is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if conditional mediation is available.
const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
if (isCMA) {
// Call WebAuthn authentication
}
}
Buscar informações do back-end
O back-end precisa fornecer várias opções ao front-end para iniciar a
chamada navigator.credentials.get()
. Essas opções geralmente são buscadas como um
objeto JSON de um endpoint no seu servidor.
As principais propriedades no objeto de opções incluem:
challenge
: um desafio gerado pelo servidor em um ArrayBuffer (normalmente codificado em Base64URL para transporte JSON). Isso é essencial para evitar ataques repetidos. Seu servidor precisa gerar um novo desafio para cada tentativa de login e precisa invalidá-lo após um curto período ou se uma tentativa falhar.allowCredentials
: uma matriz de descritores de credencial. Transmita uma matriz vazia. Isso faz com que o navegador liste todas as credenciais para orpId
especificado.userVerification
: especifica sua preferência de verificação de usuário, como exigir um bloqueio de tela do dispositivo. O valor padrão e recomendado é"preferred"
. Os valores possíveis são:"required"
: a verificação do usuário precisa ser realizada pelo autenticador (como PIN ou biometria). A operação falha se a verificação não puder ser realizada."preferred"
: o autenticador tenta fazer a verificação do usuário, mas a operação pode ser bem-sucedida sem ele."discouraged"
: o autenticador precisa evitar a verificação do usuário, se possível.
rpId
: o ID da parte confiável, geralmente o domínio do seu site (comoexample.com
). Esse valor precisa corresponder exatamente aorp.id
usado quando a credencial de chave de acesso foi criada.
Seu servidor precisa construir esse objeto de opções. Os valores ArrayBuffer
(como o
challenge
) precisam ser codificados em Base64URL para transporte JSON. No front-end,
depois de analisar o JSON, use PublicKeyCredential.parseRequestOptionsFromJSON()
para converter o objeto (incluindo a decodificação de strings Base64URL) no formato
esperado por navigator.credentials.get()
.
O snippet de código abaixo mostra como buscar e decodificar as informações necessárias para autenticar com uma chave de acesso.
// Fetch an encoded PubicKeyCredentialRequestOptions from the server.
const _options = await fetch('/webauthn/signinRequest');
// Deserialize and decode the PublicKeyCredentialRequestOptions.
const decoded_options = JSON.parse(_options);
const options = PublicKeyCredential.parseRequestOptionsFromJSON(decoded_options);
...
Chamar a API WebAuthn com a flag conditional
para autenticar o usuário
Depois de preparar o objeto publicKeyCredentialRequestOptions
(chamado de
options
no exemplo de código abaixo), chame
navigator.credentials.get()
para iniciar a autenticação de chave de acesso condicional.
// To abort a WebAuthn call, instantiate an AbortController.
const abortController = new AbortController();
// Invoke WebAuthn to authenticate with a passkey.
const credential = await navigator.credentials.get({
publicKey: options,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
Principais parâmetros para essa chamada:
publicKey
: precisa ser o objetopublicKeyCredentialRequestOptions
(chamadooptions
no exemplo) que você extraiu do servidor e processou na etapa anterior.signal
: transmitir um sinal deAbortController
(comoabortController.signal
) permite que você cancele a solicitaçãoget()
de maneira programática. Isso é útil quando você quer invocar outra chamada da WebAuthn.mediation: 'conditional'
: essa é a flag crucial que torna a chamada da WebAuthn condicional. Ele informa ao navegador para aguardar a interação do usuário com um comando de preenchimento automático em vez de mostrar imediatamente uma caixa de diálogo modal.
Enviar a credencial de chave pública retornada para o servidor RP
Se o usuário selecionar uma chave de acesso e verificar a identidade dele (por
exemplo, usando o bloqueio de tela do dispositivo), a promessa
navigator.credentials.get()
será resolvida. Isso retorna um objeto
PublicKeyCredential
ao front-end.
A promessa pode ser rejeitada por vários motivos. É necessário processar esses erros
no código verificando a propriedade name
do objeto Error
:
NotAllowedError
: o usuário cancelou a operação ou nenhuma chave de acesso foi selecionada.AbortError
: a operação foi interrompida, possivelmente pelo seu código usando umAbortController
.- Outras exceções: ocorreu um erro inesperado. O navegador normalmente mostra uma caixa de diálogo de erro ao usuário.
O objeto PublicKeyCredential
contém várias propriedades. As principais propriedades
relevantes para a autenticação incluem:
id
: o ID codificado em base64url da credencial da chave de acesso autenticada.rawId
: uma versão ArrayBuffer do ID da credencial.response.clientDataJSON
: um ArrayBuffer de dados do cliente. Esse campo contém informações como o desafio e a origem que o servidor precisa verificar.response.authenticatorData
: um ArrayBuffer de dados do autenticador. Esse campo inclui informações como o ID da RP.response.signature
: um ArrayBuffer que contém a assinatura. Esse valor é o núcleo da credencial, e seu servidor precisa verificar essa assinatura usando a chave pública armazenada para a credencial .response.userHandle
: um ArrayBuffer que contém o ID do usuário fornecido durante o registro da chave de acesso.authenticatorAttachment
: indica se o autenticador faz parte do dispositivo cliente (platform
) ou é externo (cross-platform
). Um anexocross-platform
pode ocorrer se o usuário fez login com um smartphone. Nesses casos, peça para o usuário criar uma chave de acesso no dispositivo atual para facilitar o acesso no futuro.type
: esse campo é sempre definido como"public-key"
.
Para enviar esse objeto PublicKeyCredential
ao seu back-end, primeiro chame o
método .toJSON()
. Esse método cria uma versão serializável em JSON da
credencial, que processa corretamente a conversão de propriedades ArrayBuffer
(como rawId
, clientDataJSON
, authenticatorData
, signature
e
userHandle
) para strings codificadas em Base64URL. Em seguida, use JSON.stringify()
para
converter esse objeto em uma string e enviá-lo no corpo da solicitação para o
servidor.
...
// Encode and serialize the PublicKeyCredential.
const _result = credential.toJSON();
const result = JSON.stringify(_result);
// Encode and send the credential to the server for verification.
const response = await fetch('/webauthn/signinResponse', {
method: 'post',
credentials: 'same-origin',
body: result
});
Verificar a assinatura
Quando o servidor de back-end recebe a credencial de chave pública, ele precisa verificar a autenticidade dela. Isso envolve:
- Analisar os dados de credenciais.
- Procurar a chave pública armazenada associada à
id
da credencial. - Verificação do
signature
recebido em relação à chave pública armazenada. - Validar outros dados, como o desafio e a origem.
Recomendamos o uso de uma biblioteca FIDO/WebAuthn do lado do servidor para processar essas operações criptográficas com segurança. Você pode encontrar bibliotecas de código aberto no repositório awesome-webauthn do GitHub.
Se a assinatura e todas as outras declarações forem válidas, o servidor poderá fazer login do usuário. Para conferir etapas detalhadas de validação do lado do servidor, consulte Autenticação de chave de acesso do lado do servidor.
Sinal se as credenciais correspondentes não forem encontradas no back-end
Se o servidor de back-end não encontrar uma credencial com um ID correspondente durante o login, o usuário pode ter excluído essa chave de acesso do servidor, mas não do provedor. Essa incompatibilidade pode gerar uma experiência de usuário confusa se o provedor de chaves de acesso continuar sugerindo uma chave de acesso que não funciona mais com seu site. Para melhorar isso, sinalize o provedor de chave de acesso para remover a chave de acesso órfã.
É possível usar o método PublicKeyCredential.signalUnknownCredential()
, parte da
API Webauthn Signal,
para informar ao provedor de chaves de acesso que a credencial especificada foi removida ou
não existe. Chame esse método estático no lado do cliente se o servidor
indicar (por exemplo, com um código de status HTTP específico, como 404) que um
ID de credencial apresentado é desconhecido. Forneça o ID do RP e o ID da credencial desconhecida
para este método. O provedor de chave de acesso, se for compatível com o indicador, precisa
remover a chave de acesso.
// Detect authentication failure due to lack of the credential
if (response.status === 404) {
// Feature detection
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId: "example.com",
credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
});
} else {
// Encourage the user to delete the passkey from the password manager nevertheless.
...
}
}
Após a autenticação
Dependendo de como o usuário fez login, sugerimos diferentes fluxos a seguir.
Se o usuário tiver feito login sem uma chave de acesso
Se o usuário tiver feito login no seu site sem uma chave de acesso, talvez ele não tenha uma chave registrada para essa conta ou no dispositivo atual. Esse é um momento oportuno para incentivar a criação de chaves de acesso. Considere as seguintes abordagens:
- Fazer upgrade de senhas para chaves de acesso: use o criação condicional, um recurso da WebAuthn que permite que o navegador crie automaticamente uma chave de acesso para o usuário após um login com senha bem-sucedido. Isso pode melhorar significativamente a adoção de chaves de acesso simplificando o processo de criação. Saiba como ele funciona e como implementá-lo em Ajudar os usuários a adotar chaves de acesso de maneira mais simples.
- Solicitar manualmente a criação de chaves de acesso: incentive os usuários a criar uma chave de acesso. Isso pode ser eficaz depois que um usuário concluir um processo de login mais envolvido, como a autenticação multifator (MFA). No entanto, evite solicitações excessivas, que podem ser invasivas para a experiência do usuário."
Para saber como incentivar os usuários a criar uma chave de acesso e conhecer outras práticas recomendadas, consulte os exemplos em Como comunicar chaves de acesso aos usuários.
Se o usuário tiver feito login com uma chave de acesso
Depois que um usuário faz login com uma chave de acesso, você tem várias oportunidades para melhorar ainda mais a experiência dele e manter a consistência da conta.
Incentive a criação de uma nova chave de acesso após uma autenticação entre dispositivos
Se um usuário fizer login com uma chave de acesso usando um mecanismo entre dispositivos (por exemplo, lendo um código QR com o smartphone), a chave de acesso usada pode não ser armazenada localmente no dispositivo em que ele está fazendo login. Isso pode acontecer quando:
- O usuário tem uma chave de acesso, mas em um provedor que não oferece suporte ao sistema operacional ou navegador de login.
- O usuário perdeu o acesso ao provedor da chave de acesso no dispositivo de login, mas uma chave de acesso ainda está disponível em outro.
Nessa situação, peça para o usuário criar uma nova chave de acesso no
dispositivo atual. Isso pode evitar que eles precisem repetir o processo de login em vários dispositivos
no futuro. Para determinar se o usuário fez login usando uma
chave de acesso entre dispositivos, verifique a propriedade authenticatorAttachment
da
credencial. Se o valor for "cross-platform"
, ele indica uma autenticação
entre dispositivos. Nesse caso, explique a conveniência de criar uma nova chave de acesso e
oriente o usuário durante o processo de criação.
Sincronizar os detalhes da chave de acesso com o provedor usando indicadores
Para garantir a consistência e uma melhor experiência do usuário, a parte confiável (RP) pode usar a API WebAuthn Signals para comunicar atualizações sobre credenciais e informações do usuário ao provedor de chave de acesso.
Por exemplo, para manter a lista de chaves de acesso de um usuário do provedor de chaves de acesso precisa, mantenha as credenciais no back-end sincronizadas. É possível indicar que uma chave de acesso não existe mais para que os provedores de chave de acesso possam remover as chaves de acesso desnecessárias.
Da mesma forma, é possível sinalizar se um usuário atualiza o nome de usuário ou o nome de exibição no seu serviço, para manter atualizadas as informações do usuário exibidas pelo provedor de chaves de acesso (por exemplo, nas caixas de diálogo de seleção de conta).
Para saber mais sobre as práticas recomendadas para manter as chaves de acesso consistentes, consulte Manter as chaves de acesso consistentes com as credenciais no seu servidor com a API Signal.
Não pedir um segundo fator
As chaves de acesso oferecem proteção integrada e robusta contra ameaças comuns, como phishing. Portanto, um segundo fator de autenticação não aumenta significativamente a segurança. Em vez disso, cria uma etapa desnecessária para os usuários durante o login.
Lista de verificação
- Permitir que os usuários façam login com uma chave de acesso usando o preenchimento automático de formulários.
- Sinal quando a credencial correspondente de uma chave de acesso não é encontrada no back-end.
- Peça que os usuários criem manualmente uma chave de acesso se eles ainda não tiverem feito isso após o login.
- Crie automaticamente uma chave de acesso (criação condicional) depois que o usuário fizer login com uma senha (e um segundo fator).
- Solicitar a criação de uma chave de acesso local se o usuário tiver feito login com uma chave de acesso entre dispositivos.
- Sinalize a lista de chaves de acesso disponíveis e os detalhes atualizados do usuário (nome de usuário, nome de exibição) para o provedor após o login ou quando ocorrerem mudanças.
Recursos
- Autenticação de chave de acesso do lado do servidor
- Criar uma chave de acesso para logins sem senha
- Ajudar os usuários a gerenciar chaves de acesso de maneira eficaz
- Chaves de acesso
- Documento da Apple: autenticação de um usuário por um serviço da Web
- Documento do Google: login sem senha com chaves de acesso