Per fornire un'autenticazione fluida e contestuale su più domini, le organizzazioni spesso incorporano le pagine di accesso all'interno di iframe. Tuttavia, il caricamento dei contesti di autenticazione all'interno di frame di terze parti espone gli utenti a minacce critiche come il clickjacking (UI redressing) e la creazione non autorizzata di credenziali. Per mitigare questi rischi, i browser disattivano WebAuthn negli iframe multiorigine per impostazione predefinita. Per rimuovere in sicurezza questa limitazione sono necessari protocolli di difesa in profondità attivi.
Identificare i modelli di minaccia
Prima di attivare le passkey (WebAuthn) all'interno dei subframe, comprendi gli scenari di abuso da cui ti stai difendendo:
- Monitoraggio tramite l'inserimento di iframe nascosti: un malintenzionato attiva una richiesta WebAuthn dal proprio dominio utilizzando un annuncio o un widget su un sito attendibile, inducendo gli utenti ad autorizzare una passkey senza vedere il contesto. In questo modo, l'identità dell'utente viene collegata a un account controllato da un malintenzionato per raccogliere dati.
- Sovrapposizione visiva e clickjacking (UI redressing): una pagina principale dannosa rende invisibile l'iframe di autenticazione utilizzando CSS standard e sovrappone un elemento UI falso per rubare un clic che attiva un flusso di autenticazione. Ciò può comportare il dirottamento della sessione o azioni non autorizzate forzate se l'utente completa inavvertitamente il prompt.
Per contrastare queste minacce, segui queste best practice:
Per il documento di primo livello (frame superiore):
Per il documento incorporato (iframe):
- Attivare i cookie di terze parti partizionati
- Proteggere l'endpoint con la Content Security Policy
- Fidarsi, ma verificare lato server
Per entrambi i documenti:
Attivare la delega utilizzando Permissions Policy
Per impostazione predefinita, i browser bloccano l'accesso a WebAuthn negli iframe multiorigine. Permissions Policy è il meccanismo unificato della piattaforma web che consente a un documento di primo livello di delegare esplicitamente queste potenti funzionalità a origini di terze parti specifiche e attendibili.
Token delle funzionalità
WebAuthn utilizza due token distinti:
publickey-credentials-get: Concede l'autorizzazione per i flussi di accesso con passkey (navigator.credentials.get()).publickey-credentials-create: Concede l'autorizzazione per i flussi di registrazione delle passkey (navigator.credentials.create()).
Requisiti per l'attivazione
L'attivazione di queste funzionalità richiede l'allineamento sia nella risposta del server principale sia nel markup lato client:
- Intestazione della risposta HTTP Permissions-Policy (sito del server principale): la pagina principale deve dichiarare le origini consentite nelle intestazioni della risposta HTTP utilizzando la sintassi Structured Fields.
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
Norme relative alle autorizzazioni: compatibilità con publickey-credentials-get:
Norme relative alle autorizzazioni: compatibilità con publickey-credentials-create:
- L'attributo HTML
allow: nel markup HTML, l'elemento<iframe>deve anche dichiarare che attiva la funzionalità.
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
Compatibilità dell'iframe allow="publickey-credentials-get":
Browser Support
Compatibilità dell'iframe allow="publickey-credentials-create":
Browser Support
Attivare i cookie di terze parti partizionati
Per garantire un flusso di autenticazione affidabile, è necessario stabilire e mantenere una sessione all'interno dell'iframe multiorigine incorporato. Con il passaggio dei browser moderni a rigide restrizioni dei cookie di terze parti, i meccanismi di persistenza standard vengono spesso bloccati per impostazione predefinita e potrebbero richiedere la chiamata dell'API Storage Access per ottenere l'accesso.
Per mitigare questi ostacoli, configura i cookie di sessione con gli attributi SameSite:
None, Secure e Partitioned. Questo meccanismo della piattaforma unificata
garantisce uno stato persistente all'interno dell'iframe rispettando i controlli della privacy
a livello di browser.
Imposta SameSite: None
SameSite:
None
contrassegna esplicitamente un cookie per l'accesso cross-site, consentendone l'invio con
richieste effettuate da un contesto di terze parti (come un iframe). Questo attributo è un
prerequisito per il funzionamento dei cookie in scenari multiorigine, anche se
deve essere combinato con l'attributo Secure per essere accettato dai browser moderni.
Imposta Partitioned
L'attributo Partitioned attiva CHIPS (Cookies Having
Independent Partitioned
State),
consentendo l'archiviazione separata del cookie per ogni sito di primo livello. In questo modo, il cookie rimane accessibile nel contesto specifico dell'iframe di terze parti, consentendo uno stato della sessione persistente senza abilitare il monitoraggio tra siti. L'utente
dovrà accedere di nuovo per ogni incorporamento su un sito diverso.
Proteggere l'endpoint con Content Security Policy
Mentre Permissions Policy determina se l'iframe può eseguire WebAuthn, Content Security Policy (CSP) determina chi è autorizzato a ospitare l'iframe.
Per un endpoint di autenticazione, è fondamentale assicurarsi che solo i siti partner autorizzati o le tue proprietà possano caricare il subframe di accesso, impedendo tentativi di clickjacking non autorizzati prima ancora che possano caricare la UI.
Utilizza frame-ancestors
L'istruzione frame-ancestors
definisce le pagine principali valide che possono incorporare il tuo sito. Aggiungendo domini a
questa direttiva, puoi consentire ai domini autorizzati di incorporare il
subframe di accesso.
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
Content Security Policy: compatibilità con frame-ancestors:
Imposta X-Frame-Options
L'intestazione X-Frame-Options legacy supporta una funzionalità simile, ma supporta solo opzioni binarie (DENY o SAMEORIGIN). Imposta sia CSP frame-ancestors sia X-Frame-Options: DENY nel caso in cui il browser non supporti CSP. CSP ha
sempre la priorità dove è supportato.
X-Frame-Options: DENY
Compatibilità con X-Frame-Options:
Attendibile con verifica lato server
I controlli lato client del browser valutano l'intento e le autorizzazioni, ma il server è l'arbitro finale dell'affidabilità. Verifica la risposta sul server Relying Party (RP) per assicurarti che il contesto sia valido e firmato.
Payload dei dati del cliente
I dati client WebAuthn includono parametri progettati specificamente per aiutarti a verificare il contesto di una richiesta effettuata all'interno di un iframe:
crossOrigin(booleano): indica se l'API WebAuthn è stata richiamata all'interno di un iframe multiorigine. Se la tua architettura si basa sugli iframe, il server deve imporre che questo flag siatrue.topOrigin(stringa): l'origine del contesto di navigazione di primo livello (ciò che è visibile nella barra degli indirizzi del browser). Il server deve verificare questo valore rispetto a un elenco di origini principali autorizzate note.
Elenco di controllo per la verifica
Per verificare la risposta dell'autenticatore sul server:
- Analizza e decodifica il
collectedClientDatafirmato dalla risposta dell'autenticatore. - Assicurati che
typecorrisponda alla cerimonia (webauthn.getowebauthn.create). - Verifica la presenza e la firma dell'utente.
- Se la richiesta doveva provenire da una struttura iframe:
- Applica
crossOrigin === true. - Forza la corrispondenza di
topOrigincon l'elenco autorizzato di origini principali.
- Applica
Stabilire sessioni in modo sicuro utilizzando postMessage()
Per stabilire una sessione in modo affidabile, l'iframe deve trasmettere il token di autenticazione
alla pagina principale utilizzando postMessage(), consentendo alla pagina principale di gestire lo
stato della sessione nel proprio contesto proprietario.
Workflow sicuro
Per stabilire una sessione sicura:
- Assicurati che l'URL dell'iframe
srccontenga i parametri di querynonceeorigin:- Utilizza un valore casuale per
nonce. Unnoncefunge da token di verifica della sicurezza per garantire che il token di autenticazione ricevuto da un iframe corrisponda legittimamente alla sessione specifica avviata dalla pagina principale. - Utilizza il dominio del frame principale per
origin. Un parametrooriginspecifica l'origine della pagina principale, consentendo all'iframe di identificare in modo sicuro il contesto autorizzato in cui è stato incorporato.
- Utilizza un valore casuale per
- L'iframe completa l'autenticazione WebAuthn con il proprio server.
Il server iframe emette un token, ad esempio un JWT che include
noncee lo inoltra alla pagina principale.// 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);La pagina principale rimane in ascolto dell'evento
message, convalida l'origine del mittente e verifica il 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, }); });La pagina principale mantiene la sessione se il JWT viene verificato correttamente.
Il mittente e il destinatario condividono le responsabilità in materia di sicurezza:
- Il mittente (iframe): specifica sempre un'origine di destinazione rigorosa quando invii
messaggi (non utilizzare mai
"*"). - Il destinatario (genitore): verifica sempre
event.originquando ricevi messaggi per evitare lo spoofing dell'origine.
Conclusione
L'utilizzo di iframe sicuri dipende dalla Permissions Policy per l'attivazione, dalla CSP per la limitazione, dai cookie di terze parti partizionati per la persistenza della sessione, dalla verifica lato server del contesto client e dal trasferimento della sessione sensibile al contesto tramite postMessage().
Per saperne di più sugli argomenti correlati, segui il blog per sviluppatori di Chrome di Google ed esplora altre risorse nella documentazione sull'identità dello sviluppatore di Chrome.