233 lines
8.8 KiB
Markdown
233 lines
8.8 KiB
Markdown
# 🔐 Система аутентификации Discours Core
|
||
|
||
## 📚 Обзор
|
||
|
||
Модульная система аутентификации с **httpOnly cookies**, JWT токенами, Redis-сессиями, OAuth интеграцией и RBAC авторизацией.
|
||
|
||
### 🎯 **Единый подход с httpOnly cookies для ВСЕХ типов авторизации:**
|
||
|
||
- ✅ **OAuth** (Google/GitHub/Yandex/VK) → httpOnly cookie
|
||
- ✅ **Email/Password** → httpOnly cookie
|
||
- ✅ **GraphQL запросы** → `credentials: 'include'`
|
||
- ✅ **Максимальная безопасность** → защита от XSS/CSRF
|
||
|
||
## 🚀 Быстрый старт
|
||
|
||
### Для разработчиков
|
||
|
||
```python
|
||
from auth.tokens.sessions import SessionTokenManager
|
||
from auth.utils import extract_token_from_request
|
||
|
||
# Проверка токена (автоматически из cookie или Bearer заголовка)
|
||
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}")
|
||
```
|
||
|
||
### Для фронтенда
|
||
|
||
```typescript
|
||
// Все запросы используют httpOnly cookies
|
||
const response = await fetch('/graphql', {
|
||
method: 'POST',
|
||
credentials: 'include', // ✅ КРИТИЧНО: отправляет httpOnly cookies
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ query, variables })
|
||
});
|
||
```
|
||
|
||
### Redis ключи для поиска
|
||
|
||
```bash
|
||
# Сессии пользователей
|
||
session:{user_id}:{token} # Данные сессии (hash)
|
||
user_sessions:{user_id} # Список активных токенов (set)
|
||
|
||
# OAuth токены (для API интеграций)
|
||
oauth_access:{user_id}:{provider} # Access токен
|
||
oauth_refresh:{user_id}:{provider} # Refresh токен
|
||
```
|
||
|
||
## 📖 Документация
|
||
|
||
### 🏗️ Архитектура
|
||
- **[Обзор системы](system.md)** - Компоненты и менеджеры токенов
|
||
- **[Архитектура](architecture.md)** - Диаграммы и потоки данных
|
||
- **[Миграция](migration.md)** - Обновление с предыдущих версий
|
||
|
||
### 🔑 Аутентификация
|
||
- **[Управление сессиями](sessions.md)** - JWT токены и Redis хранение
|
||
- **[OAuth интеграция](oauth.md)** - Социальные провайдеры с httpOnly cookies
|
||
- **[Микросервисы](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)** - Схема данных и кеширование
|
||
|
||
## 🔄 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');
|
||
}
|
||
```
|
||
|
||
## 🔍 Для микросервисов
|
||
|
||
### Подключение к 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
|
||
# Извлечение токена из запроса (cookie или Bearer)
|
||
from auth.utils import extract_token_from_request
|
||
|
||
token = await extract_token_from_request(request)
|
||
# Автоматически проверяет:
|
||
# 1. Authorization: Bearer <token>
|
||
# 2. Cookie: session_token=<token>
|
||
```
|
||
|
||
## 🎯 Основные компоненты
|
||
|
||
- **SessionTokenManager** - JWT сессии с Redis хранением + httpOnly cookies
|
||
- **OAuthTokenManager** - OAuth access/refresh токены для API интеграций
|
||
- **BatchTokenOperations** - Массовые операции с токенами
|
||
- **TokenMonitoring** - Мониторинг и статистика
|
||
- **AuthMiddleware** - HTTP middleware с поддержкой cookies
|
||
|
||
## ⚡ Производительность
|
||
|
||
- **Connection pooling** для Redis
|
||
- **Batch операции** для массовых действий (100-1000 токенов)
|
||
- **Pipeline использование** для атомарности
|
||
- **SCAN** вместо KEYS для безопасности
|
||
- **TTL** автоматическая очистка истекших токенов
|
||
- **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 для всех типов авторизации
|
||
- ✅ **Простота**: Браузер автоматически управляет токенами |