Вы проверяете личный кабинет: под своей учётной записью чужих заказов не видно. Копируете адрес страницы заказа, открываете в другом браузере под другим покупателем — и видите тот же заказ целиком, с адресом доставки и телефоном. Интерфейс ни при чём: данные отдал сервер, не спросив, кому они принадлежат.
Такие находки живут сразу за формой входа: чтобы их видеть, надо понимать, чем сервер вас опознал, что выдал взамен и что проверяет дальше.
Вход меняет пароль на токен, и дальше каждый запрос сервер судит по заголовку, а не по экрану: свой токен открывает свой заказ, отсутствующий даёт 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.
- После выхода перестают работать оба токена, а не только тот, что в браузере.
- Права проверяются на сервере: скрытая кнопка не защита.
Что почитать дальше
- Клиент-сервер и HTTP — откуда берутся заголовки и статус-коды.
- DevTools браузера — где смотреть запрос входа, куки и заголовок
Authorization. - API-тестирование в Postman — как повторить запрос без токена, с чужим и истёкшим.
- Нефункциональные виды тестирования — что ещё входит в проверку безопасности.