Para oferecer uma autenticação tranquila e contextual em vários domínios, as organizações geralmente incorporam páginas de login em iframes. No entanto, carregar contextos de autenticação em frames de terceiros expõe os usuários a ameaças graves, como clickjacking (redirecionamento da interface) e criação não autorizada de credenciais. Para reduzir esses riscos, os navegadores desativam o WebAuthn em iframes de origem cruzada por padrão. Para remover essa restrição com segurança, é necessário ter protocolos ativos de defesa em profundidade.
Identificar modelos de ameaças
Antes de ativar as chaves de acesso (WebAuthn) em subframes, entenda os cenários de abuso contra os quais você está se defendendo:
- Rastreamento usando injeção de iframe oculto:um invasor aciona uma solicitação do WebAuthn no próprio domínio usando um anúncio ou widget em um site confiável, enganando os usuários para que autorizem uma chave de acesso sem ver o contexto. Isso vincula a identidade do usuário a uma conta controlada por um invasor para coletar dados.
- Sobreposição visual e clickjacking (redirecionamento da interface): uma página mãe maliciosa renderiza o iframe de autenticação invisível usando CSS padrão e sobrepõe um elemento de interface falso para roubar um clique que aciona um fluxo de autenticação. Isso pode resultar em sequestro de sessão ou ações não autorizadas forçadas se o usuário concluir o comando sem querer.
Para combater essas ameaças, siga estas práticas recomendadas:
Para o documento de nível superior (frame superior):
Para o documento incorporado (iframe):
- Ativar cookies particionados de terceiros
- Proteja o endpoint com a Política de Segurança de Conteúdo
- Confie, mas verifique do lado do servidor
Para os dois documentos:
Ativar a delegação usando a política de permissões
Por padrão, os navegadores bloqueiam o acesso à WebAuthn em iframes de origem cruzada. A política de permissões é o mecanismo unificado da plataforma da Web que permite que um documento de nível superior delegue explicitamente esses recursos avançados a origens específicas e confiáveis de terceiros.
Tokens de recursos
O WebAuthn usa dois tokens distintos:
publickey-credentials-get: concede autorização para fluxos de login com chaves de acesso (navigator.credentials.get()).publickey-credentials-create: concede autorização para fluxos de registro de chaves de acesso (navigator.credentials.create()).
Requisitos para ativação
Para ativar esses recursos, é necessário alinhar a resposta do servidor principal e a marcação do lado do cliente:
- Cabeçalho de resposta HTTP da política de permissões (site do servidor principal): a página principal precisa declarar as origens permitidas nos cabeçalhos de resposta HTTP usando a sintaxe de campos estruturados.
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
Política de permissões: compatibilidade com publickey-credentials-get
Política de permissões: compatibilidade com publickey-credentials-create
- O atributo HTML
allow:na marcação HTML, o elemento<iframe>também precisa declarar que ativa o recurso.
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
Compatibilidade do iframe allow="publickey-credentials-get":
Browser Support
Compatibilidade do iframe allow="publickey-credentials-create":
Browser Support
Ativar cookies particionados de terceiros
Para garantir um fluxo de autenticação confiável, uma sessão precisa ser estabelecida e mantida no iframe incorporado de origem cruzada. À medida que os navegadores modernos passaram para restrições rígidas de cookies de terceiros, os mecanismos de persistência padrão geralmente são bloqueados por padrão e podem exigir a chamada da API Storage Access para conseguir acesso.
Para reduzir esses obstáculos, configure os cookies de sessão com os atributos SameSite:
None, Secure e Partitioned. Esse mecanismo de plataforma unificada
garante um estado persistente no iframe, respeitando os controles de privacidade
no nível do navegador.
Definir SameSite: None
SameSite:
None
marca explicitamente um cookie para acesso entre sites, permitindo que ele seja enviado com
solicitações feitas em um contexto de terceiros (como um iframe). Esse atributo é um
pré-requisito para que os cookies funcionem em cenários de origem cruzada, mas ele
precisa ser combinado com o atributo Secure para ser aceito por navegadores modernos.
Definir Partitioned
O atributo Partitioned ativa o cookie no CHIPS (Cookies com estado particionado independente), permitindo que ele seja armazenado separadamente para cada site de nível superior. Isso garante que o cookie permaneça acessível no contexto específico do iframe de terceiros, permitindo um estado de sessão persistente sem ativar o rastreamento entre sites. O usuário
precisará fazer login novamente para cada incorporação em um site diferente.
Proteger o endpoint com a Política de Segurança de Conteúdo
Enquanto a Política de Permissões determina se o iframe pode executar o WebAuthn, a Política de Segurança de Conteúdo (CSP) determina quem pode hospedar o iframe.
Para um endpoint de autenticação, é fundamental garantir que apenas sites parceiros autorizados ou suas próprias propriedades possam carregar o subframe de login, encerrando tentativas não autorizadas de clickjacking antes mesmo de carregar a interface.
Usar frame-ancestors
A diretivaframe-ancestors
define as páginas principais válidas que podem incorporar seu site. Ao adicionar domínios a essa diretiva, você permite que eles incorporem o subframe de login.
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
Política de segurança de conteúdo: compatibilidade com frame-ancestors:
Definir X-Frame-Options
O cabeçalho X-Frame-Options legado oferece uma capacidade semelhante, mas só aceita opções binárias (DENY ou SAMEORIGIN). Defina frame-ancestors e X-Frame-Options: DENY da CSP caso o navegador não seja compatível com ela. A CSP é sempre priorizada onde há suporte.
X-Frame-Options: DENY
Compatibilidade com X-Frame-Options:
Confie, mas verifique do lado do servidor
As verificações do lado do cliente do navegador avaliam a intenção e as permissões, mas o servidor é o árbitro final da confiança. Verifique a resposta no servidor da parte confiante (RP) para garantir que o contexto seja válido e assinado.
Payload de dados do cliente
Os dados do cliente WebAuthn incluem parâmetros projetados especificamente para ajudar você a verificar o contexto de uma solicitação feita em um iframe:
crossOrigin(booleano): indica se a API WebAuthn foi invocada em um iframe de origem cruzada. Se a arquitetura depender de iframes, o servidor precisa garantir que essa flag sejatrue.topOrigin(string): a origem do contexto de navegação de nível superior (o que é visível na barra de endereço do navegador). O servidor precisa verificar isso em uma lista de origens de familiares responsáveis conhecidas e autorizadas.
Lista de verificação da confirmação
Para verificar a resposta do autenticador no seu servidor, siga estas etapas:
- Analise e decodifique o
collectedClientDataassinado da resposta do autenticador. - Verifique se o
typecorresponde à cerimônia (webauthn.getouwebauthn.create). - Verifique a presença e a assinatura do usuário.
- Se a solicitação deveria vir de uma estrutura de iframe:
- Aplicar
crossOrigin === true. - Faça com que
topOrigincorresponda à sua lista autorizada de origens principais.
- Aplicar
Estabelecer sessões com segurança usando postMessage()
Para estabelecer uma sessão de forma confiável, o iframe precisa transmitir o token de autenticação
de volta para a página mãe usando postMessage(), permitindo que ela gerencie o
estado da sessão no próprio contexto.
Fluxo de trabalho seguro
Para estabelecer uma sessão segura, siga este fluxo de trabalho:
- Verifique se o URL do iframe
srccontém os parâmetros de consultanonceeorigin:- Use um valor aleatório para
nonce. Umnonceserve como um token de verificação de segurança para garantir que o token de autenticação recebido de um iframe corresponda legitimamente à sessão específica iniciada pela página mãe. - Use o domínio do frame pai para o
origin. Um parâmetrooriginespecifica a origem da página mãe, permitindo que o iframe identifique com segurança o contexto autorizado em que foi incorporado.
- Use um valor aleatório para
- O iframe conclui a autenticação do WebAuthn com o próprio servidor.
O servidor do iframe emite um token, como um JWT, que inclui o
noncee encaminha para a página mãe.// Extract nonce and origin from the URL params const urlParams = new URLSearchParams(window.location.search); const nonce = urlParams.get('nonce'); const origin = urlParams.get('origin'); if (!nonce || !origin) { alert('Nonce or origin is missing in the URL'); return; } // Create a JWT const response = await post('/createToken', { nonce, origin }); const token = response.token; // Post the JWT to the parent frame window.parent.postMessage({ token }, origin);A página mãe detecta o evento
message, valida a origem do remetente e verifica o token.window.addEventListener("message", (event) => { if (event.origin !== "https://embedded-auth.example.com") return; // Verify the received JWT const result = await post('/verifyIdToken', { token: event.data.token, origin: provider.origin, }); });A página mãe mantém a sessão se o JWT for verificado.
O remetente e o destinatário compartilham responsabilidades de segurança:
- O remetente (iframe): sempre especifique uma origem de destino estrita ao enviar
mensagens (nunca use
"*"). - O receptor (elemento pai): sempre verifique
event.originao receber mensagens para evitar a falsificação de origem.
Conclusão
O uso seguro de iframes depende da política de permissões para ativação, da CSP para restrição, de cookies particionados de terceiros para persistência de sessão, da verificação do lado do servidor do contexto do cliente e da transferência de sessão baseada no contexto usando postMessage().
Para saber mais sobre temas relacionados, siga o blog para desenvolvedores do Chrome do Google e confira mais recursos na documentação de identidade do desenvolvedor do Chrome.