Как организовать получение токена в веб-приложении
Что проверяют
Понимаете ли вы, где токен живёт в браузере и от каких атак это защищает, а от каких нет. Интервьюер ждёт, что вы отличите OAuth 2.0 (протокол) от JWT (формат токена) и опишете обновление токена без гонок. Следом почти всегда спрашивают: localStorage или cookie и почему.
Как отвечать
Сначала уточните, это свой логин по паролю или вход через внешнего провайдера. Для SPA с провайдером актуален Authorization Code с PKCE, а implicit flow рекомендации OAuth Security BCP (RFC 9700) использовать не советуют.
- BFF как вариант по умолчанию: токены держит серверная прослойка, браузер получает только сессионную cookie с флагами
HttpOnly,Secure,SameSite. JavaScript до токена не дотянется даже при XSS; - если токены на клиенте: короткий access token в памяти, refresh token в
HttpOnlycookie с узкимPathна эндпоинт обновления и ротацией при каждом использовании; - cookie и CSRF:
SameSite=Laxзакрывает большую часть сценариев, для изменяющих запросов добавляют CSRF-токен; - обновление без гонок: перехватчик на 401 (interceptor в axios или обёртка над
fetch) запускает refresh один раз, а остальные запросы ждут тот же промис. Иначе при ротации второй параллельный refresh получит отказ и выкинет пользователя; - несколько вкладок: вход и выход синхронизируют через
BroadcastChannel; - выход: refresh token отзывают на сервере, а не только стирают у себя.
Для OIDC на клиенте есть готовые библиотеки вроде oidc-client-ts, писать протокол руками незачем.
Где спотыкаются
Кладут токен в localStorage и называют это безопасным. Любой внедрённый скрипт прочитает его одной строкой.
Считают, что JWT зашифрован. Payload закодирован в base64url и читается кем угодно, подпись защищает только от подделки.
Хранят client_secret в коде SPA. Публичный клиент секрет сохранить не может, для него и придуман PKCE.