Lesson 20 of 26
Урок 20 — Авторизация и Аутентификация
Название: Authentication vs Authorization — кто ты и что тебе можно
Описание: Разбираем два фундаментальных понятия безопасности: аутентификацию (кто ты?) и авторизацию (что тебе разрешено?). Изучаем JWT, OAuth, сессии и как всё это тестировать.
Почему это важно для QA: Ошибки в аутентификации и авторизации — одни из наиболее критичных уязвимостей. Тестировщик, который не умеет их проверять, пропустит баги с потенциально катастрофическими последствиями.
1. Ключевые определения
Аутентификация (Authentication / AuthN)
«Кто ты?» — процесс проверки личности пользователя.
Пользователь утверждает: «Я Иван Петров»
Система проверяет: «Докажи» → пароль, биометрия, SMS-код
Результат: «Да, ты действительно Иван Петров»Авторизация (Authorization / AuthZ)
«Что тебе разрешено?» — процесс определения прав доступа после подтверждения личности.
Система знает: «Ты — Иван Петров, роль = Manager»
Запрос: «Хочу удалить пользователя»
Система проверяет: «У Manager нет права удалять пользователей»
Результат: 403 ForbiddenАналогия
Аутентификация = пропуск на работу (доказывает, кто ты)
Авторизация = уровень доступа (в какие кабинеты тебя пустят)
Ты показываешь пропуск охраннику → прошёл аутентификацию
Пытаешься войти в серверную → нет доступа → не авторизован2. Разница в одной таблице
| Критерий | Аутентификация | Авторизация |
|---|---|---|
| Вопрос | «Кто ты?» | «Что тебе можно?» |
| Когда | Первым | После аутентификации |
| Проверяет | Личность | Права доступа |
| Ошибка при провале | 401 Unauthorized | 403 Forbidden |
| Примеры | Логин/пароль, JWT, OAuth | Роли, разрешения, ACL |
3. Методы аутентификации
3.1 Логин и пароль (Basic Auth)
Классический способ. Пользователь вводит Email + Password, сервер проверяет в БД.
Проблема: пароли нужно хранить безопасно (bcrypt, Argon2, scrypt)
Никогда: не хранить пароли в открытом виде или MD53.2 Session-based Authentication
1. Пользователь входит с логином/паролем
2. Сервер создаёт запись в БД: sessions { id: "abc123", userId: 42, expiresAt: ... }
3. Сервер отправляет Cookie: sessionId=abc123
4. При каждом запросе браузер отправляет Cookie
5. Сервер ищет сессию в БД и получает данные пользователяПлюсы: можно немедленно инвалидировать сессию (выход из аккаунта)
Минусы: нужно хранить сессии на сервере (не подходит для масштабирования)
3.3 JWT (JSON Web Token)
Токен, содержащий информацию о пользователе, подписанный сервером.
Структура JWT: header.payload.signature
Пример:
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3MjAzNDU2Nzh9.xxxxx
Декодированный payload:
{
"userId": 42,
"role": "admin",
"exp": 1720345678 ← время истечения (Unix timestamp)
}Плюсы: не нужно хранить на сервере, хорошо масштабируется
Минусы: нельзя отозвать до истечения (если не использовать блэклист)
Как работает JWT:
1. Пользователь входит → сервер создаёт JWT и подписывает секретным ключом
2. JWT отправляется клиенту (в Cookie или LocalStorage)
3. Клиент отправляет JWT в заголовке: Authorization: Bearer <token>
4. Сервер проверяет подпись → доверяет данным в payload3.4 OAuth 2.0 / OpenID Connect
Позволяет авторизоваться через сторонние сервисы (Google, GitHub, Facebook).
Сценарий: «Войти через Google»
1. Пользователь нажимает «Войти через Google»
2. Редирект на Google (accounts.google.com/oauth/...)
3. Пользователь разрешает доступ
4. Google редиректит обратно с кодом: /callback?code=xyz
5. Сервер меняет code на access_token у Google
6. Сервер получает данные пользователя у Google
7. Создаёт сессию / JWT для пользователя3.5 Multi-Factor Authentication (MFA)
Добавляет второй фактор к паролю:
Фактор 1 (знание): пароль
Фактор 2 (владение): SMS-код, TOTP (Google Authenticator), hardware key
Фактор 3 (биометрия): отпечаток пальца, распознавание лица4. Модели авторизации
4.1 RBAC (Role-Based Access Control)
Самая распространённая модель. Права привязаны к роли.
Роли:
├── Guest → может читать публичный контент
├── User → может редактировать свой профиль, создавать заказы
├── Manager → может управлять заказами, видеть аналитику
└── Admin → полный доступ ко всему
Пользователь получает роль → наследует все права роли4.2 ABAC (Attribute-Based Access Control)
Права зависят от атрибутов пользователя, ресурса и контекста.
Правило: Пользователь может редактировать документ,
ЕСЛИ document.authorId == user.id
И user.department == document.department
И currentTime < document.deadline4.3 ACL (Access Control List)
Список разрешений на конкретный ресурс.
Файл /reports/q1-2026.pdf:
├── User #42 → READ
├── User #43 → READ, WRITE
└── Role "Admin" → READ, WRITE, DELETE5. Как тестировать аутентификацию
5.1 Позитивные тесты (happy path)
TC-01: Вход с корректными логином и паролем
TC-02: Вход с помощью Google OAuth
TC-03: Вход с MFA (корректный TOTP)
TC-04: «Запомнить меня» — сессия сохраняется после перезапуска браузера
TC-05: Выход — сессия завершается, Cookie удаляется5.2 Негативные тесты
TC-06: Неверный пароль → 401, ошибка «Неверный логин или пароль»
TC-07: Несуществующий email → 401 (НЕ «Пользователь не найден» — это утечка данных!)
TC-08: Пустые поля → ошибка валидации
TC-09: Блокировка после N неудачных попыток (brute-force protection)
TC-10: Истёкший JWT → 401, требует повторной авторизации
TC-11: Невалидный JWT (изменена подпись) → 401
TC-12: MFA с неверным кодом → 401
TC-13: Повторное использование ссылки «Сброс пароля» → 410 Gone или ошибка6. Как тестировать авторизацию
6.1 Тест ролевой модели
Матрица доступа для теста:
Действие | Guest | User | Manager | Admin
──────────────────────┼───────┼──────┼─────────┼──────
Просмотр каталога | ✓ | ✓ | ✓ | ✓
Создание заказа | ✗ | ✓ | ✓ | ✓
Отмена своего заказа | ✗ | ✓ | ✓ | ✓
Отмена чужого заказа | ✗ | ✗ | ✓ | ✓
Управление товарами | ✗ | ✗ | ✓ | ✓
Управление пользоват. | ✗ | ✗ | ✗ | ✓6.2 Тест горизонтального доступа (IDOR)
Insecure Direct Object Reference — самый частый тип уязвимости авторизации.
Пользователь #42 делает запрос:
GET /api/orders/1001 ← заказ #1001 принадлежит пользователю #42 → OK
Что если поменять ID?
GET /api/orders/1002 ← заказ #1002 принадлежит пользователю #99
Ожидаем: 403 Forbidden
Баг (IDOR): 200 OK + данные чужого заказаЭто критический баг! Всегда проверяй!
6.3 Тест вертикального доступа
Пользователь с ролью User пытается:
DELETE /api/admin/users/99
Ожидаем: 403 Forbidden
Баг: 200 OK (User может удалять пользователей как Admin)7. Пример тестов в Playwright
import { test, expect } from "@playwright/test";
import { LoginPage } from "../pages/LoginPage";
import { ApiClient } from "../utils/ApiClient";
const USERS = {
regular: { email: "user@test.com", password: "TestPass123", role: "user" },
admin: { email: "admin@test.com", password: "AdminPass123", role: "admin" },
} as const;
test.describe("Авторизация — IDOR тест", () => {
test("пользователь не видит заказ другого пользователя", async ({ request }) => {
const userApi = new ApiClient(request);
await userApi.login(USERS.regular.email, USERS.regular.password);
// Получаем ID заказа другого пользователя (Admin)
const adminApi = new ApiClient(request);
await adminApi.login(USERS.admin.email, USERS.admin.password);
const adminOrders = await adminApi.get("/api/orders");
const otherUserOrderId = adminOrders.body[0].id;
// Пробуем получить чужой заказ от имени обычного пользователя
const response = await userApi.get(`/api/orders/${otherUserOrderId}`);
expect(
response.status,
"Пользователь не должен видеть чужие заказы (IDOR)"
).toBe(403);
});
});
test.describe("Авторизация — вертикальный доступ", () => {
test("обычный пользователь не может вызвать admin API", async ({ request }) => {
const userApi = new ApiClient(request);
await userApi.login(USERS.regular.email, USERS.regular.password);
const response = await userApi.delete("/api/admin/users/99");
expect(
response.status,
"Обычный пользователь не может вызывать Admin API"
).toBe(403);
});
});
8. Распространённые уязвимости (OWASP Top 10)
| Уязвимость | Описание | Как тестировать |
|---|---|---|
| Broken Authentication | Слабые пароли, нет блокировки brute-force | Попробовать 100 неверных паролей |
| Broken Authorization | IDOR, доступ к чужим данным | Подменить userId в URL/запросе |
| Sensitive Data Exposure | Пароли в открытом виде в URL | Проверить URL и логи |
| JWT Vulnerabilities | Алгоритм «none», слабый секрет | Декодировать и изменить JWT |
| Session Fixation | Сессия не меняется после входа | Проверить sessionId до и после входа |
9. Частые ошибки при тестировании
❌ Тестируют только happy path
→ Всегда проверяй IDOR — это один из самых критичных и частых багов.
❌ Не проверяют сообщения об ошибках
→ «Пользователь с таким email не существует» — это утечка данных! Должно быть: «Неверный логин или пароль».
❌ Забывают тестировать после смены роли
→ Пользователь получил Admin → потом Admin отозвали → старый JWT всё ещё работает?
Итог
АУТЕНТИФИКАЦИЯ (AuthN) = «Кто ты?»
├── Методы: пароль, JWT, OAuth, MFA
├── Ошибка: 401 Unauthorized
└── Тестируем: вход, выход, неверные данные, истёкший токен
АВТОРИЗАЦИЯ (AuthZ) = «Что тебе можно?»
├── Модели: RBAC, ABAC, ACL
├── Ошибка: 403 Forbidden
└── Тестируем: ролевую матрицу, IDOR, вертикальный доступ
КЛЮЧЕВОЕ ПРАВИЛО: сначала аутентификация, потом авторизация
САМЫЙ ОПАСНЫЙ БАГ: IDOR — пользователь видит данные другого