SES-018: update /auth/refresh
Техническое задание / Спецификация требований Обновить логику /auth/refresh — Обязательная проверка флага is_revoked
- Эпик: Авторизация и аутентификация (EPIC-10)
- Компонент: R Gatekeeper (Backend API), Postgres (Auth DB), Mobile App (AgroLaborApp)
- Зависимость (Pre-requisite): SES-007 (Реализация логаута и отзыва токена)
- Статус: Готово к реализации
- Ссылка на Jira: SES-008
1. Бизнес-контекст и цель (Business Context)
Для защиты пользовательских сессий в платформе “Цифровые симуляторы бизнес-процессов” от перехвата и несанкционированного обновления необходимо внедрить строгую валидацию на этапе ротации ключей. Если злоумышленник скомпрометировал refresh_token, он не должен иметь возможности сгенерировать новые токены, если сессия уже была аннулирована пользователем или системой.
Цель задачи: Обновить логику существующего эндпоинта POST /auth/refresh в микросервисе R Gatekeeper. Сервис должен принудительно проверять состояние флага is_revoked в таблице refresh_tokens базы данных Postgres перед выдачей новой пары access_token и refresh_token.
2. Пользовательские истории (User Stories)
Как Ядро службы безопасности платформы,
Я хочу проверять статус отзыва токена обновления при каждом запросе на ротацию сессии,
Чтобы украденные, утекшие или ранее закрытые через логаут токены не могли использоваться для несанкционированного доступа к системе.
3. Системные требования и бэкенд-логика (Functional Requirements)
3.1. Верификация состояния в базе данных
При поступлении запроса на обновление токенов, сервис R Gatekeeper извлекает хэш токена из защищенной куки и выполняет поиск метаданных в Postgres (Auth DB) по полю token_hash:
SELECT id, user_id, is_revoked, expires_at
FROM refresh_tokens
WHERE token_hash = $1;3.2. Конвейер бизнес-правил валидации (Validation Pipeline)
Бэкенд должен последовательно проверять запись в БД по следующему алгоритму:
[Запрос на обновление сессии]
│
▼
┌───────────────────────┐
│ Токен найден в базе? ├─► Нет ──► [401 Unauthorized]
└───────────┬───────────┘
│ Да
▼
┌───────────────────────┐
│ Просрочен expires_at? ├─► Да ──► [401 Unauthorized] (Сессия истекла)
└───────────┬───────────┘
│ Нет
▼
┌───────────────────────┐
│ is_revoked == true?├─► Да ──► [403 Forbidden] (ФИКСАЦИЯ REPLAY ATTACK!)
└───────────┬───────────┘
│ Нет (Токен валиден)
▼
[Генерация новой пары токенов]
- Правило 1 (Существование): Если запись с указанным
token_hashотсутствует в БД, возвращать ошибку401 Unauthorized. - Правило 2 (Срок действия): Если текущее системное время
NOW() > expires_at, возвращать ошибку401 Unauthorizedс сообщением об истечении сессии. - Правило 3 (Отзыв токена - Основная задача): Если поле
is_revoked == true, немедленно прервать транзакцию. Запрещено генерировать новые ключи. Запрос классифицируется как попытка повторного использования (Replay Attack). Возвращать статус403 Forbiddenсо специальным телом ответа.
4. Спецификация API (API Specification Updates)
POST /auth/refresh
Используется для ротации сессии и выдачи нового Access Token.
Пример запроса (Headers):
POST /auth/refresh HTTP/1.1
Host: ://yourcompany.com
Cookie: refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Сценарий А: Успешное обновление (Response 200 OK) Если is_revoked == false и срок действия не истек, бэкенд производит ротацию (старый токен помечается как отозванный, создается новая запись) и возвращает новый ключ доступа:
{
"success": true,
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"message": "Tokens successfully rotated."
}Сценарий Б: Токен ранее был отозван / Попытка взлома (Response 403 Forbidden) Если при поиске в БД обнаружено, что is_revoked == true:
{
"success": false,
"error": {
"code": "TOKEN_REVOKED_REPLAY_ATTACK",
"message": "The provided refresh token has been revoked. Security alert raised.",
"details": {
"reason": "Session was previously terminated or flagged as compromised",
"action_required": "FORCE_LOCAL_LOGOUT"
}
},
"timestamp": "2026-05-28T06:55:00Z"
}5. Критерии приемки и тест-кейсы для QA
Тест-кейс 1: Стандартное обновление активной сессии
- Дано: Авторизованный клиент. В БД Postgres запись токена имеет
is_revoked = falseиexpires_atв будущем. - Когда: Отправляется запрос
POST /auth/refresh. - Тогда: Ответ содержит статус
200 OK, выдается новыйaccessToken, сессия продолжается штатно.
Тест-кейс 2: Попытка атаки с использованием отозванного токена (Анализ безопасности)
- Дано: Запись токена в БД имеет статус
is_revoked = trueпосле успешного логаута в задачеSES-007. - Когда: Злоумышленник (или устаревший кэш мобильного приложения) отправляет запрос
POST /auth/refreshс этим хэшем. - Тогда:
- API возвращает строго
403 Forbidden. - Тело ответа полностью соответствует структуре ошибки
TOKEN_REVOKED_REPLAY_ATTACK. - Мобильное приложение AgroLaborApp перехватывает этот код и запускает процедуру жесткого логаута (очистка памяти и редирект на экран логина).
- API возвращает строго