2025-09-28 12:22:37 +03:00
|
|
|
|
# 🏗️ Архитектура системы авторизации Discours Core
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
## 🎯 Обзор архитектуры 2025
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
Модульная система авторизации с **httpOnly cookies** для максимальной безопасности и единообразия.
|
|
|
|
|
|
|
|
|
|
|
|
**Ключевые принципы:**
|
|
|
|
|
|
- **🍪 httpOnly cookies** для ВСЕХ типов авторизации (OAuth + Email/Password)
|
|
|
|
|
|
- **🛡️ Максимальная безопасность** - защита от XSS и CSRF
|
|
|
|
|
|
- **🔄 Единообразие** - один механизм для всех провайдеров
|
|
|
|
|
|
- **📱 Автоматическое управление** - браузер сам отправляет cookies
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
**Хранение данных:**
|
2025-09-28 12:22:37 +03:00
|
|
|
|
- **Сессии** → Redis (JWT токены) + httpOnly cookies (передача)
|
|
|
|
|
|
- **OAuth токены** → Redis (для API интеграций)
|
|
|
|
|
|
- **Пользователи** → PostgreSQL (основные данные + OAuth связи)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
## 📊 Схема потоков данных
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
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 связей.
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
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
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
## 🔐 OAuth Flow (httpOnly cookies)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant U as User
|
|
|
|
|
|
participant F as Frontend
|
2025-09-28 12:22:37 +03:00
|
|
|
|
participant B as Backend
|
2025-09-22 00:56:36 +03:00
|
|
|
|
participant R as Redis
|
|
|
|
|
|
participant P as OAuth Provider
|
|
|
|
|
|
|
|
|
|
|
|
U->>F: Click "Login with Provider"
|
2025-09-28 12:22:37 +03:00
|
|
|
|
F->>B: GET /oauth/{provider}/login
|
|
|
|
|
|
B->>R: Store OAuth state (TTL: 10 min)
|
|
|
|
|
|
B->>P: Redirect to Provider
|
2025-09-22 00:56:36 +03:00
|
|
|
|
P->>U: Show authorization page
|
|
|
|
|
|
U->>P: Grant permission
|
2025-09-28 12:22:37 +03:00
|
|
|
|
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
|
2025-09-22 00:56:36 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
## 🔄 Session Management (httpOnly cookies)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
[*] --> Anonymous
|
2025-09-28 12:22:37 +03:00
|
|
|
|
Anonymous --> Authenticating: Login attempt (OAuth/Email)
|
|
|
|
|
|
Authenticating --> Authenticated: Valid JWT + httpOnly cookie set
|
2025-09-22 00:56:36 +03:00
|
|
|
|
Authenticating --> Anonymous: Invalid credentials
|
|
|
|
|
|
Authenticated --> Refreshing: Token near expiry
|
2025-09-28 12:22:37 +03:00
|
|
|
|
Refreshing --> Authenticated: New httpOnly cookie set
|
2025-09-22 00:56:36 +03:00
|
|
|
|
Refreshing --> Anonymous: Refresh failed
|
2025-09-28 12:22:37 +03:00
|
|
|
|
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
|
2025-09-22 00:56:36 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 🗄️ Redis структура данных
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# JWT Sessions (основные - передаются через httpOnly cookies)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
session:{user_id}:{token} # Hash: {user_id, username, device_info, last_activity}
|
|
|
|
|
|
user_sessions:{user_id} # Set: {token1, token2, ...}
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# OAuth Tokens (для API интеграций - НЕ для аутентификации)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
oauth_access:{user_id}:{provider} # JSON: {token, expires_in, scope}
|
|
|
|
|
|
oauth_refresh:{user_id}:{provider} # JSON: {token, provider_data}
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# 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-09-22 00:56:36 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
### 🔄 Изменения в архитектуре 2025:
|
|
|
|
|
|
|
|
|
|
|
|
**Убрано:**
|
|
|
|
|
|
- ❌ Токены в URL параметрах (небезопасно)
|
|
|
|
|
|
- ❌ localStorage для основных токенов (уязвимо к XSS)
|
|
|
|
|
|
- ❌ Bearer заголовки для веб-приложений (сложнее управлять)
|
|
|
|
|
|
|
|
|
|
|
|
**Добавлено:**
|
|
|
|
|
|
- ✅ httpOnly cookies для всех типов авторизации
|
|
|
|
|
|
- ✅ Автоматическая отправка cookies браузером
|
|
|
|
|
|
- ✅ SameSite защита от CSRF
|
|
|
|
|
|
- ✅ Secure flag для HTTPS
|
|
|
|
|
|
|
2025-09-22 00:56:36 +03:00
|
|
|
|
### Примеры Redis команд
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Поиск сессий пользователя
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
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 для безопасности
|
|
|
|
|
|
|
|
|
|
|
|
### Мониторинг производительности
|
|
|
|
|
|
```python
|
|
|
|
|
|
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}
|
|
|
|
|
|
```
|