1

Тема: Зберігання JWT в браузері

Всім привіт.

Розбираюсь з роботою авторизації в Blazor web asm, а саме використання JWT. В цілому основні моменти зрозуміли: отримуємо токен, потім підставляємо його в заголовок кожного запиту. Для роботи авторизації на стороні клієнта реалізував AuthenticationStateProvider, який дивиться токен и по ньому будує AuthenticationState.

Питання де саме варто зберігати JWT на стороні клієнта? В мережі знайшов два підхода: тримати в локальній зміній, і відновлювати значення через кукіси, та через локальне сховище браузера.

На початку здавалось що кукіси більш безпечний варіант, але поміркувавши зрозумів що при доступі атакуючої сторони до js на сторінці вона може як зчитати сторедж, так і надіслати refresh запит з кукісами. Тобто явної переваги у жодного з методів по суті немає.

А от проблем використання наче більше з варіантом локальна змінна + кукіси. Наприклад я авторизуюсь, відкриваю копію сторінки, виходжу з аккаунту, заходжу під іншим. На першій сторінці в змінній все ще старий JWT, причому він може бути все ще валідним.

Локальний сторедж наче позбавлений такого недоліку, так як це єдина точка доступу і ми додатково можемо на самій сторінці перевіряти по таймеру чи не змінилось це значення і відповідно реагувати.

Хотілось би почути думку людей, які більше працювали з OAuth 2, можливо є ще якісь цікаві моменти чи сценарії. Або взагалі інші підходи до реалізації.

2

Re: Зберігання JWT в браузері

Ви праві, що при XSS обидва варіанти однаково програють — але це не робить їх рівними. Різниця в тому, ЩО саме дістанеться атакуючому.

Робочий компроміс, який зазвичай і використовують: access-токен живе тільки в пам'яті (звичайне поле сервісу, ніякого стореджу), а refresh-токен лежить у httpOnly + Secure + SameSite кукі. JS до нього не дістається взагалі — ні ваш, ні чужий. При старті вкладки робите тихий refresh на свій ендпоінт, кука їде сама, у відповідь приходить новий access. Тоді XSS може вкрасти максимум короткоживучий access (хвилин на 5-15), а не вічний вхід.

З httpOnly кукою треба закрити CSRF на самому refresh-ендпоінті — SameSite=Strict або окремий anti-CSRF токен, бо інакше чужа сторінка зможе смикнути оновлення.

Щодо «залишкового токена» у другій вкладці — це проблема не сховища, а того, що вихід у вас лише клієнтський. Навіть з localStorage стара вкладка встигне походити з валідним токеном до наступної перевірки таймером. Лікується двома речами: на бекенді при виході ревокуєте refresh (тоді вкладка просто не продовжиться), а між вкладками синхронізуєте вихід через BroadcastChannel — миттєво і без опитування по таймеру.

Для Blazor WASM ще один нюанс: усе, що доступне через JS interop, доступне й атакуючому скрипту, тож «сховати» токен на клієнті неможливо в принципі. Тому питання не де зберігати, а наскільки коротко він живе і чи можна його відкликати.

Подякували: Wolf.dp1

3

Re: Зберігання JWT в браузері

Добре, а щодо зручності використання? Чи є якісь кейси, коли вигідніше тримати JWT в стореджі, а не як внутрішня зміна?