Este documento discute o que é userVerification
no WebAuthn e os comportamentos do navegador que resultam quando userVerification
é especificado durante a criação ou autenticação de chaves de acesso.
O que é a "verificação do usuário" na WebAuthn?
As chaves de acesso são criadas com base na criptografia de chave pública. Ao criar uma chave de acesso, um par de chaves pública e privada é gerado, a chave privada é armazenada pelo provedor de chave de acesso e a chave pública é retornada ao servidor da parte confiável (RP) para armazenamento. O servidor pode autenticar um usuário verificando uma assinatura assinada pela mesma chave de acesso usando a chave pública pareada. A flag "user present" (UP) em uma credencial de chave pública prova que alguém interagiu com o dispositivo durante a autenticação.
A verificação do usuário é uma camada opcional de segurança que busca garantir que a pessoa certa estava presente durante a autenticação, e não apenas alguém, como a presença do usuário. Em smartphones, isso geralmente é feito usando o mecanismo de bloqueio de tela, seja biométrico, PIN ou senha. A verificação do usuário foi realizada e é informada na flag "UV" que é retornada nos dados do autenticador durante o registro e a autenticação da chave de acesso.
Como UP e UV são validados no servidor
As flags booleanas de presença do usuário (UP) e de usuário verificado (UV) são sinalizadas para o servidor no campo de dados do autenticador. Durante a autenticação, o conteúdo do campo de dados do autenticador pode ser validado verificando a assinatura usando a chave pública armazenada. Contanto que a assinatura seja válida, o servidor pode considerar as flags como genuínas.
No registro e na autenticação da chave de acesso, o servidor precisa examinar se a flag UP é true
e se a flag UV é true
ou false
, dependendo do requisito.
Como especificar o parâmetro userVerification
De acordo com a especificação da WebAuthn, o RP pode solicitar uma verificação do usuário com um parâmetro userVerification
na criação e na declaração de credenciais. Ele aceita 'preferred'
, 'required'
ou 'discouraged'
, que significam respectivamente:
'preferred'
(padrão): é recomendável usar um método de verificação do usuário no dispositivo, mas ele pode ser ignorado se não estiver disponível. A credencial de resposta contém um valor de sinalização UV detrue
se a verificação do usuário foi realizada efalse
se a UV não foi realizada.'required'
: é necessário invocar um método de verificação de usuário disponível no dispositivo. Se nenhuma estiver disponível, a solicitação falhará localmente. Isso significa que a credencial de resposta sempre retorna com a flag UV definida comotrue
.'discouraged'
: não é recomendável usar um método de verificação do usuário. No entanto, dependendo do dispositivo, a verificação do usuário pode ser realizada de qualquer maneira, e a flag UV pode contertrue
oufalse
.
Exemplo de código para a criação de chaves de acesso:
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
userVerification: 'preferred'
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
Exemplo de código para autenticação de chave de acesso:
const publicKeyCredentialRequestOptions = {
challenge: /* Omitted challenge data... */,
rpId: 'example.com',
userVerification: 'preferred'
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions
});
Qual opção você deve escolher para userVerification
?
O valor de userVerification
que você vai usar depende dos requisitos do aplicativo e das necessidades de experiência do usuário.
Quando usar userVerification='preferred'
Use userVerification='preferred'
se a experiência do usuário for mais importante que a proteção.
Há ambientes em que a verificação do usuário é mais um obstáculo do que uma proteção. Por exemplo, no macOS onde o Touch ID não está disponível (porque o dispositivo não é compatível, está desativado ou o dispositivo está no modo clamshell), o usuário é solicitado a inserir a senha do sistema. Isso causa atrito, e o usuário pode abandonar a autenticação completamente. Se a eliminação de atrito for mais importante para você, use userVerification='preferred'
.
Com userVerification='preferred'
, a flag de UV é true
se a verificação do usuário for realizada e false
se a verificação do usuário for ignorada. Por exemplo, no macOS, onde o Touch ID não está disponível, o usuário precisa clicar em um botão para pular a verificação, e a credencial de chave pública inclui uma flag UV false
.
A flag UV pode ser um indicador na sua análise de risco. Se a tentativa de login parecer arriscada devido a outros fatores, você pode apresentar outros desafios de login ao usuário se a verificação não tiver sido realizada.
Quando usar userVerification='required'
Use userVerification='required'
se você achar que UP e UV são absolutamente necessários.
A desvantagem dessa opção é que o usuário pode ter mais dificuldade para fazer login. Por exemplo, no macOS, onde o Touch ID não está disponível, o usuário precisa digitar a senha do sistema.
Com userVerification='required'
, é possível garantir que a verificação do usuário seja realizada no dispositivo. Verifique se o servidor verifica se a flag UV é true
.
Conclusão
Ao aproveitar a verificação do usuário, as partes que dependem de chaves de acesso podem avaliar a probabilidade de o proprietário do dispositivo fazer login. A decisão de exigir a verificação do usuário ou torná-la opcional depende de quão crítico o mecanismo de fallback de login é para o fluxo do usuário. Verifique se o servidor verifica as flags UP e UV para a autenticação de usuário da chave de acesso.