8.4 KiB
8.4 KiB
🏗️ Архитектура системы авторизации Discours Core
🎯 Обзор архитектуры 2025
Модульная система авторизации с httpOnly cookies для максимальной безопасности и единообразия.
Ключевые принципы:
- 🍪 httpOnly cookies для ВСЕХ типов авторизации (OAuth + Email/Password)
- 🛡️ Максимальная безопасность - защита от XSS и CSRF
- 🔄 Единообразие - один механизм для всех провайдеров
- 📱 Автоматическое управление - браузер сам отправляет cookies
Хранение данных:
- Сессии → Redis (JWT токены) + httpOnly cookies (передача)
- OAuth токены → Redis (для API интеграций)
- Пользователи → PostgreSQL (основные данные + OAuth связи)
📊 Схема потоков данных
graph TB
subgraph "Frontend"
FE[Web Frontend]
MOB[Mobile App]
API[API Clients]
end
subgraph "Auth Layer"
MW[AuthMiddleware]
DEC[GraphQL Decorators]
UTILS[Auth Utils]
end
subgraph "Token Managers"
STM[SessionTokenManager]
VTM[VerificationTokenManager]
OTM[OAuthTokenManager]
BTM[BatchTokenOperations]
MON[TokenMonitoring]
end
subgraph "Storage"
REDIS[(Redis)]
DB[(PostgreSQL)]
end
subgraph "External OAuth"
GOOGLE[Google]
GITHUB[GitHub]
FACEBOOK[Facebook]
VK[VK]
YANDEX[Yandex]
end
FE --> MW
MOB --> MW
API --> MW
MW --> STM
MW --> UTILS
DEC --> STM
UTILS --> STM
STM --> REDIS
VTM --> REDIS
OTM --> REDIS
BTM --> REDIS
MON --> REDIS
STM --> DB
OTM --> GOOGLE
OTM --> GITHUB
OTM --> FACEBOOK
OTM --> VK
OTM --> YANDEX
🏗️ Диаграмма компонентов
Примечание: Токены хранятся только в Redis, PostgreSQL используется только для пользовательских данных и OAuth связей.
graph TB
subgraph "HTTP Layer"
REQ[HTTP Request]
RESP[HTTP Response]
end
subgraph "Middleware Layer"
AUTH_MW[AuthMiddleware]
UTILS[Auth Utils]
end
subgraph "Token Management"
STM[SessionTokenManager]
VTM[VerificationTokenManager]
OTM[OAuthTokenManager]
BTM[BatchTokenOperations]
MON[TokenMonitoring]
end
subgraph "Storage"
REDIS[(Redis)]
DB[(PostgreSQL)]
end
subgraph "External"
OAUTH_PROV[OAuth Providers]
end
REQ --> AUTH_MW
AUTH_MW --> UTILS
UTILS --> STM
STM --> REDIS
VTM --> REDIS
OTM --> REDIS
BTM --> REDIS
MON --> REDIS
STM --> DB
OTM --> OAUTH_PROV
STM --> RESP
VTM --> RESP
OTM --> RESP
🔐 OAuth Flow (httpOnly cookies)
sequenceDiagram
participant U as User
participant F as Frontend
participant B as Backend
participant R as Redis
participant P as OAuth Provider
U->>F: Click "Login with Provider"
F->>B: GET /oauth/{provider}/login
B->>R: Store OAuth state (TTL: 10 min)
B->>P: Redirect to Provider
P->>U: Show authorization page
U->>P: Grant permission
P->>B: GET /oauth/{provider}/callback?code={code}&state={state}
B->>R: Verify state
B->>P: Exchange code for token
P->>B: Return access token + user data
B->>B: Create/update user
B->>B: Generate JWT session token
B->>R: Store session in Redis
B->>F: Redirect + Set httpOnly cookie
Note over B,F: Cookie: session_token=JWT<br/>HttpOnly, Secure, SameSite=lax
F->>U: User logged in (cookie automatic)
Note over F,B: All subsequent requests
F->>B: GraphQL with credentials: 'include'
Note over F,B: Browser automatically sends cookie
🔄 Session Management (httpOnly cookies)
stateDiagram-v2
[*] --> Anonymous
Anonymous --> Authenticating: Login attempt (OAuth/Email)
Authenticating --> Authenticated: Valid JWT + httpOnly cookie set
Authenticating --> Anonymous: Invalid credentials
Authenticated --> Refreshing: Token near expiry
Refreshing --> Authenticated: New httpOnly cookie set
Refreshing --> Anonymous: Refresh failed
Authenticated --> Anonymous: Logout (cookie deleted)
Authenticated --> Anonymous: Token expired (cookie invalid)
note right of Authenticated
All requests include
httpOnly cookie automatically
via credentials: 'include'
end note
🗄️ Redis структура данных
# JWT Sessions (основные - передаются через httpOnly cookies)
session:{user_id}:{token} # Hash: {user_id, username, device_info, last_activity}
user_sessions:{user_id} # Set: {token1, token2, ...}
# OAuth Tokens (для API интеграций - НЕ для аутентификации)
oauth_access:{user_id}:{provider} # JSON: {token, expires_in, scope}
oauth_refresh:{user_id}:{provider} # JSON: {token, provider_data}
# OAuth State (временные - для CSRF защиты)
oauth_state:{state} # JSON: {provider, redirect_uri, code_verifier} TTL: 10 мин
# Verification Tokens (email подтверждения и т.д.)
verification_token:{token} # JSON: {user_id, type, data, created_at}
🔄 Изменения в архитектуре 2025:
Убрано:
- ❌ Токены в URL параметрах (небезопасно)
- ❌ localStorage для основных токенов (уязвимо к XSS)
- ❌ Bearer заголовки для веб-приложений (сложнее управлять)
Добавлено:
- ✅ httpOnly cookies для всех типов авторизации
- ✅ Автоматическая отправка cookies браузером
- ✅ SameSite защита от CSRF
- ✅ Secure flag для HTTPS
Примеры Redis команд
# Поиск сессий пользователя
redis-cli --scan --pattern "session:123:*"
# Получение данных сессии
redis-cli HGETALL "session:123:your_token_here"
# Проверка TTL
redis-cli TTL "session:123:your_token_here"
# Поиск OAuth токенов
redis-cli --scan --pattern "oauth_access:123:*"
🔒 Security Components
graph TD
subgraph "Input Validation"
EMAIL[Email Format]
PASS[Password Strength]
TOKEN[JWT Validation]
end
subgraph "Authentication"
BCRYPT[bcrypt + SHA256]
JWT_SIGN[JWT Signing]
OAUTH_VERIFY[OAuth Verification]
end
subgraph "Authorization"
RBAC[RBAC System]
PERM[Permission Checks]
RESOURCE[Resource Access]
end
subgraph "Session Security"
TTL[Redis TTL]
REVOKE[Token Revocation]
REFRESH[Secure Refresh]
end
EMAIL --> BCRYPT
PASS --> BCRYPT
TOKEN --> JWT_SIGN
BCRYPT --> RBAC
JWT_SIGN --> RBAC
OAUTH_VERIFY --> RBAC
RBAC --> PERM
PERM --> RESOURCE
RESOURCE --> TTL
RESOURCE --> REVOKE
RESOURCE --> REFRESH
⚡ Performance & Scaling
Горизонтальное масштабирование
- Stateless JWT токены
- Redis Cluster для высокой доступности
- Load Balancer aware session management
Оптимизации
- Connection pooling для Redis
- Batch operations для массовых операций (100-1000 токенов)
- Pipeline использование для атомарности
- SCAN вместо KEYS для безопасности
Мониторинг производительности
from auth.tokens.monitoring import TokenMonitoring
monitoring = TokenMonitoring()
# Статистика токенов
stats = await monitoring.get_token_statistics()
# {
# "session_tokens": 150,
# "verification_tokens": 5,
# "oauth_access_tokens": 25,
# "memory_usage": 1048576
# }
# Health check
health = await monitoring.health_check()
# {"status": "healthy", "redis_connected": True}