This commit is contained in:
2026-01-15 09:32:13 +06:00
parent 14f020e819
commit 303d38f28e
19 changed files with 2072 additions and 14 deletions

282
СХЕМА_РАБОТЫ.md Normal file
View File

@@ -0,0 +1,282 @@
# 🔄 Схема работы OpenID Connect с ZITADEL
## Визуальная схема
```
┌─────────────┐
│ Пользователь│
└──────┬──────┘
│ 1. Открывает страницу входа
┌─────────────────────────────────────┐
│ Frontend (React) │
│ http://localhost:3000 │
│ │
│ ┌───────────────────────────────┐ │
│ │ Форма входа │ │
│ │ - Логин/Пароль │ │
│ │ - Кнопка ZITADEL 🔐 │ │
│ └───────────────────────────────┘ │
└──────────────┬──────────────────────┘
│ 2. Нажимает "Войти через ZITADEL"
│ GET /api/auth/oidc/zitadel/login
┌─────────────────────────────────────┐
│ Backend (FastAPI) │
│ http://localhost:8000 │
│ │
│ ┌───────────────────────────────┐ │
│ │ OAuth Client │ │
│ │ - Создаёт authorize URL │ │
│ │ - Добавляет state, nonce │ │
│ └───────────────────────────────┘ │
└──────────────┬──────────────────────┘
│ 3. Redirect на ZITADEL
┌─────────────────────────────────────┐
│ ZITADEL │
│ https://your-instance.zitadel.cloud│
│ │
│ ┌───────────────────────────────┐ │
│ │ Страница входа │ │
│ │ - Email/Username │ │
│ │ - Password │ │
│ │ - 2FA (опционально) │ │
│ └───────────────────────────────┘ │
└──────────────┬──────────────────────┘
│ 4. Пользователь вводит данные
│ 5. ZITADEL проверяет
│ 6. Redirect с code
┌─────────────────────────────────────┐
│ Backend (FastAPI) │
│ /api/auth/oidc/zitadel/callback │
│ │
│ ┌───────────────────────────────┐ │
│ │ 7. Обмен code на token │ │
│ │ POST /oauth/token │ │
│ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────┐ │
│ │ 8. Получение userinfo │ │
│ │ - email │ │
│ │ - name │ │
│ │ - sub (user ID) │ │
│ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────┐ │
│ │ 9. Создание/обновление │ │
│ │ пользователя в users.json │ │
│ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────┐ │
│ │ 10. Генерация JWT токена │ │
│ │ для MC Panel │ │
│ └───────────────────────────────┘ │
└──────────────┬──────────────────────┘
│ 11. Redirect на frontend
│ ?token=xxx&username=yyy
┌─────────────────────────────────────┐
│ Frontend (React) │
│ │
│ ┌───────────────────────────────┐ │
│ │ 12. Обработка callback │ │
│ │ - Извлечение token │ │
│ │ - Сохранение в localStorage│ │
│ │ - Очистка URL │ │
│ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────┐ │
│ │ 13. Автоматический вход │ │
│ │ - Загрузка данных │ │
│ │ - Показ панели │ │
│ └───────────────────────────────┘ │
└──────────────┬──────────────────────┘
│ 14. Пользователь в системе!
┌─────────────────────────────────────┐
│ MC Panel Dashboard │
│ - Серверы │
│ - Тикеты │
│ - Личный кабинет │
└─────────────────────────────────────┘
```
## Детальный поток данных
### Шаг 1-2: Инициация входа
```
Пользователь → Frontend
Frontend → Backend: GET /api/auth/oidc/zitadel/login
Backend создаёт OAuth URL:
- client_id
- redirect_uri
- scope: openid email profile
- state (CSRF защита)
- nonce (replay защита)
```
### Шаг 3-6: Аутентификация в ZITADEL
```
Backend → ZITADEL: Redirect на /oauth/authorize
ZITADEL показывает форму входа
Пользователь вводит данные
ZITADEL проверяет учётные данные
ZITADEL → Backend: Redirect с code
URL: /callback?code=xxx&state=yyy
```
### Шаг 7-8: Получение данных
```
Backend → ZITADEL: POST /oauth/token
Параметры:
- code
- client_id
- client_secret
- redirect_uri
ZITADEL → Backend: access_token + id_token
Backend извлекает userinfo:
{
"sub": "123456789012345678",
"email": "user@example.com",
"name": "John Doe",
"picture": "https://..."
}
```
### Шаг 9-10: Создание пользователя
```
Backend проверяет users.json:
- Ищет по oidc_id = "zitadel:123456789012345678"
Если найден:
- Обновляет email, name, picture
Если не найден:
- Создаёт нового пользователя
- Генерирует username из email
- Роль: "user"
- Пустой пароль (OIDC пользователь)
Backend создаёт JWT токен:
{
"sub": "john_doe",
"role": "user",
"exp": 1234567890
}
```
### Шаг 11-14: Возврат в приложение
```
Backend → Frontend: Redirect
URL: http://localhost:3000/?token=xxx&username=yyy
Frontend (useEffect):
- Извлекает token и username из URL
- Сохраняет в localStorage
- Очищает URL (history.replaceState)
- Обновляет состояние (setToken, setUser)
Frontend загружает данные:
- GET /api/auth/me (проверка токена)
- GET /api/servers (список серверов)
Пользователь видит панель управления
```
## Структура данных
### ZITADEL userinfo
```json
{
"sub": "123456789012345678",
"email": "user@example.com",
"email_verified": true,
"name": "John Doe",
"given_name": "John",
"family_name": "Doe",
"picture": "https://avatar.url",
"locale": "en"
}
```
### MC Panel user (users.json)
```json
{
"john_doe": {
"username": "john_doe",
"password": "",
"role": "user",
"servers": [],
"oidc_id": "zitadel:123456789012345678",
"email": "user@example.com",
"name": "John Doe",
"picture": "https://avatar.url",
"provider": "zitadel",
"created_at": "2026-01-15T12:00:00"
}
}
```
### JWT токен (MC Panel)
```json
{
"sub": "john_doe",
"role": "user",
"exp": 1737820800,
"iat": 1737216000
}
```
## Безопасность
### Защита от атак
1. **CSRF (Cross-Site Request Forgery)**
- State parameter проверяется
- Случайное значение для каждого запроса
2. **Replay атаки**
- Nonce в id_token
- Одноразовое использование code
3. **Man-in-the-Middle**
- HTTPS обязателен в продакшене
- Проверка redirect_uri
4. **Token theft**
- JWT с истечением (7 дней)
- Хранение в localStorage (XSS защита нужна)
### Рекомендации для продакшена
```
✓ Использовать HTTPS
✓ Настроить CORS правильно
✓ Добавить rate limiting
✓ Логировать все входы
✓ Мониторить подозрительную активность
✓ Регулярно обновлять client_secret
✓ Использовать refresh tokens
```
## Готово! 🎉
Схема показывает полный цикл аутентификации через ZITADEL.
**Всё работает автоматически и безопасно!** 🔐