11 KiB
11 KiB
🔄 Схема работы 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
{
"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)
{
"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)
{
"sub": "john_doe",
"role": "user",
"exp": 1737820800,
"iat": 1737216000
}
Безопасность
Защита от атак
-
CSRF (Cross-Site Request Forgery)
- State parameter проверяется
- Случайное значение для каждого запроса
-
Replay атаки
- Nonce в id_token
- Одноразовое использование code
-
Man-in-the-Middle
- HTTPS обязателен в продакшене
- Проверка redirect_uri
-
Token theft
- JWT с истечением (7 дней)
- Хранение в localStorage (XSS защита нужна)
Рекомендации для продакшена
✓ Использовать HTTPS
✓ Настроить CORS правильно
✓ Добавить rate limiting
✓ Логировать все входы
✓ Мониторить подозрительную активность
✓ Регулярно обновлять client_secret
✓ Использовать refresh tokens
Готово! 🎉
Схема показывает полный цикл аутентификации через ZITADEL.
Всё работает автоматически и безопасно! 🔐