Aby zapewnić płynne uwierzytelnianie w kontekście w wielu domenach, organizacje często umieszczają strony logowania w ramkach iframe. Jednak wczytywanie kontekstów uwierzytelniania w ramkach innych firm naraża użytkowników na poważne zagrożenia, takie jak clickjacking (przekierowanie interfejsu) i nieautoryzowane tworzenie danych logowania. Aby ograniczyć to ryzyko, przeglądarki domyślnie wyłączają WebAuthn w elementach iframe z innych domen. Bezpieczne zniesienie tego ograniczenia wymaga aktywnych protokołów obrony warstwowej.
Identyfikowanie modeli zagrożeń
Zanim włączysz klucze dostępu (WebAuthn) w ramkach podrzędnych, zapoznaj się ze scenariuszami nadużyć, przed którymi chcesz się chronić:
- Śledzenie za pomocą wstrzykiwania ukrytego elementu iframe: atakujący wywołuje prośbę WebAuthn z własnej domeny za pomocą reklamy lub widżetu w zaufanej witrynie, nakłaniając użytkowników do autoryzacji klucza dostępu bez znajomości kontekstu. Powoduje to powiązanie tożsamości użytkownika z kontem kontrolowanym przez atakującego, co umożliwia zbieranie danych.
- Nakładka wizualna i clickjacking (przekształcanie interfejsu): złośliwa strona nadrzędna renderuje ramkę iframe uwierzytelniania jako niewidoczną za pomocą standardowego CSS-u i nakłada na nią fałszywy element interfejsu, aby przechwycić kliknięcie, które uruchamia przepływ uwierzytelniania. Jeśli użytkownik nieumyślnie wykona prompt, może to doprowadzić do przejęcia sesji lub wymuszenia nieautoryzowanych działań.
Aby przeciwdziałać tym zagrożeniom, stosuj te sprawdzone metody:
W przypadku dokumentu najwyższego poziomu (głównej ramki):
W przypadku dokumentu umieszczonego (element iframe):
- Włączanie partycjonowanych plików cookie innych firm
- Zabezpieczanie punktu końcowego za pomocą zasady Content Security Policy
- Zaufaj, ale zweryfikuj po stronie serwera
W przypadku obu dokumentów:
Włączanie przekazywania uprawnień za pomocą zasad uprawnień
Przeglądarki domyślnie blokują dostęp do WebAuthn w międzyźródłowych elementach iframe. Permissions Policy to ujednolicony mechanizm platformy internetowej, który umożliwia dokumentowi najwyższego poziomu wyraźne przekazywanie tych zaawansowanych funkcji określonym, zaufanym źródłom zewnętrznym.
Tokeny funkcji
WebAuthn używa 2 rodzajów tokenów:
publickey-credentials-get: przyznaje autoryzację w przypadku logowania za pomocą klucza dostępu (navigator.credentials.get()).publickey-credentials-create: przyznaje autoryzację w przypadku przepływów rejestracji klucza dostępu (navigator.credentials.create()).
Wymagania dotyczące włączania
Włączenie tych funkcji wymaga zgodności zarówno w odpowiedzi serwera nadrzędnego, jak i w kodzie po stronie klienta:
- Nagłówek odpowiedzi HTTP Permissions-Policy (serwer witryny nadrzędnej): strona nadrzędna musi zadeklarować dozwolone domeny w nagłówkach odpowiedzi HTTP, używając składni pól strukturalnych.
Permissions-Policy: publickey-credentials-get=(self "https://embedded-auth.example.com")
Zasady dotyczące uprawnień: zgodność interfejsu publickey-credentials-get:
Zasady dotyczące uprawnień: zgodność z publickey-credentials-create:
- Atrybut HTML
allow: w znaczniku HTML element<iframe>musi też deklarować, że włącza tę funkcję.
<iframe src="https://embedded-auth.example.com?nonce=deadbeef12345678&client=https%3A%2F%2Fembedded-auth.example.com" allow="publickey-credentials-get"></iframe>
Zgodność elementu iframe z atrybutem allow="publickey-credentials-get":
Browser Support
Zgodność elementu iframe z atrybutem allow="publickey-credentials-create":
Browser Support
Włączanie partycjonowanych plików cookie innych firm
Aby zapewnić niezawodny proces uwierzytelniania, w osadzonym elemencie iframe z innej domeny musi zostać utworzona i utrzymana sesja. W miarę jak nowoczesne przeglądarki przechodzą na rygorystyczne ograniczenia dotyczące plików cookie innych firm, standardowe mechanizmy utrwalania są często domyślnie blokowane i mogą wymagać wywołania interfejsu Storage Access API, aby uzyskać dostęp.
Aby uniknąć tych problemów, skonfiguruj pliki cookie sesji za pomocą atrybutów SameSite:
None, Secure i Partitioned. Ten ujednolicony mechanizm platformy
zapewnia trwały stan w ramach elementu iframe przy jednoczesnym poszanowaniu ustawień prywatności na poziomie przeglądarki.
Zestaw SameSite: None
SameSite:
None
wyraźnie oznacza plik cookie jako dostępny w wielu witrynach, co umożliwia wysyłanie go z żądaniami pochodzącymi z kontekstu innej firmy (np. z elementu iframe). Ten atrybut jest warunkiem wstępnym działania plików cookie w scenariuszach obejmujących różne domeny, ale musi być połączony z atrybutem Secure, aby był akceptowany przez nowoczesne przeglądarki.
Zestaw Partitioned
Atrybut Partitioned włącza plik cookie w technologii CHIPS (Cookies Having Independent Partitioned State), dzięki czemu plik cookie jest przechowywany oddzielnie dla każdej witryny najwyższego poziomu. Dzięki temu plik cookie pozostaje dostępny w konkretnym kontekście elementu iframe innej firmy, co umożliwia utrzymanie stanu sesji bez włączania śledzenia w witrynach. Użytkownik będzie musiał zalogować się ponownie w przypadku każdego osadzenia w innej witrynie.
Ochrona punktu końcowego za pomocą standardu Content Security Policy
Zasady dotyczące uprawnień określają, czy element iframe może uruchamiać WebAuthn, a Content Security Policy (CSP) określają, kto może hostować element iframe.
W przypadku punktu końcowego uwierzytelniania kluczowe jest zapewnienie, że tylko autoryzowane witryny partnerów lub Twoje własne usługi mogą wczytywać ramkę podrzędną logowania. Dzięki temu można zapobiegać nieautoryzowanym próbom klikania w celu oszustwa, zanim jeszcze wczyta się interfejs.
Używaj funkcji frame-ancestors
frame-ancestorsDyrektywa
określa prawidłowe strony nadrzędne, które mogą osadzać Twoją witrynę. Dodając domeny do tej dyrektywy, możesz zezwolić na domeny, które mogą osadzać ramkę podrzędną logowania.
Content-Security-Policy: frame-ancestors 'self' https://parent-site.example.com;
Zgodność z zasadami Content Security Policy: frame-ancestors:
Zestaw X-Frame-Options
Starszy nagłówek X-Frame-Options obsługuje podobne funkcje, ale tylko opcje binarne (DENY lub SAMEORIGIN). Ustaw oba nagłówki CSP frame-ancestors i X-Frame-Options: DENY na wypadek, gdyby przeglądarka nie obsługiwała CSP. CSP jest zawsze traktowany priorytetowo, jeśli jest obsługiwany.
X-Frame-Options: DENY
Zgodność z X-Frame-Options:
Zaufaj, ale weryfikuj po stronie serwera
Sprawdzanie po stronie klienta w przeglądarce ocenia intencje i uprawnienia, ale ostatecznym arbitrem zaufania jest serwer. Sprawdź odpowiedź na serwerze Relying Party (RP), aby upewnić się, że kontekst jest prawidłowy i podpisany.
Ładunek danych klienta
Dane klienta WebAuthn zawierają parametry zaprojektowane specjalnie po to, aby pomóc Ci w weryfikacji kontekstu żądania wysłanego w ramce iframe:
crossOrigin(boolean): wskazuje, czy interfejs WebAuthn API został wywołany w ramce iframe z innej domeny. Jeśli Twoja architektura opiera się na elementach iframe, serwer musi wymuszać, aby ten flag był ustawiony natrue.topOrigin(string): pochodzenie kontekstu przeglądania najwyższego poziomu (to, co jest widoczne na pasku adresu przeglądarki). Serwer musi zweryfikować ten element na podstawie listy znanych, autoryzowanych domen nadrzędnych.
Lista kontrolna weryfikacji
Aby zweryfikować odpowiedź uwierzytelniania na serwerze, wykonaj te czynności:
- Przeanalizuj i zdekoduj podpisany obiekt
collectedClientDataz odpowiedzi uwierzytelniania. - Upewnij się, że
typepasuje do ceremonii (webauthn.getlubwebauthn.create). - Sprawdź obecność użytkownika i jego podpis.
- Jeśli żądanie miało pochodzić ze struktury elementu iframe:
- Wymuś
crossOrigin === true. - Wymuszaj, aby
topOriginpasowało do autoryzowanej listy źródeł nadrzędnych.
- Wymuś
Bezpieczne nawiązywanie sesji za pomocą postMessage()
Aby niezawodnie utworzyć sesję, element iframe musi przekazać token uwierzytelniania z powrotem do strony nadrzędnej za pomocą funkcji postMessage(), umożliwiając stronie nadrzędnej zarządzanie stanem sesji w kontekście własnych danych.
Bezpieczny przepływ pracy
Aby nawiązać bezpieczną sesję, wykonaj te czynności:
- Sprawdź, czy adres URL elementu iframe
srczawiera parametry zapytanianonceiorigin:- Użyj losowej wartości w przypadku parametru
nonce.noncepełni funkcję tokena weryfikacji bezpieczeństwa, który zapewnia, że token uwierzytelniania otrzymany z elementu iframe jest zgodny z sesją zainicjowaną przez stronę nadrzędną. - Użyj domeny ramki nadrzędnej dla parametru
origin. Parametroriginokreśla źródło strony nadrzędnej, co umożliwia elementowi iframe bezpieczne zidentyfikowanie autoryzowanego kontekstu, w którym został umieszczony.
- Użyj losowej wartości w przypadku parametru
- Element iframe przeprowadza uwierzytelnianie WebAuthn na własnym serwerze.
Serwer elementu iframe wydaje token, np. JWT, który zawiera
nonce, i przekazuje go na stronę nadrzędną.// 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);Strona nadrzędna nasłuchuje zdarzenia
message, sprawdza pochodzenie nadawcy i weryfikuje 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, }); });Strona nadrzędna zachowuje sesję, jeśli token JWT zostanie zweryfikowany.
Nadawca i odbiorca ponoszą wspólną odpowiedzialność za bezpieczeństwo:
- Nadawca (element iframe): podczas wysyłania wiadomości zawsze podawaj dokładny docelowy adres pochodzenia (nigdy nie używaj
"*"). - Odbiorca (rodzic): zawsze weryfikuj
event.originpodczas odbierania wiadomości, aby zapobiec podszywaniu się pod nadawcę.
Podsumowanie
Bezpieczne używanie elementu iframe zależy od włączenia za pomocą zasady uprawnień, ograniczenia za pomocą CSP, podzielonych plików cookie innych firm w celu zachowania sesji, weryfikacji po stronie serwera kontekstu klienta i przekazywania sesji z uwzględnieniem kontekstu za pomocą postMessage().
Więcej informacji na powiązane tematy znajdziesz na blogu Google dla deweloperów Chrome oraz w dokumentacji dotyczącej tożsamości dewelopera Chrome.