Pour fournir une authentification fluide et contextuelle sur plusieurs domaines, les organisations intègrent souvent des pages de connexion dans des iFrames. Toutefois, le chargement de contextes d'authentification dans des frames tiers expose les utilisateurs à des menaces critiques telles que le détournement de clic (redressage de l'UI) et la création d'identifiants non autorisée. Pour atténuer ces risques, les navigateurs désactivent WebAuthn dans les iFrames cross-origin par défaut. Pour lever cette restriction en toute sécurité, vous devez disposer de protocoles de défense en profondeur actifs.
Identifier les modèles de menace
Avant d'activer les clés d'accès (WebAuthn) dans les sous-cadres, comprenez les scénarios d'utilisation abusive contre lesquels vous vous protégez :
- Suivi à l'aide de l'injection d'iFrame masqué : un pirate informatique déclenche une invite WebAuthn depuis son propre domaine à l'aide d'une annonce ou d'un widget sur un site de confiance, ce qui incite les utilisateurs à autoriser une clé d'accès sans voir le contexte. Cela associe l'identité de l'utilisateur à un compte contrôlé par un pirate informatique pour collecter des données.
- Superposition visuelle et clickjacking (habillage de l'interface utilisateur) : une page parente malveillante rend l'iframe d'authentification invisible à l'aide de CSS standard et superpose un faux élément d'interface utilisateur pour voler un clic qui déclenche un flux d'authentification. Si l'utilisateur répond involontairement à la requête, cela peut entraîner un détournement de session ou des actions non autorisées forcées.
Pour contrer ces menaces, suivez les bonnes pratiques suivantes :
Pour le document de premier niveau (frame supérieur) :
Pour le document intégré (iFrame) :
- Activer les cookies tiers partitionnés
- Protéger le point de terminaison avec Content Security Policy
- Faites confiance, mais vérifiez côté serveur
Pour les deux documents :
Activer la délégation à l'aide de la règle d'autorisation
Par défaut, les navigateurs bloquent l'accès à WebAuthn dans les iFrame multi-origines. La Permissions Policy est un mécanisme unifié de plate-forme Web qui permet à un document de premier niveau de déléguer explicitement ces puissantes fonctionnalités à des origines tierces spécifiques et fiables.
Jetons de fonctionnalité
WebAuthn utilise deux jetons distincts :
publickey-credentials-get: accorde l'autorisation pour les flux de connexion par clé d'accès (navigator.credentials.get()).publickey-credentials-create: accorde l'autorisation pour les flux d'enregistrement de clés d'accès (navigator.credentials.create()).
Conditions d'activation
Pour activer ces fonctionnalités, vous devez aligner la réponse du serveur parent et le balisage côté client :
- En-tête de réponse HTTP "Permissions-Policy" (site du serveur parent) : La page parente doit déclarer les origines autorisées dans ses en-têtes de réponse HTTP à l'aide de la syntaxe Structured Fields.
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
Règlement sur les autorisations : compatibilité publickey-credentials-get
Compatibilité de la règle relative aux autorisations avec publickey-credentials-create :
- L'attribut HTML
allow: dans le balisage HTML, l'élément<iframe>doit également déclarer qu'il active la fonctionnalité.
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
Compatibilité de l'attribut allow="publickey-credentials-get" de l'iFrame :
Browser Support
Compatibilité de l'attribut "allow="publickey-credentials-create"" de l'iframe :
Browser Support
Activer les cookies tiers partitionnés
Pour garantir un flux d'authentification fiable, une session doit être établie et maintenue dans l'iFrame intégré d'origine croisée. À mesure que les navigateurs modernes sont passés à des restrictions strictes concernant les cookies tiers, les mécanismes de persistance standards sont souvent bloqués par défaut et peuvent nécessiter l'appel de l'API Storage Access pour y accéder.
Pour surmonter ces obstacles, configurez vos cookies de session avec les attributs SameSite:
None, Secure et Partitioned. Ce mécanisme de plate-forme unifié assure un état persistant dans l'iFrame tout en respectant les contrôles de confidentialité au niveau du navigateur.
Ensemble SameSite: None
SameSite:
None marque explicitement un cookie pour l'accès multisite, ce qui permet de l'envoyer avec les requêtes effectuées à partir d'un contexte tiers (comme un iFrame). Cet attribut est indispensable pour que les cookies fonctionnent dans les scénarios multiorigines. Toutefois, il doit être associé à l'attribut Secure pour être accepté par les navigateurs modernes.
Ensemble Partitioned
L'attribut Partitioned permet d'activer CHIPS (Cookies Having Independent Partitioned State) pour le cookie, ce qui permet de le stocker séparément pour chaque site de premier niveau. Cela garantit que le cookie reste accessible dans le contexte d'iFrame tiers spécifique, ce qui permet de maintenir l'état de la session sans activer le suivi intersites. L'utilisateur devra se reconnecter pour chaque intégration sur un site différent.
Protéger le point de terminaison avec Content Security Policy
Alors que la stratégie d'autorisation détermine si votre iframe peut exécuter WebAuthn, la Content Security Policy (CSP) détermine qui est autorisé à héberger votre iframe.
Pour un point de terminaison d'authentification, il est essentiel de s'assurer que seuls les sites partenaires autorisés ou vos propres propriétés peuvent charger le sous-cadre de connexion, ce qui empêche les tentatives de détournement de clic non autorisées avant même qu'elles ne puissent charger l'UI.
Utiliser frame-ancestors
La directive frame-ancestors définit les pages parentes valides qui peuvent intégrer votre site. En ajoutant des domaines à cette directive, vous pouvez autoriser les domaines qui sont autorisés à intégrer le sous-cadre de connexion.
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
Compatibilité de la directive "frame-ancestors" de la Content Security Policy :
Ensemble X-Frame-Options
L'ancien en-tête X-Frame-Options offre des fonctionnalités similaires, mais n'est compatible qu'avec les options binaires (DENY ou SAMEORIGIN). Définissez à la fois frame-ancestors et X-Frame-Options: DENY pour la CSP au cas où le navigateur ne la prendrait pas en charge. La CSP est toujours prioritaire lorsqu'elle est prise en charge.
X-Frame-Options: DENY
Compatibilité X-Frame-Options :
Faites confiance, mais vérifiez côté serveur
Les vérifications côté client du navigateur évaluent l'intention et les autorisations, mais le serveur est le juge ultime de la confiance. Vérifiez la réponse sur le serveur Relying Party (RP) pour vous assurer que le contexte est valide et signé.
Charge utile des données client
Les données client WebAuthn incluent des paramètres spécifiquement conçus pour vous aider à vérifier le contexte d'une requête effectuée dans un iFrame :
crossOrigin(booléen) : indique si l'API WebAuthn a été appelée dans un iFrame d'origine croisée. Si votre architecture repose sur des iFrames, votre serveur doit appliquer la valeurtrueà ce flag.topOrigin(chaîne) : origine du contexte de navigation de premier niveau (ce qui est visible dans la barre d'adresse du navigateur). Le serveur doit vérifier cela par rapport à une liste d'origines parentes connues et autorisées.
Checklist de la validation
Pour vérifier la réponse de l'authentificateur sur votre serveur, procédez comme suit :
- Analysez et décodez le
collectedClientDatasigné à partir de la réponse de l'authentificateur. - Assurez-vous que
typecorrespond à la cérémonie (webauthn.getouwebauthn.create). - Vérifiez la présence et la signature de l'utilisateur.
- Si la demande était censée provenir d'une structure iframe :
- Appliquez
crossOrigin === true. - Appliquez la règle selon laquelle
topOrigindoit correspondre à votre liste autorisée d'origines parentales.
- Appliquez
Établir des sessions de manière sécurisée à l'aide de postMessage()
Pour établir une session de manière fiable, l'iFrame doit renvoyer le jeton d'authentification à la page parente à l'aide de postMessage(), ce qui permet à la page parente de gérer l'état de la session dans son propre contexte first party.
Workflow sécurisé
Pour établir une session sécurisée, suivez ce workflow :
- Assurez-vous que l'URL
srcde l'iFrame contient les paramètres de requêtenonceetorigin:- Utilisez une valeur aléatoire pour
nonce. Unnoncesert de jeton de validation de sécurité pour s'assurer que le jeton d'authentification reçu d'un iFrame correspond légitimement à la session spécifique initiée par la page parente. - Utilisez le domaine du frame parent pour
origin. Un paramètreoriginspécifie l'origine de la page parente, ce qui permet à l'iFrame d'identifier de manière sécurisée le contexte autorisé dans lequel il a été intégré.
- Utilisez une valeur aléatoire pour
- L'iFrame effectue l'authentification WebAuthn avec son propre serveur.
Le serveur d'iframe émet un jeton tel qu'un JWT qui inclut
nonceet le transmet à la page parente.// 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 page parente écoute l'événement
message, valide l'origine de l'expéditeur et vérifie le jeton.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 page parente conserve la session si le jeton JWT est validé.
L'expéditeur et le destinataire partagent les responsabilités en termes de sécurité :
- L'expéditeur (iframe) : spécifiez toujours une origine cible stricte lorsque vous envoyez des messages (n'utilisez jamais
"*"). - Le récepteur (parent) : vérifiez toujours
event.originlorsque vous recevez des messages pour éviter l'usurpation d'origine.
Conclusion
L'utilisation sécurisée des iFrames repose sur la règle d'autorisation pour l'activation, la CSP pour la restriction, les cookies tiers partitionnés pour la persistance de session, la validation côté serveur du contexte client et le transfert de session contextuel à l'aide de postMessage().
Pour en savoir plus sur les thèmes associés, consultez le blog Google Chrome pour les développeurs et explorez d'autres ressources dans la documentation sur l'identité des développeurs Chrome.