7.2 KiB
7.2 KiB
Документация по аутентификации (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 <admin_access_token> и роль ROLE_ADMIN.
Запрос:
{
"email": "user@example.com",
"password": "StrongPass123!"
}
Успех:
- 200 OK, пустой ответ
Ошибки:
- 400 Bad Request — невалидный email/пароль
- 401/403 — нет прав администратора
- 409 Conflict — email уже зарегистрирован
Пример (fetch):
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
Запрос:
{
"email": "user@example.com",
"password": "StrongPass123!"
}
Успех:
- 200 OK
{
"accessToken": "<JWT>",
"tokenType": "Bearer",
"refreshToken": "<refresh-token>"
}
Ошибки:
- 400/401 — неверные учетные данные
Пример (fetch):
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 <JWT>.- Когда
accessTokenистекает (HTTP 401), фронт вызывает/api/auth/refreshсrefreshToken, получает новую пару токенов (ротация) и повторяет запрос.
Рекомендации по хранению
refreshTokenпредпочтительно хранить в HttpOnly Secure SameSite cookie (сервер ставит Set-Cookie).- Альтернатива (менее безопасная): хранить в памяти/secure storage и передавать в теле запроса.
POST /api/auth/refresh
Запрос (вариант с телом):
{
"refreshToken": "<refresh-token>"
}
Успех:
- 200 OK
{
"accessToken": "<new-jwt>",
"tokenType": "Bearer",
"refreshToken": "<new-refresh-token>"
}
Ошибки:
- 400 — отсутствует/некорректный refreshToken
- 401 — просрочен/отозван/невалиден
Пример (fetch, с телом):
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-стратегия):
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 <JWT>
Пример защищенного вызова:
await fetch(`${API_URL}/api/private/profile`, {
headers: { Authorization: `Bearer ${token}` },
});
Формат ошибок (пример)
{
"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):
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!"}'
Вход:
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
- Сброс пароля через почту