Почему не стоит хранить токены в sessionStorage
Что проверяют
Есть ли у вас модель угроз, а не набор заученных правил. Смотрят, понимаете ли вы, от чего именно защищает каждый способ хранения, и не считаете ли sessionStorage безопаснее просто потому, что он живёт меньше.
Как отвечать
Начните с главного: всё, до чего дотягивается JavaScript страницы, дотягивается и до чужого скрипта на ней. sessionStorage читается одной строкой, поэтому любая XSS, скомпрометированная зависимость или сторонний виджет уносят токен на чужой домен. Угнанный токен работает до истечения срока, отозвать его обычно нечем, и в логах это выглядит как обычный вход.
Отдельно проговорите, что по безопасности разницы с localStorage нет. Привязка ко вкладке это ограничение удобства, а не защита: атакующий читает хранилище в тот момент, когда его код уже выполняется.
Как надо: долгоживущий токен обновления в куке с флагами HttpOnly, Secure, SameSite и путём, суженным до эндпоинта обновления. Короткий токен доступа держат в памяти модуля, а после перезагрузки страницы получают заново по куке. Тогда XSS может действовать, пока страница открыта, но не заберёт учётные данные с собой.
Добавьте оговорку про CSRF: кука прикрепляется браузером автоматически, поэтому для небезопасных методов нужны SameSite и отдельный токен или заголовок, который кросс-доменная форма проставить не может. И скажите, что хранилище это последний рубеж: основная защита это политика Content-Security-Policy, экранирование вывода и контроль зависимостей.
Где спотыкаются
Отвечают, что sessionStorage безопаснее, ведь он очищается при закрытии вкладки. Срок жизни не мешает краже, он лишь сокращает окно, в которое её удобно повторить.
Считают HttpOnly серебряной пулей. Флаг мешает утечке значения, но не мешает скрипту на странице выполнять запросы от лица пользователя: перевод денег уйдёт и без чтения токена.
Упираются в перезагрузку страницы и возвращают токен в хранилище «на время». Правильный выход это тихое обновление по куке, а не компромисс, который отменяет всю схему целиком.