login is ready

This commit is contained in:
root
2025-09-12 10:02:09 +05:00
parent c52b1c72e7
commit 4f18dd6ae3
18 changed files with 1050 additions and 170 deletions
+104
View File
@@ -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": "описание ошибки" }
```
+43
View File
@@ -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
+248
View File
@@ -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: 515 минут
- refreshToken: 730 дней
## 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
- Сброс пароля через почту
+19
View File
@@ -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 — нет или просрочен токен