Introdução de dicas, solicitações de origem relacionadas e serialização JSON para WebAuthn no Chrome

O Chrome 128 e 129 apresenta novos recursos interessantes para a WebAuthn, a API subjacente para criar sistemas de autenticação baseados em chave de acesso.

  • Dicas: as dicas dão às partes confiáveis (RPs) um melhor controle sobre a interface da WebAuthn no navegador. Eles são especialmente úteis para usuários corporativos que querem usar chaves de segurança.
  • Solicitações de origem relacionadas: com solicitações de origem relacionadas, os RPs podem tornar as chaves de acesso válidas em vários domínios. Se você tem vários sites, agora pode permitir que os usuários reutilizem as chaves de acesso nos seus sites, eliminando atritos no login.
  • Serialização JSON: as APIs de serialização JSON permitem simplificar o código de front-end de uma RP, codificando e decodificando opções e credenciais transmitidas para e da API WebAuthn.

Dicas

Com hints, as partes confiáveis (RPs) agora podem especificar as preferências da interface para criar uma chave de acesso ou fazer a autenticação com ela.

Anteriormente, quando um RP queria restringir o autenticador que o usuário podia usar para criar uma chave de acesso ou para autenticação, ele usava authenticatorSelection.authenticatorAttachment para especificar "platform" ou "cross-platform". Eles limitam o autenticador a um autenticador de plataforma ou a um autenticador de roaming. Com hints, essa especificação pode ser mais flexível.

O RP pode usar hints opcional no PublicKeyCredentialCreationOptions ou PublicKeyCredentialRequestOptions para especificar "security-key", "client-device" e "hybrid" em uma ordem de preferência em uma matriz.

Confira abaixo um exemplo de solicitação de criação de credencial que prefere autenticadores "cross-platform" com "security-key" como dica. Isso informa ao Chrome para mostrar uma interface focada em chaves de segurança para usuários corporativos.

const credential = await navigator.credentials.create({
  publicKey: {
    challenge: *****,
    hints: ['security-key'],
    authenticatorSelection: {
      authenticatorAttachment: 'cross-platform'
    }
  }
});
Ao especificar "security-key" como uma dica, o navegador mostra uma caixa de diálogo focada na chave de segurança.
Ao especificar "security-key" como uma dica, o navegador mostra uma caixa de diálogo focada em chaves de segurança.

Quando um RP quer priorizar um cenário de verificação entre dispositivos, ele pode enviar uma solicitação de autenticação que dê preferência a autenticadores "cross-platform" com "hybrid" como dica.

const credential = await navigator.credentials.create({
  publicKey: {
    challenge: *****,
    residentKey: true,
    hints: ['hybrid']
    authenticatorSelection: {
      authenticatorAttachment: 'cross-platform'
    }
  }
});
Ao especificar "hybrid" como uma dica, o navegador mostra uma caixa de diálogo focada no login em vários dispositivos.
Ao especificar "hybrid" como uma dica, o navegador mostra uma caixa de diálogo focada no login entre dispositivos.

Com as solicitações de origem relacionadas, as RPs podem tornar as chaves de acesso utilizáveis em vários domínios. A criação de uma experiência de login centralizada e o uso de protocolos de federação continuam sendo a solução recomendada para a maioria dos sites. No entanto, se você tiver vários domínios e a federação não for possível, as origens relacionadas podem ser uma solução.

Todas as solicitações da WebAuthn precisam especificar um ID de parte confiável (ID do RP), e todas as chaves de acesso são associadas a um único ID do RP. Tradicionalmente, uma origem só podia especificar um ID da RP com base no domínio. Nesse caso, www.example.co.uk poderia especificar um ID da RP de example.co.uk, mas não example.com. Com as solicitações de origem relacionadas, um ID da RP reivindicada pode ser validado buscando um arquivo JSON conhecido localizado em /.well-known/webauthn do domínio de destino. Portanto, example.co.uk (e example.in, example.de e assim por diante) podem usar um ID de RP de example.com se example.com os especificar no seguinte formato:

URL: https://example.com/.well-known/webauthn

{
  "origins": [
    "https://example.co.uk",
    "https://example.de",
    "https://example.sg",
    "https://example.net",
    "https://exampledelivery.com",
    "https://exampledelivery.co.uk",
    "https://exampledelivery.de",
    "https://exampledelivery.sg",
    "https://myexamplerewards.com",
    "https://examplecars.com"
  ]
}

Aprenda a configurar solicitações de origem relacionadas em Permitir a reutilização da chave de acesso nos sites com solicitações de origem relacionadas.

Serialização JSON

Os objetos de solicitação e resposta do WebAuthn têm vários campos que contêm dados binários brutos em um ArrayBuffer, como ID da credencial, ID do usuário ou desafio. Se um site quiser usar JSON para trocar esses dados com o servidor, os dados binários primeiro precisam ser codificados, por exemplo, com Base64URL. Isso aumenta a complexidade desnecessária para desenvolvedores que querem começar a usar chaves de acesso nos sites.

A WebAuthn agora oferece APIs para analisar PublicKeyCredentialCreationOptions e PublicKeyCredentialRequestOptions objetos de solicitação da WebAuthn diretamente do JSON e serializar a resposta PublicKeyCredential diretamente em JSON. Todos os campos com valor ArrayBuffer que carregam dados binários brutos são convertidos automaticamente de ou para os valores codificados em Base64URL. Essas APIs estão disponíveis no Chrome 129.

Antes de criar uma chave de acesso, extraia um objeto PublicKeyCredentialCreationOptions codificado em JSON do servidor e decodifique-o usando PublicKeyCredential.parseCreationOptionsFromJSON().

Compatibilidade com navegadores

  • Chrome: 129
  • Edge: 129.
  • Firefox: 119.
  • Safari: não é compatível.

Origem

export async function registerCredential() {

  // Fetch encoded `PublicKeyCredentialCreationOptions`
  // and JSON decode it.
  const options = await fetch('/auth/registerRequest').json();

  // Decode `PublicKeyCredentialCreationOptions` JSON object
  const decodedOptions = PublicKeyCredential.parseCreationOptionsFromJSON(options);  

  // Invoke the WebAuthn create() function.
  const cred = await navigator.credentials.create({
    publicKey: decodedOptions,
  });
  ...

Depois de criar uma chave de acesso, codifique a credencial resultante usando toJSON() para que ela possa ser enviada ao servidor.

Compatibilidade com navegadores

  • Chrome: 129.
  • Edge: 129.
  • Firefox: 119.
  • Safari: não é compatível.

Origem

  ...
  const cred = await navigator.credentials.create({
    publicKey: options,
  });

  // Encode the credential to JSON and stringify
  const credential = JSON.stringify(cred.toJSON());

  // Send the encoded credential to the server
  await fetch('/auth/registerResponse', credential);
  ...

Antes de autenticar com uma chave de acesso, extraia um PublicKeyRequestCreationOptions codificado em JSON do servidor e decodifique-o usando PublicKeyCredential.parseRequestOptionsFromJSON().

Compatibilidade com navegadores

  • Chrome: 129.
  • Edge: 129.
  • Firefox: 119.
  • Safari: incompatível.

Origem

export async function authenticate() {

  // Fetch encoded `PublicKeyCredentialRequestOptions`
  // and JSON decode it.
  const options = await fetch('/auth/signinRequest').json();

  // Decode `PublicKeyCredentialRequestOptions` JSON object
  const decodedOptions = PublicKeyCredential.parseRequestOptionsFromJSON(options);

  // Invoke the WebAuthn get() function.
  const cred = await navigator.credentials.get({
    publicKey: options
  });
  ...

Depois de fazer a autenticação com uma chave de acesso, codifique a credencial resultante usando o método toJSON() para que ela possa ser enviada ao servidor.

Compatibilidade com navegadores

  • Chrome: 129.
  • Edge: 129.
  • Firefox: 119.
  • Safari: incompatível.

Origem

  ...
  const cred = await navigator.credentials.get({
    publicKey: options
  });

  // Encode the credential to JSON and stringify
  const credential = JSON.stringify(cred.toJSON());

  // Send the encoded credential to the server
  await fetch(`/auth/signinResponse`, credential);
  ...

Saiba mais

Para saber mais sobre a WebAuthn e as chaves de acesso, confira os seguintes recursos: