Safari całkowicie nie pozwala ustawiać plików cookie w ramkach iframe domen innych niż domena nadrzędna, nagłówki CORS po stronie serwera niech będą przeklęte.
Aby wyjaśnić: użytkownik jest na domainA.com. Ramka iframe dla domainB.com jest otwarta i próbuje uwierzytelnić użytkownika na domainB.com w ramce iframe. Nagłówek Set-Cookie jest zwracany z serwera w ramce iframe domainB.com ze wszystkimi wymaganymi nagłówkami, ale Safari nie odsyła go w kolejnych wywołaniach.
Stare obejście polegało na przesłaniu formularza z ramki iframe i ustawieniu pliku cookie w odpowiedzi. Myślę, że spodobał im się fakt, że użytkownik klikał coś, aby przesłać formularz. Musiałbyś sondować plik cookie, aby zobaczyć, kiedy odpowiedź wróciła, ponieważ przesłane formularze nie mają wywołań zwrotnych, aw przypadku plików cookie HttpOnly nie można, ale hej, zadziałało! Aż nie.
Następnie nowszym obejściem było przekierowanie użytkownika do domeny iframe w nowym oknie / karcie, ustawienie tam losowego pliku cookie i od tego momentu ta subdomena była „zaufana” w ramce iframe. Ponownie wymagało to kliknięcia, aby otworzyć nowe okno / kartę, a nawet pojawiło się wizualne wskazanie otwarcia nowej karty. Dużo bezpieczeństwa, takie standardy.
A teraz, od Safari 13 - Koniec z obejściem. Nigdy więcej bezpiecznego ustawienia plików cookie iframe 🤬
Każdy inny schemat uwierzytelniania nie jest dla nas dobry (np. Nagłówek Auth-X). Musimy użyć bezpiecznego pliku cookie HttpOnly, ponieważ nie chcemy, aby ten token był w jakikolwiek sposób dostępny po stronie klienta javascript.
Żeby było jasne, wszystko działa świetnie w każdej innej przeglądarce.
Czy ktoś ma jakieś sugestie?
Edytować:
Dzięki za link @ tomschmidt, który wydaje się właściwym kierunkiem. Próbowałem użyć interfejsu API Storage Storage firmy Apple, ale niestety, mimo inicjowania logiki logowania za pomocą interfejsu API muszę się poprosić o dostęp:
requestStorageAccess = async() => {
return new Promise(resolve => {
//@ts-ignore
document.requestStorageAccess().then(
function () {
console.log('Storage access was granted');
resolve(true);
},
function () {
console.log('Storage access was denied');
resolve(false);
}
);
});
}
const storageAccessGranted = await requestStorageAccess();
console.log(storageAccessGranted) // prints 'true'
await login();
Jednak pliki cookie otrzymane w odpowiedzi na interfejs API / login nie są wysyłane w kolejnych wywołaniach interfejsu API :(
źródło
Odpowiedzi:
Myślę, że mogłem znaleźć rozwiązanie: Apple's Storage Access API: https://webkit.org/blog/8124/introducing-storage-access-api/
źródło
To obejście nadal działa, dopóki nowe okno przechowuje ciasteczko, które chcesz przechowywać. Element iframe nadal nie może przechowywać własnych plików cookie. W moim przypadku wszystko, czego potrzebowałem, to plik cookie identyfikatora sesji. Otwieram więc małe okienko wyskakujące, gdy użytkownik udziela dostępu do pamięci. Pobiera i przechowuje plik cookie identyfikatora sesji, zamyka i ponownie ładuje ramkę iframe. Ramka iframe ma wówczas dostęp do pliku cookie identyfikatora sesji i wysyła go w kolejnych żądaniach. Myślę, że to tylko tymczasowe, wygląda na to, że w przyszłości usuną dostęp do pamięci z okien wyskakujących. Może naprawią, że iframe nie będzie w stanie przechowywać plików cookie.
źródło