Um eine reibungslose, kontextbezogene Authentifizierung über mehrere Domains hinweg zu ermöglichen, betten Organisationen Anmeldeseiten häufig in iFrames ein. Wenn Authentifizierungskontexte jedoch in Frames von Drittanbietern geladen werden, sind Nutzer kritischen Bedrohungen wie Clickjacking (UI-Redressing) und der unbefugten Erstellung von Anmeldedaten ausgesetzt. Um diese Risiken zu minimieren, deaktivieren Browser WebAuthn in ursprungsübergreifenden iFrames standardmäßig. Um diese Einschränkung sicher aufzuheben, sind aktive Defense-in-Depth-Protokolle erforderlich.
Bedrohungsmodelle identifizieren
Bevor Sie Passkeys (WebAuthn) in Unterframes aktivieren, sollten Sie sich mit den Missbrauchsszenarien vertraut machen, gegen die Sie sich schützen möchten:
- Tracking durch Einfügen eines verborgenen iFrames:Ein Angreifer löst über eine Anzeige oder ein Widget auf einer vertrauenswürdigen Website einen WebAuthn-Prompt von seiner eigenen Domain aus und bringt Nutzer so dazu, einen Passkey zu autorisieren, ohne den Kontext zu sehen. Dadurch wird die Identität des Nutzers mit einem vom Angreifer kontrollierten Konto verknüpft, um Daten zu sammeln.
- Visuelles Overlay und Clickjacking (UI-Redressing): Auf einer schädlichen übergeordneten Seite wird der Authentifizierungs-iFrame mit Standard-CSS unsichtbar gemacht und ein gefälschtes UI-Element überlagert, um einen Klick zu stehlen, der einen Authentifizierungsablauf auslöst. Dies kann zu Session-Hijacking oder erzwungenen unbefugten Aktionen führen, wenn der Nutzer den Prompt versehentlich abschließt.
So können Sie diesen Bedrohungen entgegenwirken:
Für das Dokument der obersten Ebene (Top-Frame):
Für das eingebettete Dokument (iFrame):
- Partitionierte Drittanbieter-Cookies aktivieren
- Endpunkt mit Content Security Policy schützen
- Serverseitig vertrauen, aber überprüfen
Für beide Dokumente gilt:
Delegierung mit der Berechtigungsrichtlinie aktivieren
Browser blockieren standardmäßig den Zugriff auf WebAuthn in ursprungsübergreifenden iFrames. Die Permissions Policy ist der einheitliche Mechanismus der Webplattform, mit dem ein Dokument der obersten Ebene diese leistungsstarken Funktionen explizit an bestimmte, vertrauenswürdige Drittanbieterursprünge delegieren kann.
Funktionstokens
WebAuthn verwendet zwei verschiedene Tokens:
publickey-credentials-get: Gewährt die Autorisierung für die Anmeldung mit Passkeys (navigator.credentials.get()).publickey-credentials-create: Gewährt die Autorisierung für die Registrierung von Passkeys (navigator.credentials.create()).
Voraussetzungen für die Aktivierung
Wenn Sie diese Funktionen aktivieren möchten, müssen Sie sowohl die Antwort des übergeordneten Servers als auch das clientseitige Markup anpassen:
- HTTP-Antwortheader „Permissions-Policy“ (übergeordnete Serverwebsite): Die übergeordnete Seite muss die zulässigen Ursprünge in ihren HTTP-Antwortheadern mit der Syntax für strukturierte Felder deklarieren.
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
Berechtigungsrichtlinie: Kompatibilität von publickey-credentials-get:
Berechtigungsrichtlinie: Kompatibilität von publickey-credentials-create:
- Das HTML-Attribut
allow:Im HTML-Markup muss das<iframe>-Element auch deklarieren, dass es die Funktion aktiviert.
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
Kompatibilität von iFrame mit allow="publickey-credentials-get":
Browser Support
Kompatibilität von iFrame mit allow="publickey-credentials-create":
Browser Support
Partitionierte Drittanbieter-Cookies aktivieren
Damit der Authentifizierungsablauf zuverlässig ist, muss eine Sitzung im eingebetteten iframe mit ursprungsübergreifendem Zugriff eingerichtet und aufrechterhalten werden. Da moderne Browser auf strenge Einschränkungen für Drittanbieter-Cookies umgestellt haben, werden standardmäßige Persistenzmechanismen oft standardmäßig blockiert. Möglicherweise muss die Storage Access API aufgerufen werden, um Zugriff zu erhalten.
Um diese Hindernisse zu umgehen, konfigurieren Sie Ihre Sitzungscookies mit den Attributen SameSite:
None, Secure und Partitioned. Dieser einheitliche Plattformmechanismus sorgt für einen persistenten Status im iFrame und berücksichtigt gleichzeitig die Datenschutzeinstellungen auf Browserebene.
SameSite: None festlegen
SameSite:
None
kennzeichnet ein Cookie explizit für den websiteübergreifenden Zugriff, sodass es mit Anfragen gesendet werden kann, die aus einem Drittanbieterkontext (z. B. einem iFrame) stammen. Dieses Attribut ist eine Voraussetzung dafür, dass Cookies in Cross-Origin-Szenarien funktionieren. Es muss jedoch mit dem Attribut Secure kombiniert werden, damit es von modernen Browsern akzeptiert wird.
Partitioned festlegen
Mit dem Attribut Partitioned wird das Cookie für CHIPS (Cookies Having Independent Partitioned State) aktiviert. Dadurch kann das Cookie für jede Top-Level-Website separat gespeichert werden. So bleibt das Cookie im Kontext des jeweiligen Drittanbieter-iFrames zugänglich und der Sitzungsstatus kann beibehalten werden, ohne dass websiteübergreifendes Tracking aktiviert werden muss. Der Nutzer muss sich für jedes Einbettungselement auf einer anderen Website noch einmal anmelden.
Endpunkt mit Content Security Policy schützen
Während mit der Permissions Policy festgelegt wird, ob in Ihrem iFrame WebAuthn ausgeführt werden kann, wird mit der Content Security Policy (CSP) festgelegt, wer Ihr iFrame hosten darf.
Bei einem Authentifizierungsendpunkt ist es entscheidend, dass nur autorisierte Partnerwebsites oder Ihre eigenen Properties den Anmelde-Subframe laden können. Dadurch werden nicht autorisierte Clickjacking-Versuche unterbunden, bevor die Benutzeroberfläche überhaupt geladen werden kann.
„frame-ancestors“ verwenden
Mit der frame-ancestors-Anweisung werden die gültigen übergeordneten Seiten definiert, auf denen Ihre Website eingebettet werden kann. Wenn Sie dieser Direktive Domains hinzufügen, können Sie die Domains zulassen, die den Anmelde-Subframe einbetten dürfen.
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
Content Security Policy: frame-ancestors compatibility (Content Security Policy: frame-ancestors-Kompatibilität):
X-Frame-Options festlegen
Der alte X-Frame-Options-Header bietet ähnliche Funktionen, unterstützt aber nur binäre Optionen (DENY oder SAMEORIGIN). Legen Sie sowohl CSP frame-ancestors als auch X-Frame-Options: DENY fest, falls der Browser CSP nicht unterstützt. CSP hat immer Priorität, sofern es unterstützt wird.
X-Frame-Options: DENY
Kompatibilität mit X-Frame-Options:
Serverseitig prüfen
Bei den clientseitigen Prüfungen des Browsers werden Absicht und Berechtigungen ausgewertet, aber der Server ist der letztendliche Schiedsrichter für Vertrauen. Überprüfen Sie die Antwort auf dem Server der vertrauenden Partei (Relying Party, RP), um sicherzustellen, dass der Kontext gültig und signiert ist.
Clientdatennutzlast
WebAuthn-Clientdaten enthalten Parameter, die speziell dafür entwickelt wurden, den Kontext einer Anfrage zu überprüfen, die in einem iFrame gestellt wurde:
crossOrigin(boolesch): Gibt an, ob die WebAuthn API in einem ursprungsübergreifenden iFrame aufgerufen wurde. Wenn Ihre Architektur auf iFrames basiert, muss Ihr Server erzwingen, dass dieses Flagtrueist.topOrigin(String): Der Ursprung des Browsing-Kontexts der obersten Ebene (was in der Adressleiste des Browsers zu sehen ist). Der Server muss dies anhand einer Liste bekannter, autorisierter übergeordneter Ursprünge überprüfen.
Checkliste für die Bestätigung
So prüfen Sie die Authentifikatorantwort auf Ihrem Server:
- Parsen und decodieren Sie die signierte
collectedClientDataaus der Authentifikatorantwort. - Prüfen Sie, ob
typemit der Zeremonie (webauthn.getoderwebauthn.create) übereinstimmt. - Prüfen Sie die Anwesenheit und die Signatur des Nutzers.
- Wenn die Anfrage von einer iFrame-Struktur stammen sollte:
- Erzwingen Sie
crossOrigin === true. - Erzwingen Sie, dass
topOriginmit Ihrer autorisierten Liste von übergeordneten Quellen übereinstimmt.
- Erzwingen Sie
Sitzungen mit postMessage() sicher einrichten
Damit eine Sitzung zuverlässig eingerichtet werden kann, muss das iFrame das Authentifizierungstoken über postMessage() an die übergeordnete Seite zurückgeben. So kann die übergeordnete Seite den Sitzungsstatus im eigenen Kontext verwalten.
Sicherer Workflow
So richten Sie eine sichere Sitzung ein:
- Achten Sie darauf, dass die
src-URL des iFrames die Suchparameternonceundoriginenthält:- Verwenden Sie einen zufälligen Wert für
nonce. Einnoncedient als Sicherheitsüberprüfungstoken, um sicherzustellen, dass das vom iFrame empfangene Authentifizierungstoken der von der übergeordneten Seite initiierten Sitzung entspricht. - Verwenden Sie die Domain des übergeordneten Frames für
origin. Mit dem Parameteroriginwird der Ursprung der übergeordneten Seite angegeben. So kann der iFrame den autorisierten Kontext, in den er eingebettet wurde, sicher identifizieren.
- Verwenden Sie einen zufälligen Wert für
- Das iFrame schließt die WebAuthn-Authentifizierung mit seinem eigenen Server ab.
Der Iframe-Server gibt ein Token wie ein JWT aus, das die
nonceenthält, und leitet zur übergeordneten Seite weiter.// 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);Die übergeordnete Seite wartet auf das
message-Ereignis, validiert den Ursprung des Absenders und prüft das 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, }); });Auf der übergeordneten Seite wird die Sitzung beibehalten, wenn das JWT erfolgreich überprüft wurde.
Sowohl der Absender als auch der Empfänger sind für die Sicherheit verantwortlich:
- Absender (iFrame): Geben Sie beim Senden von Nachrichten immer einen strengen Zielursprung an (verwenden Sie niemals
"*"). - Der Empfänger (Elternteil): Überprüfen Sie beim Empfang von Nachrichten immer
event.origin, um das Spoofing von Absendern zu verhindern.
Fazit
Die sichere Verwendung von iFrames hängt von der Permissions Policy für die Aktivierung, CSP für die Einschränkung, partitionierten Drittanbieter-Cookies für die Sitzungspersistenz, serverseitigen Überprüfung des Clientkontexts und kontextsensitiven Sitzungsübergabe mit postMessage() ab.
Weitere Informationen zu verwandten Themen finden Sie im Chrome-Entwicklerblog von Google und in der Dokumentation zur Chrome-Entwickleridentität.