Análise detalhada de userverification

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 é "verificação do usuário" no 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/privada é gerado. A chave privada é armazenada pelo provedor de chaves 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 feita pela mesma chave de acesso usando a chave pública pareada. A flag "usuário presente" (UP, na sigla em inglês) 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 afirma. Em smartphones, isso geralmente é feito usando o mecanismo de bloqueio de tela, seja ele biométrico ou um PIN ou senha. Se a verificação do usuário foi realizada, isso é informado na flag "UV", que é retornada nos dados do autenticador durante o registro e a autenticação da chave de acesso.

Captura de tela de uma caixa de diálogo de verificação do usuário nas Chaves do iCloud no macOS. A caixa de diálogo pede que o usuário faça login usando o Touch ID, mostrando a origem que solicita a autenticação e o nome de usuário. No canto superior direito da caixa de diálogo, há um botão chamado "Cancelar".
Caixa de diálogo de verificação do usuário nas Chaves do iCloud no macOS.
Captura de tela de uma caixa de diálogo de verificação do usuário no Chrome para Android. A caixa de diálogo pede que o usuário confirme a identidade usando reconhecimento facial ou detecção de impressão digital e mostra a origem que está solicitando a autenticação. No canto inferior esquerdo, há uma opção para verificar usando um PIN.
Caixa de diálogo de verificação do usuário no Chrome para Android.

Como o UP e o UV são validados no servidor

As flags booleanas de presença do usuário (UP) e 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. Enquanto a assinatura for válida, o servidor poderá considerar os flags genuínos.

Uma representação da estrutura de dados de autenticação. Da esquerda para a direita, cada seção da estrutura de dados lê "RP ID HASH" (32 bytes), "FLAGS" (1 byte), "COUNTER" (4 bytes, uint32 big-endian), "ATTESTE CRED. DATA' (comprimento variável, se presente) e 'EXTENSIONS' (comprimento variável, se presente (CBOR)). A seção "FLAGS" é expandida para mostrar uma lista de possíveis flags, rotuladas da esquerda para a direita: "ED", "AT", "0", "BS", "BE", "UV", "0" e "UP".
Campos de dados do autenticador em uma credencial de chave pública.

No registro e na autenticação com chaves de acesso, o servidor precisa examinar se a flag UP é true ou false e se a flag UV é true ou false, dependendo do requisito.

Como especificar o parâmetro userVerification

De acordo com a especificação 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): o uso de um método de verificação do usuário no dispositivo é preferível, mas pode ser ignorado se não estiver disponível. A credencial de resposta contém um valor de flag UV de true se a verificação do usuário foi realizada e false se não foi.
  • 'required': é necessário invocar um método de verificação do usuário disponível no dispositivo. Se não houver um disponível, a solicitação vai falhar localmente. Isso significa que a credencial de resposta sempre retorna com a flag de UV definida como true.
  • 'discouraged': não é recomendável usar um método de verificação de usuário. No entanto, dependendo do dispositivo, a verificação do usuário pode ser realizada de qualquer maneira, e a flag UV pode conter true ou false.

Exemplo de código para 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 com 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ê deve usar depende dos requisitos do aplicativo e das necessidades de experiência do usuário.

Quando usar userVerification='preferred'

Use userVerification='preferred' se você priorizar a experiência do usuário em vez da proteção.

Há ambientes em que a verificação do usuário gera mais transtornos do que proteção. Por exemplo, no macOS, quando o Touch ID não está disponível (porque o dispositivo não é compatível, está desativado ou está no modo clamshell), o usuário precisa inserir a senha do sistema. Isso causa atrito, e o usuário pode abandonar a autenticação completamente. Se eliminar o atrito for mais importante para você, use userVerification='preferred'.

Captura de tela de uma caixa de diálogo de chave de acesso no macOS que aparece quando o Touch ID não está disponível. A caixa de diálogo contém informações como a origem que solicita autenticação e o nome de usuário. No canto superior direito da caixa de diálogo, há um botão chamado "Cancelar".
Uma caixa de diálogo de chave de acesso exibida no macOS quando o Touch ID não está disponível.

Com o userVerification='preferred', a flag UV é true se a verificação do usuário for realizada com sucesso e false se for ignorada. Por exemplo, no macOS, em que o Touch ID não está disponível, ele pede que o usuário clique em um botão para pular a verificação do usuário, e a credencial de chave pública inclui uma flag UV false.

A flag de UV pode ser um indicador na sua análise de risco. Se a tentativa de login parecer arriscada devido a outros fatores, apresente 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.

Uma desvantagem dessa opção é que o usuário pode ter mais dificuldade ao fazer login. Por exemplo, no macOS, quando o Touch ID não está disponível, o usuário precisa inserir a senha do sistema.

Com o userVerification='required', é possível garantir que a verificação do usuário seja feita no dispositivo. Verifique se o servidor confirma que a flag de UV é true.

Conclusão

Ao aproveitar a verificação de usuário, as partes confiáveis de chaves de acesso podem avaliar a probabilidade de o proprietário do dispositivo fazer login. É escolha deles exigir a verificação do usuário ou torná-la opcional, dependendo de como o mecanismo de login alternativo afeta o fluxo do usuário. Verifique se o servidor confere as flags UP e UV para a autenticação de usuários com chave de acesso.