login is ready
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
## Admin Users API
|
||||
|
||||
Требуется `Authorization: Bearer <admin_access_token>` и роль `ROLE_ADMIN`.
|
||||
|
||||
### Создать пользователя
|
||||
|
||||
POST `/api/admin/users`
|
||||
|
||||
Body:
|
||||
|
||||
```json
|
||||
{ "email": "user@example.com", "password": "StrongPass123!" }
|
||||
```
|
||||
|
||||
Ответ: `200 OK` (пусто)
|
||||
|
||||
Ошибки: 400 (валидация), 401/403 (нет прав), 409 (email занят)
|
||||
|
||||
### Назначить роли пользователю
|
||||
|
||||
POST `/api/admin/users/roles`
|
||||
|
||||
Body:
|
||||
|
||||
```json
|
||||
{ "email": "user@example.com", "roles": ["ROLE_USER", "ROLE_ADMIN"] }
|
||||
```
|
||||
|
||||
Ответ: `200 OK` (пусто)
|
||||
|
||||
Ошибки: 400 (невалидная роль/пользователь не найден), 401/403
|
||||
|
||||
### Список доступных ролей
|
||||
|
||||
GET `/api/admin/roles`
|
||||
|
||||
Ответ:
|
||||
|
||||
```json
|
||||
["ROLE_ADMIN", "ROLE_USER"]
|
||||
```
|
||||
|
||||
Ошибки: 401/403
|
||||
|
||||
### Список пользователей (пагинация)
|
||||
|
||||
GET `/api/admin/users?page=0&size=20`
|
||||
|
||||
Ответ (`Page<UserSummary>`):
|
||||
|
||||
```json
|
||||
{
|
||||
"content": [
|
||||
{ "id": 1, "email": "root@konturai.local", "roles": "ROLE_ADMIN,ROLE_USER" }
|
||||
],
|
||||
"pageable": { "pageNumber": 0, "pageSize": 20, ... },
|
||||
"totalElements": 1,
|
||||
"totalPages": 1,
|
||||
"last": true,
|
||||
"size": 20,
|
||||
"number": 0,
|
||||
"sort": { ... },
|
||||
"first": true,
|
||||
"numberOfElements": 1,
|
||||
"empty": false
|
||||
}
|
||||
```
|
||||
|
||||
Ошибки: 401/403
|
||||
|
||||
### Обновить пользователя
|
||||
|
||||
PUT `/api/admin/users/update`
|
||||
|
||||
Body (любые поля опциональны кроме `id`):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"email": "new@mail.com",
|
||||
"password": "NewPass123!",
|
||||
"roles": ["ROLE_USER"]
|
||||
}
|
||||
```
|
||||
|
||||
Ответ: `200 OK` (пусто)
|
||||
|
||||
Ошибки: 400 (невалидные данные/роль), 401/403, 404 (пользователь не найден)
|
||||
|
||||
### Удалить пользователя
|
||||
|
||||
DELETE `/api/admin/users?id=1`
|
||||
|
||||
Ответ: `200 OK` (пусто)
|
||||
|
||||
Ошибки: 401/403
|
||||
|
||||
### Формат ошибок
|
||||
|
||||
Все ошибки возвращают JSON:
|
||||
|
||||
```json
|
||||
{ "message": "описание ошибки" }
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
## Admin: Пользователи и роли
|
||||
|
||||
Требуется роль `ROLE_ADMIN` и заголовок `Authorization: Bearer <admin_access_token>`.
|
||||
|
||||
### Создать пользователя
|
||||
|
||||
POST `/api/admin/users`
|
||||
|
||||
Body:
|
||||
|
||||
```json
|
||||
{ "email": "user@example.com", "password": "StrongPass123!" }
|
||||
```
|
||||
|
||||
Ответ: `200 OK` (пусто)
|
||||
|
||||
Ошибки: 400, 401/403, 409
|
||||
|
||||
### Назначить роли пользователю
|
||||
|
||||
POST `/api/admin/users/roles`
|
||||
|
||||
Body:
|
||||
|
||||
```json
|
||||
{ "email": "user@example.com", "roles": ["ROLE_USER", "ROLE_ADMIN"] }
|
||||
```
|
||||
|
||||
Ответ: `200 OK` (пусто)
|
||||
|
||||
Ошибки: 400 (invalid role / user not found), 401/403
|
||||
|
||||
### Список доступных ролей
|
||||
|
||||
GET `/api/admin/roles`
|
||||
|
||||
Ответ:
|
||||
|
||||
```json
|
||||
["ROLE_ADMIN", "ROLE_USER"]
|
||||
```
|
||||
|
||||
Ошибки: 401/403
|
||||
@@ -0,0 +1,248 @@
|
||||
## Документация по аутентификации (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`.
|
||||
|
||||
Запрос:
|
||||
|
||||
```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": "<JWT>",
|
||||
"tokenType": "Bearer",
|
||||
"refreshToken": "<refresh-token>"
|
||||
}
|
||||
```
|
||||
|
||||
Ошибки:
|
||||
|
||||
- 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 <JWT>`.
|
||||
- Когда `accessToken` истекает (HTTP 401), фронт вызывает `/api/auth/refresh` с `refreshToken`, получает новую пару токенов (ротация) и повторяет запрос.
|
||||
|
||||
### Рекомендации по хранению
|
||||
|
||||
- `refreshToken` предпочтительно хранить в HttpOnly Secure SameSite cookie (сервер ставит Set-Cookie).
|
||||
- Альтернатива (менее безопасная): хранить в памяти/secure storage и передавать в теле запроса.
|
||||
|
||||
### POST /api/auth/refresh
|
||||
|
||||
Запрос (вариант с телом):
|
||||
|
||||
```json
|
||||
{
|
||||
"refreshToken": "<refresh-token>"
|
||||
}
|
||||
```
|
||||
|
||||
Успех:
|
||||
|
||||
- 200 OK
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "<new-jwt>",
|
||||
"tokenType": "Bearer",
|
||||
"refreshToken": "<new-refresh-token>"
|
||||
}
|
||||
```
|
||||
|
||||
Ошибки:
|
||||
|
||||
- 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 <JWT>
|
||||
```
|
||||
|
||||
Пример защищенного вызова:
|
||||
|
||||
```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
|
||||
- Сброс пароля через почту
|
||||
@@ -0,0 +1,19 @@
|
||||
## Identity
|
||||
|
||||
Требуется авторизация `Authorization: Bearer <access_token>`.
|
||||
|
||||
### Текущий пользователь
|
||||
|
||||
GET `/api/identity/me`
|
||||
|
||||
Ответ:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"email": "root@konturai.local",
|
||||
"roles": ["ROLE_ADMIN", "ROLE_USER"]
|
||||
}
|
||||
```
|
||||
|
||||
Ошибки: 401 — нет или просрочен токен
|
||||
Reference in New Issue
Block a user