В модуле 1 мы запомнили: REST — stateless. Сервер ничего не помнит между запросами. Из этого вытекает практический вывод: в каждом запросе к защищённому API нужно представляться. Сервер не помнит, что вы только что логинились — повторите.
Аналогия с фестивалем
Вы пришли на фестиваль. На входе показали паспорт и купленный билет — вам надели на руку браслет. Дальше всю неделю каждый раз, когда вы идёте на концерт, в фуд-зону или хотите выпить пива (если вам больше 18) — охранник на входе смотрит на ваш браслет. Не на паспорт. Не на билет. Только на браслет.
Браслет компактный, его легко проверить, он одинаково работает для всех сценариев — вход, бар, гримёрка. Если потеряли — вернулись на стойку охраны, прошли проверку заново, выдали новый.
Точно так же устроена авторизация в API. Логин/пароль — это паспорт. Показываете один раз. В ответ получаете токен — это браслет. Дальше в каждом запросе к серверу присылаете не пароль, а токен.
Authentication vs Authorization
Два слова, которые легко путать. На собеседовании про их разницу спрашивают регулярно.
- Authentication («аутентификация») — кто ты. Показал пароль или токен — сервер понял, что это пользователь Anna. Иногда сокращают как AuthN.
- Authorization («авторизация») — что тебе можно. Сервер понял, что вы Anna — теперь решает, можете ли вы удалять чужие посты или только свои. Сокращение AuthZ.
Хитрая ловушка: статус-код 401 называется Unauthorized, но по смыслу это «unauthenticated» («ты не представился»). А 403 — Forbidden, по смыслу «unauthorized» («представился, но не пущу»). Названия в RFC исторически перепутали — смиритесь, проверять знание этой ловушки любят.
Где сервер ждёт ваш «браслет»
Есть несколько мест, куда положить идентификатор:
- Заголовок Authorization. Самое стандартное место. Внутри — схема (Bearer, Basic, и т.д.) и значение.
- Кастомный заголовок вроде X-API-Key. Часто у простых API, где требований к безопасности меньше.
- Куки. Браузер прикрепляет их автоматически. Подходит для веб-приложений, общающихся со своим бэкендом.
- 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-потоки в рамках курса не лезем — это тема на отдельный мануал. Главное — результат тот же: мы получаем токен, дальше используем его в каждом запросе.
Логаут как удаление браслета
Когда пользователь нажимает «выйти» — происходит две вещи:
- Клиент удаляет токен у себя (из куки или localStorage).
- Клиент шлёт серверу POST /api/auth/logout, чтобы тот пометил токен как невалидный.
Без второго шага токен, если он попадёт к кому-то другому, остаётся рабочим до своего срока истечения. Это уже вопрос безопасности, а не просто «закрыть вкладку».