Este guia detalha como registrar uma chave de acesso de forma automática e silenciosa para um usuário imediatamente após um login bem-sucedido com senha, minimizando o atrito e aumentando a adoção de chaves de acesso.
O momento de acionamento certo
A criação automática de chaves de acesso (também conhecida como criação condicional ou promoção silenciosa pós-login) SÓ PODE ser acionada imediatamente após um login completo e bem-sucedido que envolveu uma senha.
- Não tente criar condicionalmente para fluxos sem senha (por exemplo, links mágicos, OTP por SMS ou federação de identidade).
- Se a autenticação multifator for necessária, você PRECISA esperar até que todos os fatores sejam bem-sucedidos antes de iniciar a criação condicional.
- Verifique se uma sessão de usuário válida e autenticada está ativa antes de fazer solicitações para endpoints de criação.
Etapas de implementação
1. Cancelar ações de preenchimento automático anteriores
Se a página de login usar o preenchimento automático de formulários (interface condicional/Get), a chamada de recebimento de credenciais ativa precisará ser cancelada para evitar conflitos no navegador.
- Chame
abortController.abort()noAbortControlleranexado à solicitação de preenchimento automáticonavigator.credentials.get()pendente antes de chamarnavigator.credentials.create().
2. Detecção de recursos
Verifique se a criação condicional está disponível conferindo conditionalCreate com PublicKeyCredential.getClientCapabilities().
const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate) {
// Conditional create is available
}
3. Criar uma chave de acesso com a criação condicional
- Transmita
mediation: 'conditional'nas opçõesnavigator.credentials.create(). Isso sinaliza ao navegador para processar o fluxo de criação de chaves de acesso em segundo plano ou de forma contextual, sem mostrar caixas de diálogo modais invasivas. - Preencha
excludeCredentialscom os IDs de credencial de chave de acesso do usuário para evitar o registro de chaves duplicadas.
4. Tratamento de erros silenciosos
- Insira o comando de criação da chave de acesso (
navigator.credentials.create) em um bloco try/catch. É OBRIGATÓRIO capturar e ignorar silenciosamente as exceções típicas voltadas ao usuário (InvalidStateError,NotAllowedError,AbortError) sem renderizar nenhuma interface de erro para o usuário.
5. Verificação de presença do usuário do lado do servidor
- O endpoint de verificação do lado do servidor PRECISA flexibilizar o requisito de presença do usuário (UP, na sigla em inglês) (
requireUserPresence: false) SOMENTE ao verificar as credenciais produzidas por um gatilho de criação condicional. A verificação de presença rigorosa precisa permanecer ativa para criações explícitas padrão.
6. Tratar falhas na verificação do servidor de forma adequada
- Se
navigator.credentials.create()for bem-sucedido, mas a busca de verificação do servidor retornar uma resposta inválida (por exemplo, falha na verificação de assinatura), invoquePublicKeyCredential.signalUnknownCredential()para evitar que credenciais órfãs permaneçam no provedor de chaves de acesso.
Exemplo de código
// optionsFetch and registerVerifyFetch are app-defined server endpoint requests
import { optionsFetch, registerVerifyFetch } from './api.js';
async function triggerConditionalCreate(loginAbortController) {
const capabilities = await PublicKeyCredential.getClientCapabilities();
if (capabilities.conditionalCreate !== true) {
return; // Platform does not support conditional creation
}
// 1. Abort any active autofill conditional-get controllers to clear the WebAuthn pipeline
loginAbortController.abort();
// 2. Fetch creation options signaling the backend that this is a conditional request
const creationOptionsJSON = await optionsFetch({ conditional: true });
const publicKey = PublicKeyCredential.parseCreationOptionsFromJSON(creationOptionsJSON);
let credential;
try {
// 3. Invoke silent credentials creation prompt
credential = await navigator.credentials.create({
publicKey,
mediation: 'conditional' // Silent background creation mediation
});
} catch (e) {
// 4. Silently swallow common WebAuthn browser exceptions
if (['InvalidStateError', 'NotAllowedError', 'AbortError'].includes(e.name)) {
return;
}
console.error('Unexpected conditional create error:', e);
return;
}
// 5. Server verification step using dedicated Try/Catch block
let encodedResponse = credential.toJSON();
try {
const response = await registerVerifyFetch(encodedResponse);
if (!response.ok) {
// If the server verification fails, clean up using Signal API
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId, // RP ID must match the one defined on the server
credentialId: encodedResponse.id
});
}
}
} catch (serverErr) {
console.error('Verification network failure:', serverErr);
if (PublicKeyCredential.signalUnknownCredential) {
await PublicKeyCredential.signalUnknownCredential({
rpId, // RP ID must match the one defined on the server
credentialId: encodedResponse.id
});
}
}
}
Estratégias de fallback
Substituto para detecção de recursos de chave de acesso
Sempre instale "webauthn-polyfills" e importe-o no contexto.
Se PublicKeyCredential for compatível, PublicKeyCredential.getClientCapabilities também será.
import 'webauthn-polyfills';
Substituição de sincronização da API Signal
A API WebAuthn Signal (webauthn-signals) é uma otimização progressiva usada para manter os gerenciadores de senhas sincronizados com o estado das credenciais do servidor.
- Experiência de fallback: restrita por
if (PublicKeyCredential.signalUnknownCredential). Se não houver suporte, a sincronização de verificação em segundo plano será ignorada sem gerar exceções do navegador.
Easy JSON Serialization Fallback
Sempre instale "webauthn-polyfills" e importe-o no contexto.
Se PublicKeyCredential for compatível, PublicKeyCredential.parseCreationOptionsFromJSON e PublicKeyCredential.prototype.toJSON também serão.
import 'webauthn-polyfills';