Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Passkeys no Node.js: Guia Prático

Atualizado em: 28 de agosto de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Implementar Passkeys no Node.js permite que usuários entrem usando biometria, PIN ou desbloqueio do dispositivo, sem digitar uma senha. Uma passkey é uma credencial WebAuthn discoverable, normalmente protegida e sincronizada pelo ecossistema do usuário ou armazenada em uma chave de segurança.

A chave privada nunca é enviada ao servidor. A aplicação guarda a chave pública e valida uma assinatura vinculada ao domínio. Isso oferece resistência a phishing, elimina reutilização de senha e melhora a experiência de login.

Neste guia, você aprenderá a diferença entre passkeys e WebAuthn, registration, login sem username, conditional UI, sincronização, recuperação, migração de senhas, múltiplos dispositivos, sessões, auditoria e testes.

O que é uma passkey?

Passkey é uma credencial de chave pública construída sobre FIDO2 e WebAuthn. A documentação da FIDO Alliance sobre passkeys explica o conceito. A especificação WebAuthn do W3C define o protocolo técnico.

Para detalhes de challenge, origin e assinatura, consulte WebAuthn no Node.js. Para um fator alternativo, veja TOTP no Node.js.

Passkey versus WebAuthn

WebAuthn é a API e o protocolo. Passkey é uma experiência de credencial discoverable e, frequentemente, sincronizável. Toda passkey usa WebAuthn, mas nem toda credencial WebAuthn é apresentada como passkey.

Por que passkeys resistem a phishing?

A credencial é vinculada ao RP ID. Um site falso em outro domínio não consegue pedir uma assinatura válida para o domínio real.

Sem segredo compartilhado

O servidor armazena chave pública. Um vazamento do banco não fornece uma senha ou segredo capaz de autenticar diretamente.

Autenticador de plataforma

O dispositivo pode usar biometria, PIN ou bloqueio do sistema. A aplicação recebe apenas o resultado da verificação, não a impressão digital ou o rosto.

Autenticador externo

Chaves USB, NFC ou Bluetooth também podem armazenar credenciais. Elas são úteis para contas privilegiadas e recuperação.

Credencial discoverable

Uma passkey contém informações suficientes para que o autenticador identifique a conta sem o servidor enviar uma lista de credential IDs.

Registro de passkey

  1. Usuário autentica por um método existente.
  2. Servidor gera challenge.
  3. Servidor solicita resident key.
  4. Navegador chama navigator.credentials.create().
  5. Usuário confirma no dispositivo.
  6. Servidor verifica a resposta.
  7. Servidor armazena a chave pública.
  8. Evento é auditado.

Opções de registro

const options = await generateRegistrationOptions({
  rpName: 'Minha Aplicação',
  rpID: 'example.com',
  userID: user.id,
  userName: user.email,
  attestationType: 'none',
  authenticatorSelection: {
    residentKey: 'required',
    userVerification: 'required'
  },
  excludeCredentials: existingCredentials
});

A API depende da biblioteca WebAuthn utilizada.

residentKey required

Solicitar required garante uma credencial discoverable quando o autenticador suporta o fluxo.

User verification

Para login sem senha, normalmente exija userVerification: required. Isso confirma PIN, biometria ou mecanismo equivalente no autenticador.

User handle

Use um ID interno opaco e estável:

userID: randomBytes(32)

Não use e-mail como identificador permanente, pois ele pode mudar.

Nome exibido

O autenticador pode mostrar nome e e-mail para ajudar o usuário a escolher a conta. Esses campos não devem ser usados pelo servidor como identidade confiável.

Login sem username

O servidor retorna opções sem allowCredentials:

const options = await generateAuthenticationOptions({
  rpID: 'example.com',
  userVerification: 'required'
});

O autenticador oferece contas disponíveis para o domínio.

Identificando o usuário

A resposta inclui credential ID e user handle. O servidor localiza a credencial e confirma que ela pertence ao usuário indicado.

Conditional UI

A mediação condicional integra passkeys ao campo de login:

const credential = await navigator.credentials.get({
  publicKey: options,
  mediation: 'conditional'
});

O navegador pode mostrar uma passkey no autocomplete sem abrir um modal imediato.

Autocomplete

<input
  name="username"
  autocomplete="username webauthn"
>

O suporte varia por navegador e sistema operacional.

Detecção de suporte

Verifique APIs disponíveis e mantenha fallback:

const available = Boolean(
  window.PublicKeyCredential
);

Detecção não garante que o dispositivo possua uma passkey para o site.

Sincronização

Alguns provedores sincronizam passkeys cifradas entre dispositivos da mesma conta. Isso melhora recuperação, mas muda a interpretação de contadores e backup state.

Passkeys device-bound

Credenciais em chaves de segurança podem permanecer vinculadas ao dispositivo. Ofereça várias credenciais para reduzir o risco de perda.

Backup eligibility

Metadados da verificação podem indicar se a credencial é elegível para backup e se está atualmente copiada. Use para experiência e risco, não como única decisão de acesso.

Sign count

Passkeys sincronizadas podem não fornecer um contador global crescente. Siga a biblioteca e a especificação, evitando bloquear usuários legítimos por uma suposição antiga.

Cadastro após senha

Uma migração gradual permite que o usuário entre com senha e cadastre uma passkey. Exija autenticação recente para impedir que uma sessão roubada adicione credencial.

Passkey-first

Depois que uma passkey existe, apresente-a como opção principal. Mantenha fallback controlado durante a transição.

Removendo senha

Antes de tornar a conta passwordless, confirme:

  • passkey funcionando;
  • outro dispositivo ou método de recuperação;
  • notificação ao usuário;
  • recovery codes;
  • suporte preparado.

Várias passkeys

Permita cadastrar mais de uma credencial. Mostre nome, data de criação, último uso e tipo aproximado.

Nomeando credencial

iPhone pessoal
Notebook do trabalho
Chave de segurança reserva

Escape o nome na interface e limite tamanho.

Credenciais duplicadas

Use excludeCredentials durante o registro e mantenha credential ID único no banco.

Tabela de credenciais

CREATE TABLE passkey_credentials (
  credential_id TEXT PRIMARY KEY,
  user_id UUID NOT NULL,
  public_key BYTEA NOT NULL,
  user_handle BYTEA NOT NULL,
  sign_count BIGINT NOT NULL,
  transports TEXT[],
  backed_up BOOLEAN,
  device_type TEXT,
  display_name TEXT,
  created_at TIMESTAMPTZ NOT NULL,
  last_used_at TIMESTAMPTZ
);

Proteção contra alteração

A chave pública não é secreta, mas a tabela precisa de integridade. Uma alteração permitiria substituir a credencial legítima.

Challenges

Gere com CSPRNG, associe ao usuário ou sessão, defina propósito, expire e consuma após uma tentativa.

Origin e RP ID

Carregue de configuração confiável. Não derive de Host ou headers encaminhados fornecidos pelo cliente.

Subdomínios

Escolher um RP ID pai pode permitir uso em subdomínios. Garanta que nenhum subdomínio abandonado possa ser tomado por terceiros.

Domínios customizados

Aplicações multi-tenant com domínios customizados precisam decidir se passkeys são vinculadas ao domínio da plataforma ou a cada domínio do cliente.

Recuperação de conta

A recuperação é o ponto mais sensível. Um fluxo por e-mail fraco pode anular a resistência a phishing da passkey.

Opções de recuperação

  • segunda passkey;
  • chave de segurança reserva;
  • recovery codes;
  • TOTP;
  • processo assistido com período de espera.

Recovery codes

Armazene com hash, mostre uma vez e invalide após uso.

Notificações

Avise quando uma passkey é adicionada, removida ou usada em recuperação. Inclua opção para encerrar sessões.

Step-up authentication

Exija passkey recente para alterar e-mail, remover MFA, criar token ou exportar dados.

Sessões

Após sucesso, rotacione o ID da sessão e registre auth_time e método usado.

Claims

{
  "amr": ["passkey"],
  "auth_time": 1787925600
}

Não confie em claims vindos do cliente sem assinatura e validação.

Autorização

Passkey autentica o usuário, mas RBAC ou ABAC ainda decide acesso. Consulte RBAC no Node.js e ABAC no Node.js.

Rate limiting

Limite endpoints de challenge, verificação e cadastro para reduzir abuso e enumeração.

Enumeração de contas

O fluxo sem username reduz exposição. Quando usar e-mail, retorne mensagens consistentes independentemente de a conta possuir passkey.

Erros amigáveis

Diferencie internamente cancelamento, timeout e falha criptográfica, mas mostre mensagem simples ao usuário.

Cancelamento do prompt

O usuário pode fechar o prompt. Isso não deve ser registrado como erro crítico.

Timeout

Defina timeout nas opções e expiração do challenge. O navegador pode aplicar comportamento próprio.

Biblioteca de servidor

Use biblioteca que valide CBOR, COSE, clientDataJSON, authenticatorData, flags e assinatura. Não implemente manualmente.

Frontend

Use utilitários para converter Base64URL e ArrayBuffer. Um erro de encoding é uma causa comum de falha.

Progressive enhancement

Se o navegador não suporta conditional UI, ofereça botão “Entrar com passkey”. Se WebAuthn não está disponível, mantenha fallback seguro.

Acessibilidade

Não dependa apenas de biometria. O sistema operacional pode oferecer PIN ou chave externa. Escreva instruções claras.

Privacidade

O servidor não recebe biometria. Evite coletar attestation e metadados de dispositivo sem necessidade.

Auditoria

Registre cadastro, login, remoção, recuperação e alteração de nome, sem armazenar challenge ou assinatura.

Consulte Logs de Auditoria no Node.js.

Métricas

Monitore adesão, sucesso, fallback por senha, recuperação, credenciais por usuário e falhas por plataforma.

Funil de migração

  • oferta de passkey;
  • registro iniciado;
  • registro concluído;
  • primeiro login;
  • senha removida;
  • recuperação utilizada.

Testes com autenticador virtual

Playwright, Chrome DevTools Protocol e outras ferramentas podem simular WebAuthn em testes end-to-end.

Teste de login sem username

Cadastre duas contas e confirme que o user handle resolve a identidade correta.

Teste de conditional UI

Confirme que o fluxo não dispara prompts inesperados e que o fallback continua disponível.

Teste de challenge

Rejeite challenge expirado, reutilizado ou de outro propósito.

Teste de domínio

Origin e RP ID diferentes devem falhar.

Teste de recuperação

Remova o dispositivo principal e valide o método alternativo, notificações e período de espera.

Teste de remoção

Não permita remover a última credencial sem recuperação confirmada.

Erros comuns

  • Tratar passkey como senha: conceitos e armazenamento ficam errados.
  • User handle baseado em e-mail: mudança quebra a identidade.
  • Challenge reutilizado: replay se torna possível.
  • RP ID derivado do request: headers forjados alteram o vínculo.
  • Sem recuperação: usuário perde acesso.
  • Fallback fraco: phishing continua suficiente.
  • Remoção sem step-up: sessão roubada elimina credenciais.

Boas práticas

  • Use WebAuthn com resident key.
  • Exija user verification.
  • Use user handle opaco.
  • Valide origin e RP ID fixos.
  • Consuma challenges.
  • Permita várias passkeys.
  • Planeje recuperação forte.
  • Rotacione sessões.
  • Audite mudanças.
  • Teste navegadores e autenticadores.

Conclusão

Implementar Passkeys no Node.js oferece login sem senha, resistente a phishing e integrado ao desbloqueio do dispositivo. O servidor armazena apenas uma chave pública e verifica assinaturas vinculadas ao domínio.

Uma experiência segura depende de user handles estáveis, challenges de uso único, múltiplas credenciais e recuperação robusta. Com conditional UI, migração gradual e sessões rotacionadas, passkeys podem substituir senhas sem trocar conveniência por um fluxo de suporte inseguro.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita