-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Модернизация API AuthService.UserController
Тип: feature / api-change (breaking)
Приоритет: High
Статус: Proposal
Ответственная команда: AuthService
Контекст
Текущий контроллер UserController предоставляет:
- POST /api/User — аутентификация по логину/паролю
- GET /api/User — получение информации о текущем пользователе (по токену)
Проблемы:
- Нестандартизованный ответ об ошибке (строка "Username of password incorrect" и 400 вместо 401/403), опечатка в тексте.
- Отсутствие refresh-потока для продления access-токена.
- Несогласованность кейсинга полей ответа (PascalCase вместо camelCase) с общим стилем фронтенда и OpenAPI-конвенциями.
- Нет явной схемы ответов/ошибок в OpenAPI.
- Маршрут GET лучше явно называть
/meдля ясности.
Предлагаемые изменения
- POST /api/User (Authenticate)
- На вход: { login: string, password: string }
- На успешный ответ 200:
{ "token": "<jwt>", "refreshToken": "<guid>", "userName": "<string>", "roles": ["<string>"] , "avatar": "<url | null>", "userType": "<string>", "expiryTimeStamp": "<ISO8601>" } - На ошибки аутентификации: 401 с ProblemDetails (RFC 7807)
{ "type": "https://httpstatuses.com/401", "title": "Unauthorized", "status": 401, "detail": "Invalid login or password" } - На валидационные ошибки: 422 с ProblemDetails.
- Поля ответа перевести в camelCase; добавить поле
refreshToken.
- POST /api/User/refresh (Refresh Token) — НОВЫЙ
- На вход:
{ "refreshToken": "<guid>" } - Ответ 200:
{ "token": "<jwt>", "refreshToken": "<guid>", "expiryTimeStamp": "<ISO8601>" } - Ошибки: 401 (просрочен/отозван/неизвестен refresh), 422 (невалидный формат), ProblemDetails.
- GET /api/User переименовать в GET /api/User/me (BREAKING)
- Поведение прежнее: возвращает сведения о текущем пользователе согласно токену.
- Ошибки: 401 при отсутствии/некорректном токене, ProblemDetails.
- Обновить OpenAPI-спецификацию
- Описать схемы AuthRequest, AuthResponse, RefreshRequest, RefreshResponse, ProblemDetails.
- Обновить securitySchemes (HTTP bearer JWT).
- Задокументировать коды 200/401/422 для соответствующих эндпоинтов.
Миграция (для клиентов)
- Заменить обращение к GET /api/User на GET /api/User/me.
- Перейти на чтение полей ответа в camelCase (token, userName, ...), больше не полагаться на PascalCase.
- Обрабатывать 401/422 как ошибки с телом формата ProblemDetails.
- Для продления сессии использовать POST /api/User/refresh с сохранённым refreshToken.
Техническая реализация (кратко)
- Контроллер:
- Исправить тексты и коды ошибок: 401 вместо 400 при неверных учётных данных, ProblemDetails.
- Возвращать camelCase через JsonSerializerOptions (PropertyNamingPolicy = CamelCase) или атрибуты, привести DTO к camelCase.
- Добавить экшен
POST api/User/refreshвUserControllerили отдельныйTokenController(обсудить). Реализовать генерацию/хранение refresh-токенов (in-memory/репозиторий, TTL/ревокация). - GET переназвать на
meи пометить старый маршрут как deprecated (временный период совместимости опционально).
- Домен/сервис:
- Расширить
AuthServiceметодамиIssueTokens(login),Refresh(refreshToken). - Валидация и аудит использования refresh-токенов.
- Расширить
- OpenAPI:
- Обновить
AuthService-openapi.jsonсогласно новым схемам и маршрутам.
- Обновить
OpenAPI (черновик фрагментов)
- Components
- schemas:
- AuthRequest { login: string, password: string }
- AuthResponse { token: string, refreshToken: string, userName: string, roles: string[], avatar?: string, userType: string, expiryTimeStamp: string }
- RefreshRequest { refreshToken: string }
- RefreshResponse { token: string, refreshToken: string, expiryTimeStamp: string }
- ProblemDetails { type?: string, title?: string, status?: number, detail?: string, instance?: string, errors?: object }
- securitySchemes:
- bearerAuth { type: http, scheme: bearer, bearerFormat: JWT }
- schemas:
- Paths
- POST /api/User
- 200: AuthResponse
- 401, 422: ProblemDetails
- POST /api/User/refresh
- 200: RefreshResponse
- 401, 422: ProblemDetails
- GET /api/User/me
- security: bearerAuth
- 200: User dto (как сейчас отдаёт
AgentFromLogin), 401: ProblemDetails
- POST /api/User
Совместимость и риски
- Breaking change в маршруте GET и формате кейсинга. Предложение: на один релиз оставить старый GET /api/User (deprecated) с предупреждением в ответе/логах.
- Требуется хранение и безопасная ревокация refresh-токенов.
Критерии приёмки
- Аутентификация с валидными учётными данными возвращает 200 и поля в camelCase, включая refreshToken.
- Неверные учётные данные — 401 + ProblemDetails.
- POST /api/User/refresh с валидным refreshToken возвращает новый набор токенов и обновлённый expiryTimeStamp.
- GET /api/User/me возвращает корректные данные пользователя при валидном access-токене, 401 при невалидном.
- OpenAPI отражает все маршруты/схемы и коды.
План задач
- DTO: ввести AuthResponse, RefreshRequest, RefreshResponse, ProblemDetails-мэппинг
- Контроллер: обновить POST /api/User, добавить POST /api/User/refresh, переименовать GET на /me
- Домен: методы выдачи и обновления токенов, хранилище refresh-токенов
- Обновить AuthService-openapi.json
- Логи/метрики: аудит логинов и refresh-операций
- Миграционная заметка для интеграторов
Дополнительно
- Рассмотреть ограничение частоты попыток логина (rate limit) и капчу.
- Рассмотреть сквозной correlationId в ответах ошибок (ProblemDetails.extensions).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels