Как сделать так, чтобы авторизация не сбрасывалась при закрытии браузера при токене с временем жизни сутки
Что проверяют
Понимаете ли вы, где живёт токен и почему он пропадает при закрытии браузера, и умеете ли выбрать хранилище с учётом безопасности. Следом спрашивают про XSS, CSRF и о том, что делать, когда токен истёк.
Как отвечать
Сначала назовите причину. Токен теряется, если лежит в памяти приложения, в sessionStorage или в cookie без Expires и Max-Age: такая cookie сессионная и удаляется с закрытием браузера. Некоторые браузеры с восстановлением вкладок её сохраняют, но полагаться на это нельзя.
Варианты решения:
- постоянная cookie от сервера: ответ на логин с заголовком
Set-Cookie: token=...; Max-Age=86400; Path=/; HttpOnly; Secure; SameSite=Lax. Браузер сам отправит её с каждым запросом, а скрипт на странице её не прочитает. Это вариант по умолчанию; localStorage: переживает перезапуск браузера и прост в коде, но доступен любому скрипту на странице, поэтому одна XSS уносит токен;- пара access и refresh: короткий access-токен держится в памяти, долгий refresh-токен лежит в
HttpOnlycookie. При старте приложение вызывает эндпоинт обновления и получает свежий access без повторного входа.
Дальше про срок жизни. На старте клиент проверяет exp (для JWT это поле в payload) и не шлёт заведомо просроченный токен, а на ответ 401 пробует обновиться один раз и, если не вышло, отправляет на страницу входа. Окончательное решение всё равно принимает сервер. Хорошо добавить галочку «Запомнить меня»: без неё cookie ставится сессионной.
Где спотыкаются
Пишут HttpOnly в document.cookie. Этот флаг выставляет только сервер через Set-Cookie, из JavaScript такую cookie нельзя ни создать, ни прочитать.
Кладут токен в localStorage и называют это безопасным, не упомянув XSS и Content Security Policy.
Переходят на cookie и забывают про CSRF. Нужен SameSite=Lax или Strict, а для чувствительных операций ещё и CSRF-токен.