Что такое безопасность на фронтенде на примере хранения токенов в localStorage и куках
Что проверяют
Знаете ли вы модель угроз, а не пару заученных строк про то, что localStorage плохой, а кука хорошая. Фронтендер решает, куда ляжет токен, и отвечает за то, что случится со входом пользователя, если на страницу попадёт чужой скрипт.
Как отвечать
Начните с главного: при XSS всё, до чего дотягивается JavaScript, считается скомпрометированным. localStorage читает любой скрипт на странице, включая код из транзитивной зависимости или счётчика, поэтому долгоживущий токен там беззащитен.
Кука с флагом HttpOnly недоступна из JavaScript, и выгрести её скриптом нельзя. Но это не защита от XSS как явления: внедрённый код всё равно шлёт запросы с вашего домена, и кука уходит автоматически. HttpOnly затрудняет кражу токена, а не эксплуатацию дыры.
Set-Cookie: refresh=...; HttpOnly; Secure; SameSite=Lax; Path=/api/authРабочая схема для SPA: короткоживущий access-токен держим в памяти модуля, refresh в куке с HttpOnly, Secure, узким Path и ротацией при каждом обновлении, после перезагрузки страницы делаем тихое обновление пары. Куки требуют защиты от CSRF: SameSite плюс отдельный токен на небезопасные методы, если фронт и бэк живут на разных сайтах.
Закончите тем, что выбор хранилища вторичен: без строгого CSP, экранирования вывода и запрета на вставку чужой разметки рушится любая схема.
Где спотыкаются
Утверждают, что HttpOnly закрывает XSS. Не закрывает: внедрённый скрипт делает запрос с учётными данными и действует от имени пользователя прямо в его сессии, просто не уносит токен наружу.
Ставят SameSite=None ради стороннего домена и забывают про CSRF, либо берут Strict и ломают возврат от внешнего провайдера входа и переходы по ссылкам из писем.
Предлагают шифровать токен перед записью в localStorage. Ключ лежит в том же бандле, и скрипт, читающий хранилище, прочитает и ключ; это ритуал, а не защита.