Аутентифицированный пользователь без требуемого разрешения получает успешный ответ на защищённую операцию. Какой интеграционный контракт должен выявить этот дефект?
Интеграционный тест должен проверять не только наличие аутентификации, но и авторизацию: пользователь с действительными учётными данными, однако без нужного разрешения, не должен успешно выполнять защищённую операцию. Контракт должен явно фиксировать ожидаемый отказ, обычно 403 Forbidden, если сервер подтверждает личность пользователя, но запрещает действие.
Разделение аутентификации и авторизации появилось из практической необходимости применять принцип наименьших привилегий. Наличие действительного токена доказывает, кто выполняет запрос, но само по себе не означает право читать, изменять или удалять конкретный ресурс.
Проверка только сценария «без токена запрос отклонён» защищает лишь границу аутентификации. Она не выявляет ошибку в проверке ролей, разрешений, областей действия токена или принадлежности ресурса.
Предположим, API разрешает изменять платёжные документы только пользователям с разрешением payments:write. Тест использует администратора или другой привилегированный аккаунт, поэтому операция проходит даже при ошибке в авторизационной логике.
Такой дефект может привести к несанкционированному изменению данных. Особенно опасны случаи, когда проверка разрешения выполняется только в пользовательском интерфейсе, но отсутствует на сервере, либо применяется к одному маршруту и забывается для другого.
Интеграционный тест должен создать или выбрать пользователя с валидной аутентификацией и заведомо недостаточным набором разрешений. Затем он выполняет защищённую операцию и проверяет одновременно:
Для аутентифицированного, но неуполномоченного пользователя ожидается 403 Forbidden. Ответ 401 Unauthorized обычно означает отсутствие корректной аутентификации или невозможность подтвердить личность; смешивать эти случаи в тесте нельзя.
Проверка должна выполняться через тот же внешний интерфейс, которым пользуется реальный клиент, а не прямой записью разрешений в внутреннее состояние после начала сценария. При этом подготовка данных может использовать административный API или отдельный механизм создания тестовой учётной записи, если это не подменяет проверяемую авторизационную границу.
Есть важное ограничение: некоторые системы намеренно возвращают 404 Not Found, чтобы не раскрывать существование ресурса пользователю без доступа. Тогда контракт должен закреплять именно такую политику, а тест дополнительно проверяет отсутствие утечки факта существования ресурса. Нельзя безоговорочно требовать 403, если модель безопасности API предусматривает сокрытие ресурсов.
В API управления договорами оператор мог просматривать договоры, но не имел права их удалять. Существующий интеграционный тест проверял удаление только от имени администратора и успешно проходил, хотя сервер фактически проверял лишь наличие валидного токена.
Рассматривались два варианта. Проверять разрешения только модульным тестом было быстро, но такой тест не охватывал конфигурацию маршрутов, middleware и преобразование удостоверения пользователя. Проверять сценарий через UI было ближе к пользовательскому пути, но такой тест был медленным и скрывал точную причину ошибки.
Выбрали интеграционный сценарий с отдельным оператором без разрешения удаления. Тест подтвердил отказ, неизменность договора и отсутствие события удаления. После исправления серверной проверки этот сценарий стал регрессионной защитой для всех маршрутов удаления.
Нет. Статус подтверждает решение на границе HTTP, но не доказывает отсутствие побочного эффекта. Ошибка может возникнуть после изменения базы данных, но до формирования ответа. Поэтому для изменяющих операций нужно проверять состояние ресурса и значимые внешние эффекты.
Такой пользователь может иметь другое разрешение, принадлежать другой организации или попасть под особое правило доступа. Надёжнее минимально описывать его полномочия и проверять именно нужную комбинацию: аутентификация действительна, целевое разрешение отсутствует, остальные условия сценария контролируемы.
Нужно создать ресурс от имени одного пользователя, а операцию выполнить от имени другого пользователя с тем же типом аутентификации, но без права на этот ресурс. Тест должен проверять не только отказ, но и то, что пользователь не может изменить или прочитать чужие данные через подстановку идентификатора ресурса. Если API скрывает существование чужих ресурсов, ожидаемый ответ должен соответствовать зафиксированному контракту, например 404 вместо 403.