Как обработать ошибку отсутствия access token в localStorage
Что проверяют
Видите ли вы в отсутствии токена не исключение, а нормальное состояние «пользователь не вошёл», и понимаете ли, где эта логика должна жить. Следом почти всегда спрашивают, стоит ли вообще хранить токен в localStorage и что делать с просроченным.
Как отвечать
Проверка не размазывается по компонентам, она живёт в одном слое:
- чтение:
localStorage.getItem("accessToken")вернётnull, если ключа нет. Обращение оборачивают вtry/catch: хранилище бывает недоступно (браузер запрещает сайтам хранить данные, песочница iframe), аJSON.parseпадает на мусоре; - старт приложения: токена нет, пробуем тихо обновить сессию запросом на
/auth/refreshсcredentials: "include", refresh-токен лежит в httpOnly-cookie. Не вышло, состояние «гость»; - защищённые маршруты: гард в роутере (loader в React Router, guard в Angular, навигационный хук во Vue) отправляет на
/login?returnTo=..., после входа пользователь возвращается туда, откуда пришёл; - HTTP-слой: интерцептор axios или обёртка над
fetchподставляетAuthorizationи ловит 401. Токен может лежать на месте, но быть просроченным или отозванным, поэтому источник правды это ответ сервера; - вкладки: событие
storageсообщает другим вкладкам о входе или выходе.
Хороший ответ заканчивается безопасностью: localStorage читает любой скрипт на странице, и одна XSS уводит токен. Надёжнее держать access-токен в памяти, а refresh-токен в cookie с HttpOnly, Secure и SameSite.
Где спотыкаются
Пишут alert и window.location.href = "/login" в каждой функции. Логика дублируется, и легко получить бесконечный редирект со страницы входа на саму себя.
При 401 каждый параллельный запрос запускает свой refresh. Нужен один общий промис обновления: остальные запросы ждут его и повторяются один раз.
В Next.js и другом SSR обращаются к localStorage во время серверного рендера и получают ReferenceError. Читать его можно только на клиенте, например в useEffect.