Pull to refresh

Comments 12

Привет! Кажется если ты уже используешь httponly-куки, то кажется не нужно уже использовать токены, если ты разрабатываешь 1st party приложение.
Токены кажется обычно нужны для 3st party приложений, и там нужно использовать механизмы по типу OAuth2

Вообще имхо jwt нужны только для микросервисной архитектуры чтобы передать информацию типа user_id с подтверждением валидности между теми самыми сервисами. Для обычных приложения вида "фронтэнд + бэкэнд" это избыточно. В некоторых моих проектах клиент вообще не знает своего id (или производных типа profile_id) (он на него вообще не передается ни в каком виде) и все нормально. Естественно, в таких проектах нет p2p взаимодействий, это b2c штуки.

Согласен, что в распределённых системах JWT действительно раскрывается полностью, а для монолита сессионные куки - альтернатива, и каждая команда выбирает свои технологии. Но на практике JWT часто встречается и в фронт + бек, нет хранилища сессий, тот же токен легко отдать мобильному клиенту. Задача статьи - не убедить всех перейти на JWT, а показать безопасную работу с уже выбранной схемой: access не в localStorage, refresh в httponly куках, обработка 401. И ваше мнение о том что клиент не знает своего id, согласен поэтому в claims сложил минимум телефон и тип, потому что payload JWT читается кем угодно - об этом в статье отдельно написано.

Привет! Справедливое замечание: для чистого 1st‑party монолита классическая сессионная httpOnly кука действительно часто достаточно, а OAuth2 реально про third‑party доступ. Статья разбирает другой, не менее частый кейс: SPA + stateless‑бекенд, где команда уже выбрала JWT (нет таблицы сессий, легко масштабироваться горизонтально, одно API для веба и мобилки). И тогда встаёт вопрос, где хранить access‑token, и худший из ответов - localStorage. Статья о том, как реализовать JWT‑схему безопасно: access в памяти, refresh в httponly куках, восстановление сессии, обработка протухшего токена. Можно, конечно, вообще убрать access и остаться в куках - тоже рабочая схема, просто тогда больше внимания нужно уделить CSRF. Так что это просто разбор, если у вас JWT вот как это можно использовать.

  1. Vuex в новых проектах в 2026 году — уже моветон

  2. Как вы решаете проблему нескольких одновременно упавших запросов с 401 из-за протухшего access-токена? По вашей схеме, если мы заходим на страницу, с которой полетит несколько запросов на данные, защищенные авторизацией — каждый пойдет делать запрос на рефреш. С одним refresh-токеном. И у одного из них отвалится по невалидному (использованном) токену. Можно было раскрыть тему Web Locks API

По vuex согласен, pinia более современная рекомендация. Оставил его, потому что механизм (access в памяти + interceptor) переносится на Pinia/React почти без изменений.

По 401 вы правы. В бекенде из статьи это не приводит к разлогину (refresh - stateless JWT и не инвалидируется, все 5 refresh вернули 200), но при ротации с инвалидацией старого токена это была бы гонка с разлогином. Поправить можно попробовать с помощью single‑flight, один летящий refresh промис, все упавшие его ждут, затем повторяются.

После этой правки тот же тест даёт 5×401 дальше 1×refresh и 5×200. Про Web Locks API согласен, single‑flight закрывает гонку внутри вкладки, а для синхронизации между вкладками нужен navigator.locks или BroadcastChannel мне кажется это следующий уровень, достойный отдельной статьи.

В интерсепторе аксиоса или в fetch-враппере, который скорее всего в любом случае будет, чтобы всю эту логику спрятать в апи-клиент, как раз можно отслеживать флаг актуальности авторизации и обновления токена.

Более того, ведь необязательно дожидаться ошибки, можно отследить заранее и запросить токен перед запросом, если он почти протух

Да, реактивная схема уже отслеживает 401 сначала single-flight refresh потом ретрай(про single-flight добавил UPД в статью). Для туториала этого достаточно - так и было задумано. Проактив обновление это следующий уровень поверх, и у него есть свои нюансы. 1. Ставит refresh в критический путь запроса это значит, что пользователь ждёт refresh, хотя с ещё живым токеном запрос прошёл бы сразу. 2. При коротком TTL аксесс токена учащает refresh, если делать каждые 30 секунд перезапрос, против минуты у реактива с одинаковыми входными данными. 3. Добавляет сложность синхронизации между вкладками (тот же Web Locks API). Плюс у proactive один - избежать лишнего фейлового 401 и графика где нибудь в графане на ошибки, в целом его пользователь даже не видит, в статье указывал про сценарий "отошёл попить чай, вернулся, тыкнул" разруливается ретраем незаметно для пользака. Для туториала и большинства приложений реактив + single-flight мне кажется не плохо.

Я, конечно, извиняюсь, но задам неудобные вопросы:

  1. "Это баян", подобных "учебных" статей море, в чём ценность именно этой? Для реального использования не годится из-за простоты, vuex устарел и т.д.

  2. Почему никто не пишет более интересные примеры с реальными кейсами вроде "если 10 одновременных запросов упали с 401, то не надо сразу делать 10 запросов рефреша токенов (а так и будет с кодом всех подобных статей), нужно ждать один запрос обновления, а только потом ретрай всех упавших"?

По «баяну», статей про авторизацию действительно много, но эту я написал именно потому, что не нашёл разбора, где вся цепочка показана с кодом с обеих сторон имеется ввиду - access в переменной фронта, бекенд например на Go с рефреш и логаутом, восстановление сессии после перезагрузки, и обработка протухшего токена. Про куки и локал сторадж статей много, а цельного туториала что храним access в памяти, я не встретил. Это туториал, для того чтобы понять принцип работы, какие то боевые доработки конечно же будут и часть из них вынес в статье в отдельный модуль.

По 10 запросам это справедливо параллельные запросы с протухшим токеном все падают с 401 и interceptor действительно дергает refresh на каждый запрос. Поправить можно попробовать с помощью single‑flight, один летящий refresh промис, все упавшие его ждут, затем повторяются. Про заметку спасибо большое добавлю в UPД статьи.

У вас Path выставлен в "/". Это приводит к тому, что refresh token отправляется в каждом API запросе. Хотя нужен он только например в /refresh. Вот в это и нужно выставить Path

Здравствуйте, сужение Path до "/refresh" - хороший defense-in-depth, чтобы токен не светился в логах посторонних эндпоинтов. Но мне кажется это косметика по идее HttpOnly+SameSite+Secure закрывают основные угрозы. В продакшн можно добавить, но можно и не добавлять в туториале оставил "/" для простоты.

Sign up to leave a comment.

Articles