## Документация по аутентификации (Frontend) ### Обзор JWT-аутентификация. Публичные и админские эндпоинты: - POST `/api/auth/signin` — вход и выдача JWT + refreshToken - POST `/api/auth/refresh` — обновление пары токенов (ротация) - POST `/api/auth/logout` — выход (инвалидация refreshToken) - POST `/api/admin/users` — создать пользователя (только `ROLE_ADMIN`) Все запросы и ответы — JSON (`Content-Type: application/json`). ### Базовый URL - Прод: укажите боевой домен/порт - Dev локально: `http://localhost:8080` ### Переменные окружения (frontend) - REACT_APP_API_URL или NEXT_PUBLIC_API_URL: базовый URL API - Храните токен безопасно (HttpOnly cookie предпочтительно; если localStorage — учитывайте XSS риски) ## Создание пользователя (Admin) ### POST /api/admin/users Требует: `Authorization: Bearer ` и роль `ROLE_ADMIN`. Запрос: ```json { "email": "user@example.com", "password": "StrongPass123!" } ``` Успех: - 200 OK, пустой ответ Ошибки: - 400 Bad Request — невалидный email/пароль - 401/403 — нет прав администратора - 409 Conflict — email уже зарегистрирован Пример (fetch): ```js await fetch(`${API_URL}/api/admin/users`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${adminAccessToken}`, }, body: JSON.stringify({ email, password }), }); ``` ## Вход ### POST /api/auth/signin Запрос: ```json { "email": "user@example.com", "password": "StrongPass123!" } ``` Успех: - 200 OK ```json { "accessToken": "", "tokenType": "Bearer", "refreshToken": "" } ``` Ошибки: - 400/401 — неверные учетные данные Пример (fetch): ```js const res = await fetch(`${API_URL}/api/auth/signin`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }), }); const { accessToken, refreshToken } = await res.json(); // Сохраните токен и используйте в Authorization заголовке ``` ## Обновление токена (Refresh Token) ### Общая схема - При успешном входе фронт получает пару токенов: `accessToken` (короткоживущий) и `refreshToken` (длинноживущий). - `accessToken` используется в `Authorization: Bearer `. - Когда `accessToken` истекает (HTTP 401), фронт вызывает `/api/auth/refresh` с `refreshToken`, получает новую пару токенов (ротация) и повторяет запрос. ### Рекомендации по хранению - `refreshToken` предпочтительно хранить в HttpOnly Secure SameSite cookie (сервер ставит Set-Cookie). - Альтернатива (менее безопасная): хранить в памяти/secure storage и передавать в теле запроса. ### POST /api/auth/refresh Запрос (вариант с телом): ```json { "refreshToken": "" } ``` Успех: - 200 OK ```json { "accessToken": "", "tokenType": "Bearer", "refreshToken": "" } ``` Ошибки: - 400 — отсутствует/некорректный refreshToken - 401 — просрочен/отозван/невалиден Пример (fetch, с телом): ```js const res = await fetch(`${API_URL}/api/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken }), }); if (!res.ok) throw new Error('Refresh failed'); const { accessToken: newAccess, refreshToken: newRefresh } = await res.json(); ``` Пример (cookie-стратегия): ```js const res = await fetch(`${API_URL}/api/auth/refresh`, { method: 'POST', credentials: 'include', }); const { accessToken } = await res.json(); ``` ### Ротация refreshToken - При каждом refresh возвращайте новый `refreshToken` и инвалидируйте старый. - На фронте заменяйте сохранённый refreshToken на новый. ### TTL (рекомендации) - accessToken: 5–15 минут - refreshToken: 7–30 дней ## Logout - Если refreshToken хранится в cookie: `POST /api/auth/logout` — сервер чистит cookie и отмечает refreshToken как отозванный. - Если в хранилище фронта — удалите локальные токены и по возможности вызовите `logout` для аннулирования на бэке. ## Авторизация последующих запросов Передавайте JWT в заголовке: ``` Authorization: Bearer ``` Пример защищенного вызова: ```js await fetch(`${API_URL}/api/private/profile`, { headers: { Authorization: `Bearer ${token}` }, }); ``` ## Формат ошибок (пример) ```json { "timestamp": "2025-09-11T12:34:56Z", "status": 409, "error": "Conflict", "message": "Email already registered", "path": "/api/auth/signup" } ``` ## Валидация на фронте - Email: RFC-проверка и нормализация в lowercase - Пароль: минимум 8 символов, цифра, буква, спецсимвол - Обработайте статусы 400/401/409 и показывайте человекочитаемые сообщения ## Хранение токена - Предпочтительно: HttpOnly Secure cookie, получаемое от бэкенда - Альтернатива: `localStorage`/`sessionStorage` (учтите XSS; не вставляйте токен в DOM) ## Примеры cURL Создание пользователя (admin): ```bash curl -X POST "$API_URL/api/admin/users" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"email":"user@example.com","password":"StrongPass123!"}' ``` Вход: ```bash curl -X POST "$API_URL/api/auth/signin" \ -H "Content-Type: application/json" \ -d '{"email":"user@example.com","password":"StrongPass123!"}' ``` ## Заметки по безопасности - Не логируйте пароли и JWT - Реализуйте logout (инвалидация на клиенте или список отозванных токенов на бэке, если нужно) - Рекомендуется троттлинг/капча для /signin и создания пользователя ## Изменения в будущем - Ротация refresh-токенов реализована; можно добавить список отозванных токенов - Подтверждение email - Сброс пароля через почту