Ответ вслух Middle Код-ревью спрашивают часто обновлено

Ревью: хранение токена

Вопрос

Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.

Читай вслух, как на ревью: сначала что делает код, потом что сломано.

const api = {
  login: async (email, password) => {
    const res = await fetch('/api/login', { method: 'POST', body: JSON.stringify({ email, password }) });
    const { token } = await res.json();
    localStorage.setItem('token', token);
    return token;
  },
  get: (url) =>
    fetch(url, { headers: { Authorization: 'Bearer ' + localStorage.getItem('token') } }),
};

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Главный пункт - хранение. Токен в localStorage читается любым скриптом на странице: одна XSS-дыра, одна скомпрометированная зависимость - и сессия угнана.

Что должно прозвучать в ответе

  • токен в localStorage доступен любому скрипту - при XSS угоняется целиком

  • безопаснее httpOnly-cookie с SameSite

  • нет обработки истечения токена и обновления по refresh

  • нет проверки res.ok при логине

  • localStorage читается синхронно на каждый запрос

  • нет выхода: токен не удаляется и не отзывается на сервере

Что могут спросить следом

  • А если бэкенд умеет только Bearer-токены?
  • Чем SameSite защищает от CSRF?

Разбор

Главный пункт - хранение. Токен в localStorage читается любым скриптом на странице: одна XSS-дыра, одна скомпрометированная зависимость - и сессия угнана. Безопаснее держать сессию в httpOnly-cookie с SameSite=Lax и Secure: JS её не видит.

Если архитектура требует именно токен в заголовке, то короткоживущий токен доступа - в памяти (не в хранилище), а refresh - в httpOnly-cookie.

Истечение не обработано. При 401 нет ни обновления токена, ни перевода на страницу входа - пользователь получит молчаливые пустые экраны. Нужен единый перехватчик ответов.

Нет проверки res.ok при логине: при неверном пароле token будет undefined, и в localStorage ляжет строка "undefined", с которой всё формально работает.

Нет выхода: при логауте токен должен удаляться и отзываться на сервере - иначе он остаётся действительным.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.