Permitir a reutilização da chave de acesso nos seus sites com solicitações de origem relacionadas

Maud Nalpas
Maud Nalpas

As chaves de acesso estão vinculadas a um site específico e só podem ser usadas para fazer login no site para o qual foram criadas.

Isso é especificado no ID da parte confiável (ID da RP), que, para chaves de acesso criadas para o domínio example.com, pode ser www.example.com ou example.com.

Embora os IDs de RP impeçam que as chaves de acesso sejam usadas como uma única credencial para autenticação em todos os lugares, elas geram problemas para:

  • Sites com vários domínios: os usuários não podem usar a mesma chave de acesso para fazer login em diferentes domínios específicos de país (por exemplo, example.com e example.co.uk) gerenciados pela mesma empresa.
  • Domínios de marca: os usuários não podem usar a mesma credencial em diferentes domínios usados por uma única marca (por exemplo, acme.com e acmerewards.com).
  • Apps para dispositivos móveis: geralmente, os apps para dispositivos móveis não têm domínio próprio, o que dificulta o gerenciamento de credenciais.

Há soluções alternativas baseadas na federação de identidade e outras baseadas em iframes, mas elas são inconvenientes em alguns casos. As solicitações de origem relacionadas oferecem uma solução.

Solução

Com as solicitações de origem relacionadas, um site pode especificar as origens que podem usar o ID da RP.

Isso permite que os usuários reutilizem a mesma chave de acesso em vários sites que você opera.

Para usar solicitações de origem relacionadas, é necessário enviar um arquivo JSON especial em um URL específico https://{RP ID}/.well-known/webauthn. Se o example.com quiser permitir que as origens adicionais o usem como um ID de RP, ele precisará enviar o seguinte arquivo em https://example.com/.well-known/webauthn:.

{
    "origins": [
        "https://example.co.uk",
        "https://example.de",
        "https://example-rewards.com"
    ]
}

Na próxima vez que um desses sites fizer uma chamada para a criação de chave de acesso (navigator.credentials.create) ou autenticação (navigator.credentials.get) que use example.com como um ID de RP, o navegador vai notar um ID de RP que não corresponde à origem solicitante. Se o navegador oferecer suporte a solicitações de origem relacionada, ele vai procurar primeiro um arquivo webauthn em https://{RP ID}/.well-known/webauthn. Se o arquivo existir, o navegador vai verificar se a origem que fez a solicitação está na lista de permissões desse arquivo. Se sim, ele segue para as etapas de criação ou autenticação da chave de acesso. Se o navegador não oferecer suporte a solicitações de origem relacionadas, ele vai gerar uma SecurityError.

Suporte ao navegador

  • Chrome: compatível a partir do Chrome 128.
  • Safari: compatível com o macOS 15 Beta 3 e com o iOS 18 Beta 3 para dispositivos móveis.
  • Firefox: Aguardando posição.

A demonstração a seguir usa o exemplo de dois sites, https://ror-1.glitch.me e https://ror-2.glitch.me.
Para permitir que os usuários façam login com a mesma chave de acesso nos dois sites, ele usa as solicitações de origem relacionadas para permitir que ror-2.glitch.me use ror-1.glitch.me como o ID da RP.

Demonstração

https://ror-2.glitch.me implementa solicitações de origem relacionadas para usar ror-1.glitch.me como um ID de RP. Portanto, ror-1 e ror-2 usam ror-1.glitch.me como um ID de RP ao criar uma chave de acesso ou fazer a autenticação com ela.
Também implementamos um banco de dados de chaves compartilhadas nesses sites.

Observe a seguinte experiência do usuário:

  • É possível criar uma chave de acesso e se autenticar com ela em ror-2, mesmo que o ID do RP seja ror-1 (e não ror-2).
  • Depois de criar uma chave de acesso em ror-1 ou ror-2, você poderá fazer a autenticação com ela em ror-1 e ror-2. Como ror-2 especifica ror-1 como um ID da RP, fazer uma solicitação de criação de chave de acesso ou de autenticação em qualquer um desses sites é o mesmo que fazer a solicitação na ror-1. O ID do RP é a única coisa que vincula uma solicitação a uma origem.
  • Depois que você cria uma chave de acesso em ror-1 ou ror-2, ela pode ser preenchida automaticamente pelo Chrome em ror-1 e ror-2.
  • Uma credencial criada em qualquer um desses sites terá um ID de RP de ror-1.
O Chrome faz o preenchimento automático nos dois sites.
Graças às solicitações de origem relacionadas, os usuários podem usar a mesma chave de acesso em ror-1 e ror-2. O Chrome também vai preencher as credenciais automaticamente.

Confira o código:

Etapa 1: implementar um banco de dados de contas compartilhadas

Se você quiser que os usuários possam fazer login com a mesma chave de acesso em site-1 e site-2, implemente um banco de dados de conta compartilhado entre esses dois sites.

Etapa 2: configurar o arquivo JSON .well-known/webauthn no site-1

Primeiro, configure site-1.com para que ele permita que site-2.com o use como um ID de RP. Para isso, crie seu arquivo JSON de webauthn:

{
    "origins": [
        "https://site-2.com"
    ]
}

O objeto JSON precisa conter origens com nome de chave cujo valor é uma matriz de uma ou mais strings que contêm origens da Web.

Limitação importante: máximo de 5 marcadores

Cada elemento dessa lista será processado para extrair o rótulo do eTLD+1. Por exemplo, os rótulos eTLD + 1 de example.co.uk e example.de são example. Mas o rótulo eTLD+1 de example-rewards.com é example-rewards. No Chrome, o número máximo de marcadores é cinco.

Etapa 3: servir o JSON .well-known/webauthn no site-1

Em seguida, forneça o arquivo JSON em site-1.com/.well-known/webauthn.

Por exemplo, no modo expresso:

app.get("/.well-known/webauthn", (req, res) => {
  const origins = {
    origins: ["https://site-2.com"],
  };
  return res.json(origins);
});

Aqui, estamos usando o res.json expresso, que já define o content-type correto ('application/json').

Etapa 4: especificar o ID da parte restrita desejado em site-2

Na base de código site-2, defina site-1.com como o ID da RP em todos os lugares necessários:

  • Na criação da credencial:
    • Defina site-1.com como o ID da RP na options de criação de credenciais que são transmitidos para a chamada de front-end navigator.credentials.create e normalmente gerados no lado do servidor.
    • Defina site-1.com como o ID do RP esperado, conforme você executa as verificações de credenciais antes de salvar no banco de dados.
  • Após a autenticação:
    • Defina site-1.com como o ID do RP nas options de autenticação que são transmitidas para a chamada de front-end navigator.credentials.get e normalmente geradas no lado do servidor.
    • Defina site-1.com como o ID da RP esperado que será verificado no servidor, à medida que você executa verificações de credenciais antes de autenticar o usuário.

Solução de problemas

Pop-up de mensagem de erro no Chrome.
Mensagem de erro no Chrome durante a criação de credenciais. Esse erro é gerado se o arquivo ".well-known/webauthn" não for encontrado em "https://{RP ID}/.well-known/webauthn".
Pop-up de mensagem de erro no Chrome.
Mensagem de erro no Chrome após a criação da credencial. Esse erro será gerado se o arquivo ".well-known/webauthn" puder ser encontrado, mas não listar a origem da qual você está tentando criar uma credencial.

Outras considerações

Compartilhar chaves de acesso entre sites e apps para dispositivos móveis

As solicitações de origem relacionadas permitem que os usuários reutilizem uma chave de acesso em vários sites. Para permitir que os usuários reutilizem uma chave de acesso em um site e um app para dispositivos móveis, use as seguintes técnicas:

Compartilhar senhas entre sites

As solicitações de origem relacionadas permitem que os usuários reutilizem uma chave de acesso em vários sites. As soluções para compartilhar senhas em vários sites variam de gerenciador para gerenciador. Para o Gerenciador de senhas do Google, use o Digital Asset Links. O Safari tem um sistema diferente.

Função dos gerenciadores de credenciais e dos agentes do usuário

Isso vai além do seu escopo como desenvolvedor de sites, mas, a longo prazo, o ID do RP não deve ser um conceito visível para o usuário no agente do usuário ou no gerenciador de credenciais que ele está usando. Em vez disso, os agentes do usuário e os gerenciadores de credenciais precisam mostrar aos usuários onde as credenciais foram usadas. Essa mudança vai levar algum tempo para ser implementada. Uma solução temporária seria mostrar o site atual e o site de registro original.