Files
NeveTimePanel/СХЕМА_РАБОТЫ.md
2026-01-15 09:32:13 +06:00

11 KiB
Raw Blame History

🔄 Схема работы 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
}

Безопасность

Защита от атак

  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.

Всё работает автоматически и безопасно! 🔐