As senhas são uma daquelas coisas que normalizamos só porque convivemos com elas há anos. Os usuários os esquecem, os reutilizam, os escrevem onde não deveriam. As equipes devem gerenciar redefinições, políticas, hashes, vazamentos, phishing e suporte.
O passkey não torna a autenticação perfeita, mas elimina um grande problema: o servidor não precisa mais manter um segredo compartilhado com o usuário.
O que realmente acontece
Um passkey é uma credencial baseada em WebAuthn. Quando o usuário o cria, o dispositivo gera um par de chaves:
- uma chave privada, que permanece no dispositivo ou no gerenciador de senhas;
- uma chave pública, que o servidor pode salvar.
Ao fazer login o servidor não pergunta "diga-me a senha". Envie um desafio aleatório. O dispositivo assina com a chave privada. O servidor verifica a assinatura com a chave pública.
Essa é a parte legal: se o banco de dados for roubado, não haverá senhas dentro dele para serem quebradas. E se um usuário acabar em um domínio falso, o passkey não é válido para esse domínio. Não é apenas conveniência, é uma proteção concreta contra phishing.
O navegador funciona como uma ponte
No navegador, os dois API principais são:
navigator.credentials.create()para criar um passkey;navigator.credentials.get()para usá-lo durante o login.
Mas a lógica importante está no servidor. O servidor deve gerar o desafio, salvá-lo temporariamente, verificar a resposta, verificar a fonte e Relying Party ID e então criar a sessão.
A parte do cliente deve ser quase chata:
const options = await fetch('/api/passkeys/login/options').then((r) => r.json()); const credential = await navigator.credentials.get({ publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options), }); await fetch('/api/passkeys/login/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credential?.toJSON()), });
Se você estiver implementando a criptografia WebAuthn manualmente, pare. Use uma biblioteca robusta do lado do servidor. Os erros aqui não são "bugs fofos", são falhas de autenticação.
O que salvar no banco de dados
Não há necessidade de salvar metade do mundo. Geralmente é suficiente:
- ID da credencial;
- chave pública;
- usuário conectado;
- qualquer contador de verificação ou metadados;
- transportes, se forem úteis para UX;
- nome escolhido pelo usuário;
- data de criação e última utilização.
Uma tabela mínima pode ser assim:
create table passkey_credentials ( id uuid primary key default gen_random_uuid(), user_id uuid not null references users(id), credential_id text not null unique, public_key text not null, name text, created_at timestamptz not null default now(), last_used_at timestamptz );
Então eu adicionaria registros de auditoria e notificações: se alguém criar um novo passkey na minha conta, quero saber sobre isso.
UX é mais importante do que demonstração
A demonstração de um passkey é sempre linda: você clica, Face ID, você entra. O produto real é mais complicado.
Alguém muda de telefone. Alguém usa um computador da empresa bloqueado. Algumas pessoas não entendem porque o navegador sugere passkey. Alguém perde o acesso ao seu dispositivo.
É por isso que eu não começaria com “a partir de hoje não há mais senhas para todos”. Eu começaria assim:
- passkey opcional para usuários internos;
- sugestão de criação de um após login bem-sucedido;
- página da conta para renomear e remover passkey;
- alternativa clara;
- implementação gradual no login principal.
O texto na interface deve ser simples. "Usar a tela de bloqueio do seu dispositivo" é melhor do que "autenticar com uma credencial de residente FIDO2".
Erros que eu evitaria
Não gere desafios ao cliente. O desafio é criado no servidor e deve ser verificado apenas uma vez.
Não confie apenas no ID da credencial. Você precisa verificar assinatura, desafio, origem e Relying Party ID.
Não exclua substitutos antes de ter um bom fluxo de recuperação. Sem senha não precisa se tornar “se você perder seu telefone, estará fora para sempre”.
Não trate o passkey como um botão puramente frontend. Ocultar um botão não é segurança: a verdadeira verificação é do lado do servidor.
Passkey-primeiro ou passkey-amigável?
Para um novo produto, você pode pensar primeiro em passkey. Para um aplicativo existente, prefiro passkey amigável: adicione passkey como método recomendado, meça o sucesso e os problemas e, em seguida, reduza com calma o peso da senha.
A migração ideal não se faz sentir. O usuário descobre que o login é mais fácil, e não que a empresa tenha alterado seu protocolo de autenticação.
Conclusão
Os passkey são interessantes porque melhoram a segurança e a UX ao mesmo tempo, o que é raro. Eles não são uma varinha mágica: recuperação, compatibilidade, suporte e implementação ainda precisam ser bem projetados.
Mas a mudança básica é forte. Pare de pedir aos usuários que inventem e protejam segredos. Você permite que o dispositivo assine uma prova criptográfica vinculada ao seu domínio. Menos memória humana, menos phishing, menos redefinições de senha. Eu diria que vale a pena levá-los a sério.