← назад к разделу

Вы проверяете личный кабинет: под своей учётной записью чужих заказов не видно. Копируете адрес страницы заказа, открываете в другом браузере под другим покупателем — и видите тот же заказ целиком, с адресом доставки и телефоном. Интерфейс ни при чём: данные отдал сервер, не спросив, кому они принадлежат.

Такие находки живут сразу за формой входа: чтобы их видеть, надо понимать, чем сервер вас опознал, что выдал взамен и что проверяет дальше.

вход выдаёт пропуск — дальше сервер судит по нему, а не по тому, что видно на экране POST /loginпочта + парольсерверсверил пароль200 OKтокен доступа + refresh GET /orders/17 + Bearer eyJ…200свой заказ — сервер отдал GET /orders/17 без заголовка401ты не представился GET /orders/99 + чужой Bearer403заказ не твой — отказ GET /orders/17 + срок вышел401exp в прошлом POST /refresh + refresh-токен200новая пара, молча

Вход меняет пароль на токен, и дальше каждый запрос сервер судит по заголовку, а не по экрану: свой токен открывает свой заказ, отсутствующий даёт 401, чужой — 403 на чужом ресурсе, истёкший — снова 401, после чего клиент молча меняет его по refresh-токену. Кнопок в этой цепочке нет ни одной — значит, и проверять её кнопками нельзя.

Три слова, которые постоянно путают

«Авторизацией» называют и форму входа, и права доступа, а потом дефект описан так, что непонятно, что чинить. Разведём их на покупателе магазина.

Идентификация — вы назвались: Анна вводит почту anna@example.com. Доказательства пока нет, только заявка; так же работает логин или номер карты. Аутентификация — вы доказали: Анна вводит пароль, сервер сверяет его и верит. Доказательством бывает и код из сообщения, и отпечаток — два разного рода и есть двухфакторная проверка. Авторизация — что этому человеку положено: Анна открывает «Все заказы магазина» и получает отказ, потому что она покупатель, а не сотрудник.

Разницу видно по ответу: 401 — «не понял, кто ты» (токена нет, истёк, подделан), 403 — «понял, но нельзя». Опознают один раз, на входе, а права проверяют на каждом запросе.

Как выглядит вход изнутри

На экране вход — два поля и кнопка, в обмене — один запрос: POST /login, в теле почта и пароль. Сервер сверяет пароль (в базе лежит не он, а его необратимый отпечаток) и выдаёт пропуск: куку заголовком Set-Cookie либо токен в теле JSON.

Смотрят это во вкладке «Сеть», открыв её до нажатия «Войти»: статус /login, что пришло в ответе и чем клиент представляется дальше — куку браузер подставляет сам, заголовок Authorization ставит код страницы.

Сессия и токен: кто помнит, что вы вошли

HTTP ничего не помнит: каждый запрос сам по себе, и введённый минуту назад пароль сервер не учитывает. Доказательство приносят с собой каждый раз, и способа два.

Сессия — сервер заводит запись у себя: кто вошёл, когда, до какого срока. Клиенту достаётся её номер — случайная строка в куке, которую браузер прикладывает к каждому запросу сам. Содержимое лежит на сервере, поэтому сессию гасят мгновенно: запись удалили — номерок стал пустышкой.

Токен — наоборот: сервер ничего не хранит, а выдаёт подписанную строку, где написано, кто это; клиент кладёт её в заголовок Authorization: Bearer <токен>. Bearer значит «предъявитель»: кто принёс, тот и владелец. Живёт токен до своего срока сам по себе, отозвать его так просто нельзя — поэтому выход проверяют отдельно.

JWT: три части через точку

Токен в ответе выглядит как eyJhbGciOi….eyJzdWIiOi….SflKxwRJf: две точки делят его на три части — чем подписано, что утверждается и сама подпись. В середине идентификатор пользователя, кто выдал токен, роли и обязательно exp — момент, после которого токен недействителен, обычно считанные минуты.

Главное: подпись — не шифрование. Первые две части не зашифрованы, а перекодированы, и читает их кто угодно: вставьте токен из вкладки «Сеть» на jwt.io — увидите содержимое целиком. Подпись защищает от подделки: поправьте роль покупателя на администратора — она перестанет сходиться, и сервер ответит 401.

Отсюда две проверки: личных данных вроде телефона и номера карты внутри быть не должно (токен оседает в журналах), а правка середины обязана давать отказ, а не права.

Refresh-токен: почему вас не выкидывает каждые пять минут

Будь короткий токен единственным, человек вводил бы пароль десяток раз за час. Поэтому на входе выдают пару: токен доступа на минуты и refresh-токен на часы или дни. Истёк доступ — клиент сам отправляет refresh на сервер входа и получает свежую пару, а пользователь не замечает ничего.

Частая находка живёт здесь: «Выйти» чистит хранилище браузера, но серверу не сообщает ничего, и токен, скопированный до выхода, по-прежнему открывает кабинет.

Вход через Яндекс: кто кому доверяет

Кнопка «Войти через Яндекс» решает отдельную задачу: магазин не должен знать ваш пароль от Яндекса. Такой обмен называется OAuth — вместо пароля магазин получает токен с ограниченными правами.

Браузер уходит на домен Яндекса — адрес в строке меняется, и это ключевая деталь: пароль вводится только у того, кому принадлежит. Яндекс спрашивает, что разрешить магазину, и возвращает вас с временным кодом в адресе; код магазин меняет на токен сам. Во вкладке «Сеть» видна вся цепочка: уход на чужой домен, возврат с code, дальше запросы с токеном.

Что проверять

  • Чужой ресурс по прямой ссылке. Открыть заказ под Анной, адрес открыть под Борисом: ответ — отказ, а не чужие данные.
  • Без токена и с чужим токеном. Тот же запрос в Postman без заголовка — 401; с токеном другого покупателя — 403.
  • Истёкший токен. Дождаться истечения или укоротить срок на стенде: ждём 401 и тихое обновление по refresh, а не выброс на форму входа.
  • Выход. Сохранённый запрос со старым токеном не работает, refresh тоже; «Назад» не показывает кабинет из кеша.
  • Смена пароля и старая сессия. Войти в двух браузерах, сменить пароль в первом: закроется ли вторая сессия — вопрос к требованиям, и задать его нужно.
  • Кнопка скрыта, а запрос проходит. Интерфейс прячет «Удалить» у покупателя — отправьте DELETE руками: сервер обязан отказать.
  • Вход через Яндекс. Отказ на экране согласия ведёт на понятную страницу, а не на белый экран; вход паролем и через Яндекс с одной почтой — один кабинет.

Где спотыкаются

  • Проверяют только через интерфейс. Кнопки нет — значит, не проверено: дыры находят прямым запросом.
  • Тестируют на боевых учётках. Сменить пароль живому покупателю ради проверки сессии — происшествие; нужны две тестовые учётки с разными правами.
  • Не замечают токен в адресной строке. ?token=… уезжает в историю браузера, в журналы сервера и в пересланную ссылку — дефект, даже когда «всё работает».
  • Считают 401 и 403 одним и тем же. Перепутанный код в баг-репорте уводит не туда: чинить будут опознание вместо прав.

Коротко

  • Идентификация — назвался, аутентификация — доказал, авторизация — что положено; первые две на входе, третья на каждом запросе.
  • 401 — «не понял, кто ты», 403 — «понял, но нельзя»: разные дефекты и разные места починки.
  • Сессия лежит на сервере и гасится мгновенно, токен — у клиента и живёт до своего срока; отсюда отдельная проверка выхода.
  • Подпись JWT не шифрует: середину читает кто угодно, личных данных там быть не должно, а правка середины обязана давать 401.
  • После выхода перестают работать оба токена, а не только тот, что в браузере.
  • Права проверяются на сервере: скрытая кнопка не защита.

Что почитать дальше