Что делать с данными в localStorage при разлогине пользователя
Что проверяют
Понимаете ли вы, что разлогин это не одна строка localStorage.clear(), а согласованная очистка на сервере и на клиенте. И отличаете ли хранение от безопасности: удаление токена из хранилища не отзывает сессию.
Как отвечать
Порядок действий при выходе:
- сначала запрос на сервер, который гасит серверную сессию или refresh-токен и сбрасывает httpOnly-куку;
- потом локальная очистка, причём она выполняется даже если запрос не прошёл;
- потом сброс состояния в памяти: стор, кэш запросов, подписки и сокеты;
- в конце переход на страницу входа.
Чистить нужно свои ключи по префиксу, а не всё подряд. На том же origin живут согласие на куки, выбранная тема, ключи аналитики и соседних приложений, и clear() сносит их вместе с сессией.
for (const key of Object.keys(localStorage)) {
if (key.startsWith("app:")) localStorage.removeItem(key);
}Не забудьте про остальные хранилища: sessionStorage, IndexedDB, кэш библиотеки запросов. И про вкладки: событие storage срабатывает в других вкладках того же origin, по нему они переводятся в разлогиненное состояние. В своей вкладке оно не сработает, там состояние меняется напрямую.
Где спотыкаются
Считают sessionStorage безопасной альтернативой. От межсайтового скриптинга он защищает ровно так же, то есть никак: выполненный на странице скрипт читает оба хранилища. Разница только в сроке жизни и в том, что данные не видны другим вкладкам. От чтения скриптом защищает httpOnly-кука.
Чистят только клиент. Сервер про выход не знает, сессия и refresh-токен живы, и снятая заранее копия токена продолжает работать. Выход обязан начинаться с серверного вызова.
Забывают про память. Хранилище пустое, а стор и кэш запросов ещё держат профиль и списки предыдущего пользователя, и до перезагрузки страницы интерфейс показывает чужие данные. Заметнее всего это на общем компьютере, ради которого разлогин и делают.