2025-09-22 00:56:36 +03:00
|
|
|
|
# 🔐 Система аутентификации Discours Core
|
|
|
|
|
|
|
|
|
|
|
|
## 📚 Обзор
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
Модульная система аутентификации с **httpOnly cookies**, JWT токенами, Redis-сессиями, OAuth интеграцией и RBAC авторизацией.
|
|
|
|
|
|
|
|
|
|
|
|
### 🎯 **Единый подход с httpOnly cookies для ВСЕХ типов авторизации:**
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ **OAuth** (Google/GitHub/Yandex/VK) → httpOnly cookie
|
|
|
|
|
|
- ✅ **Email/Password** → httpOnly cookie
|
|
|
|
|
|
- ✅ **GraphQL запросы** → `credentials: 'include'`
|
|
|
|
|
|
- ✅ **Максимальная безопасность** → защита от XSS/CSRF
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
## 🚀 Быстрый старт
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
### Для разработчиков
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
from auth.tokens.sessions import SessionTokenManager
|
|
|
|
|
|
from auth.utils import extract_token_from_request
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# Проверка токена (автоматически из cookie или Bearer заголовка)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
sessions = SessionTokenManager()
|
|
|
|
|
|
token = await extract_token_from_request(request)
|
|
|
|
|
|
payload = await sessions.verify_session(token)
|
|
|
|
|
|
|
|
|
|
|
|
if payload:
|
|
|
|
|
|
user_id = payload.get("user_id")
|
|
|
|
|
|
print(f"Пользователь авторизован: {user_id}")
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
### Для фронтенда
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// Все запросы используют httpOnly cookies
|
|
|
|
|
|
const response = await fetch('/graphql', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
credentials: 'include', // ✅ КРИТИЧНО: отправляет httpOnly cookies
|
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
|
body: JSON.stringify({ query, variables })
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-09-22 00:56:36 +03:00
|
|
|
|
### Redis ключи для поиска
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Сессии пользователей
|
|
|
|
|
|
session:{user_id}:{token} # Данные сессии (hash)
|
|
|
|
|
|
user_sessions:{user_id} # Список активных токенов (set)
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# OAuth токены (для API интеграций)
|
2025-09-22 00:56:36 +03:00
|
|
|
|
oauth_access:{user_id}:{provider} # Access токен
|
|
|
|
|
|
oauth_refresh:{user_id}:{provider} # Refresh токен
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 📖 Документация
|
|
|
|
|
|
|
|
|
|
|
|
### 🏗️ Архитектура
|
|
|
|
|
|
- **[Обзор системы](system.md)** - Компоненты и менеджеры токенов
|
|
|
|
|
|
- **[Архитектура](architecture.md)** - Диаграммы и потоки данных
|
|
|
|
|
|
- **[Миграция](migration.md)** - Обновление с предыдущих версий
|
|
|
|
|
|
|
|
|
|
|
|
### 🔑 Аутентификация
|
|
|
|
|
|
- **[Управление сессиями](sessions.md)** - JWT токены и Redis хранение
|
2025-09-28 12:22:37 +03:00
|
|
|
|
- **[OAuth интеграция](oauth.md)** - Социальные провайдеры с httpOnly cookies
|
2025-09-22 00:56:36 +03:00
|
|
|
|
- **[Микросервисы](microservices.md)** - 🎯 **Интеграция с другими сервисами**
|
|
|
|
|
|
|
|
|
|
|
|
### 🛠️ Разработка
|
|
|
|
|
|
- **[API Reference](api.md)** - Методы и примеры кода
|
|
|
|
|
|
- **[Безопасность](security.md)** - Лучшие практики
|
|
|
|
|
|
- **[Тестирование](testing.md)** - Unit и E2E тесты
|
|
|
|
|
|
|
|
|
|
|
|
### 🔗 Связанные системы
|
|
|
|
|
|
- **[RBAC System](../rbac-system.md)** - Система ролей и разрешений
|
|
|
|
|
|
- **[Security System](../security.md)** - Управление паролями и email
|
|
|
|
|
|
- **[Redis Schema](../redis-schema.md)** - Схема данных и кеширование
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
## 🔄 OAuth Flow (обновленный 2025)
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 🚀 Инициация OAuth
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// Пользователь нажимает "Войти через Google"
|
|
|
|
|
|
const handleOAuthLogin = (provider: string) => {
|
|
|
|
|
|
window.location.href = `/oauth/${provider}/login`;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 🔄 OAuth Callback (бэкенд)
|
|
|
|
|
|
```python
|
|
|
|
|
|
# Google → /oauth/google/callback
|
|
|
|
|
|
# 1. Обменивает code на access_token
|
|
|
|
|
|
# 2. Получает профиль пользователя
|
|
|
|
|
|
# 3. Создает JWT сессию
|
|
|
|
|
|
# 4. Устанавливает httpOnly cookie
|
|
|
|
|
|
# 5. Редиректит на фронтенд БЕЗ токена в URL
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 🌐 Фронтенд финализация
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// Проверяем URL на ошибки
|
|
|
|
|
|
const error = urlParams.get('error');
|
|
|
|
|
|
if (error) {
|
|
|
|
|
|
// Обработка ошибок OAuth
|
|
|
|
|
|
console.error('OAuth error:', error);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Успех! httpOnly cookie уже установлен
|
|
|
|
|
|
await auth.checkSession(); // Загружает из cookie
|
|
|
|
|
|
navigate('/dashboard');
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-09-22 00:56:36 +03:00
|
|
|
|
## 🔍 Для микросервисов
|
|
|
|
|
|
|
|
|
|
|
|
### Подключение к Redis
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
# Используйте тот же Redis connection pool
|
|
|
|
|
|
from storage.redis import redis
|
|
|
|
|
|
|
|
|
|
|
|
# Проверка сессии
|
|
|
|
|
|
async def check_user_session(token: str) -> dict | None:
|
|
|
|
|
|
sessions = SessionTokenManager()
|
|
|
|
|
|
return await sessions.verify_session(token)
|
|
|
|
|
|
|
|
|
|
|
|
# Массовая проверка токенов
|
|
|
|
|
|
from auth.tokens.batch import BatchTokenOperations
|
|
|
|
|
|
batch = BatchTokenOperations()
|
|
|
|
|
|
results = await batch.batch_validate_tokens(token_list)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### HTTP заголовки
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# Извлечение токена из запроса (cookie или Bearer)
|
|
|
|
|
|
from auth.utils import extract_token_from_request
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
token = await extract_token_from_request(request)
|
2025-09-28 12:22:37 +03:00
|
|
|
|
# Автоматически проверяет:
|
|
|
|
|
|
# 1. Authorization: Bearer <token>
|
|
|
|
|
|
# 2. Cookie: session_token=<token>
|
2025-09-22 00:56:36 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 Основные компоненты
|
|
|
|
|
|
|
2025-09-28 12:22:37 +03:00
|
|
|
|
- **SessionTokenManager** - JWT сессии с Redis хранением + httpOnly cookies
|
|
|
|
|
|
- **OAuthTokenManager** - OAuth access/refresh токены для API интеграций
|
2025-09-22 00:56:36 +03:00
|
|
|
|
- **BatchTokenOperations** - Массовые операции с токенами
|
|
|
|
|
|
- **TokenMonitoring** - Мониторинг и статистика
|
2025-09-28 12:22:37 +03:00
|
|
|
|
- **AuthMiddleware** - HTTP middleware с поддержкой cookies
|
2025-09-22 00:56:36 +03:00
|
|
|
|
|
|
|
|
|
|
## ⚡ Производительность
|
|
|
|
|
|
|
|
|
|
|
|
- **Connection pooling** для Redis
|
|
|
|
|
|
- **Batch операции** для массовых действий (100-1000 токенов)
|
|
|
|
|
|
- **Pipeline использование** для атомарности
|
|
|
|
|
|
- **SCAN** вместо KEYS для безопасности
|
|
|
|
|
|
- **TTL** автоматическая очистка истекших токенов
|
2025-09-28 12:22:37 +03:00
|
|
|
|
- **httpOnly cookies** - автоматическая отправка браузером
|
|
|
|
|
|
|
|
|
|
|
|
## 🛡️ Безопасность (2025)
|
|
|
|
|
|
|
|
|
|
|
|
### Максимальная защита:
|
|
|
|
|
|
- **🚫 Защита от XSS**: httpOnly cookies недоступны JavaScript
|
|
|
|
|
|
- **🔒 Защита от CSRF**: SameSite=lax cookies
|
|
|
|
|
|
- **🛡️ Единообразие**: Все типы авторизации через cookies
|
|
|
|
|
|
- **📱 Автоматическая отправка**: Браузер сам включает cookies
|
|
|
|
|
|
|
|
|
|
|
|
### Миграция с Bearer токенов:
|
|
|
|
|
|
- ✅ OAuth теперь использует httpOnly cookies (вместо localStorage)
|
|
|
|
|
|
- ✅ Email/Password использует httpOnly cookies (вместо Bearer)
|
|
|
|
|
|
- ✅ Фронтенд: `credentials: 'include'` во всех запросах
|
|
|
|
|
|
- ✅ Middleware поддерживает оба подхода для совместимости
|
|
|
|
|
|
|
|
|
|
|
|
## 🔧 Настройка
|
|
|
|
|
|
|
|
|
|
|
|
### Environment Variables
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# OAuth провайдеры
|
|
|
|
|
|
GOOGLE_CLIENT_ID=your_google_client_id
|
|
|
|
|
|
GOOGLE_CLIENT_SECRET=your_google_client_secret
|
|
|
|
|
|
GITHUB_CLIENT_ID=your_github_client_id
|
|
|
|
|
|
GITHUB_CLIENT_SECRET=your_github_client_secret
|
|
|
|
|
|
|
|
|
|
|
|
# Cookie настройки
|
|
|
|
|
|
SESSION_COOKIE_SECURE=true
|
|
|
|
|
|
SESSION_COOKIE_HTTPONLY=true
|
|
|
|
|
|
SESSION_COOKIE_SAMESITE=lax
|
|
|
|
|
|
SESSION_COOKIE_MAX_AGE=2592000 # 30 дней
|
|
|
|
|
|
|
|
|
|
|
|
# JWT
|
|
|
|
|
|
JWT_SECRET=your_jwt_secret_key
|
|
|
|
|
|
JWT_EXPIRATION_HOURS=720 # 30 дней
|
|
|
|
|
|
|
|
|
|
|
|
# Redis
|
|
|
|
|
|
REDIS_URL=redis://localhost:6379/0
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Быстрая проверка
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Проверка OAuth провайдеров
|
|
|
|
|
|
curl https://your-domain.com/oauth/google
|
|
|
|
|
|
|
|
|
|
|
|
# Проверка сессии
|
|
|
|
|
|
curl -b "session_token=your_token" https://your-domain.com/graphql \
|
|
|
|
|
|
-d '{"query":"query { getSession { success author { id } } }"}'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 Мониторинг
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
from auth.tokens.monitoring import TokenMonitoring
|
|
|
|
|
|
|
|
|
|
|
|
monitoring = TokenMonitoring()
|
|
|
|
|
|
|
|
|
|
|
|
# Статистика токенов
|
|
|
|
|
|
stats = await monitoring.get_token_statistics()
|
|
|
|
|
|
print(f"Active sessions: {stats['session_tokens']}")
|
|
|
|
|
|
print(f"Memory usage: {stats['memory_usage'] / 1024 / 1024:.2f} MB")
|
|
|
|
|
|
|
|
|
|
|
|
# Health check
|
|
|
|
|
|
health = await monitoring.health_check()
|
|
|
|
|
|
if health["status"] == "healthy":
|
|
|
|
|
|
print("✅ Auth system is healthy")
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 Результат архитектуры 2025
|
|
|
|
|
|
|
|
|
|
|
|
После внедрения httpOnly cookies:
|
|
|
|
|
|
- ✅ **OAuth**: Google/GitHub → httpOnly cookie → GraphQL запросы
|
|
|
|
|
|
- ✅ **Email/Password**: Login form → httpOnly cookie → GraphQL запросы
|
|
|
|
|
|
- ✅ **Единая архитектура**: Все через cookies + `credentials: 'include'`
|
|
|
|
|
|
- ✅ **Максимальная безопасность**: Защита от XSS и CSRF для всех типов авторизации
|
|
|
|
|
|
- ✅ **Простота**: Браузер автоматически управляет токенами
|