В модуле 1 мы запомнили: REST — stateless. Сервер ничего не помнит между запросами. Из этого вытекает практический вывод: в каждом запросе к защищённому API нужно представляться. Сервер не помнит, что вы только что логинились — повторите.

Аналогия с фестивалем

Вы пришли на фестиваль. На входе показали паспорт и купленный билет — вам надели на руку браслет. Дальше всю неделю каждый раз, когда вы идёте на концерт, в фуд-зону или хотите выпить пива (если вам больше 18) — охранник на входе смотрит на ваш браслет. Не на паспорт. Не на билет. Только на браслет.

Браслет компактный, его легко проверить, он одинаково работает для всех сценариев — вход, бар, гримёрка. Если потеряли — вернулись на стойку охраны, прошли проверку заново, выдали новый.

Точно так же устроена авторизация в API. Логин/пароль — это паспорт. Показываете один раз. В ответ получаете токен — это браслет. Дальше в каждом запросе к серверу присылаете не пароль, а токен.

Authentication vs Authorization

Два слова, которые легко путать. На собеседовании про их разницу спрашивают регулярно.

  • Authentication («аутентификация») — кто ты. Показал пароль или токен — сервер понял, что это пользователь Anna. Иногда сокращают как AuthN.
  • Authorization («авторизация») — что тебе можно. Сервер понял, что вы Anna — теперь решает, можете ли вы удалять чужие посты или только свои. Сокращение AuthZ.

Хитрая ловушка: статус-код 401 называется Unauthorized, но по смыслу это «unauthenticated» («ты не представился»). А 403 — Forbidden, по смыслу «unauthorized» («представился, но не пущу»). Названия в RFC исторически перепутали — смиритесь, проверять знание этой ловушки любят.

Где сервер ждёт ваш «браслет»

Есть несколько мест, куда положить идентификатор:

  1. Заголовок Authorization. Самое стандартное место. Внутри — схема (Bearer, Basic, и т.д.) и значение.
  2. Кастомный заголовок вроде X-API-Key. Часто у простых API, где требований к безопасности меньше.
  3. Куки. Браузер прикрепляет их автоматически. Подходит для веб-приложений, общающихся со своим бэкендом.
  4. Query-параметр вроде ?api_key=.... Антипаттерн. URL попадает в логи, историю браузера, заголовок Referer. Используется в редких случаях типа подписанных URL для скачивания файла; для обычных API — нет.

В REST API почти всегда речь идёт о первых трёх. Их и разберём в следующих главах: API key (7.2), Bearer-токены и JWT (7.3), куки vs токены (7.4).

Как добывают «браслет» в первый раз

В жизни приложения есть один особый момент — первая выдача токена. Чаще всего это форма логина:

POST /api/auth/login
Content-Type: application/json

{"email": "anna@example.com", "password": "secret123"}

→ HTTP/1.1 200 OK
  {
    "access_token": "eyJhbGciOi...",
    "refresh_token": "fF8a2d...",
    "expires_in": 3600
  }

На этом этапе мы единственный раз светим пароль. Дальше работаем с access_token. Когда срок токена кончается — меняем его на новый через refresh_token (об этом подробнее в 7.3).

Другой вариант — OAuth-вход (через Google, GitHub, Apple). Там процесс хитрее: пользователь редиректится на сторонний сервис, логинится там, тот возвращает нас обратно с кодом, который мы меняем на токен. Подробно про OAuth-потоки в рамках курса не лезем — это тема на отдельный мануал. Главное — результат тот же: мы получаем токен, дальше используем его в каждом запросе.

Логаут как удаление браслета

Когда пользователь нажимает «выйти» — происходит две вещи:

  1. Клиент удаляет токен у себя (из куки или localStorage).
  2. Клиент шлёт серверу POST /api/auth/logout, чтобы тот пометил токен как невалидный.

Без второго шага токен, если он попадёт к кому-то другому, остаётся рабочим до своего срока истечения. Это уже вопрос безопасности, а не просто «закрыть вкладку».