All checks were successful
Deploy on push / deploy (push) Successful in 5m47s
- **🔍 Comprehensive authentication documentation refactoring**: Полная переработка документации аутентификации
- Обновлена таблица содержания в README.md
- Исправлены архитектурные диаграммы - токены хранятся только в Redis
- Добавлены практические примеры кода для микросервисов
- Консолидирована OAuth документация
12 KiB
12 KiB
Система авторизации Discours Core
🎯 Обзор архитектуры
Модульная система авторизации с JWT токенами, Redis-сессиями и OAuth интеграцией. Построена на принципах разделения ответственности и высокой производительности.
auth/
├── tokens/ # 🎯 Система управления токенами
│ ├── sessions.py # JWT сессии с Redis
│ ├── verification.py # Одноразовые токены
│ ├── oauth.py # OAuth токены
│ ├── batch.py # Массовые операции
│ ├── monitoring.py # Мониторинг и статистика
│ ├── storage.py # Фасад для совместимости
│ ├── base.py # Базовые классы
│ └── types.py # Типы и константы
├── middleware.py # HTTP middleware
├── decorators.py # GraphQL декораторы
├── oauth.py # OAuth провайдеры
├── identity.py # Методы идентификации
├── jwtcodec.py # JWT кодек
├── validations.py # Валидация данных
├── credentials.py # Креденшиалы
├── exceptions.py # Исключения
└── utils.py # Утилиты
🎯 Система токенов
SessionTokenManager
Принцип работы:
- JWT токены с payload
{user_id, username, iat, exp} - Redis хранение для отзыва и управления жизненным циклом
- Поддержка множественных сессий на пользователя
- Автоматическое обновление
last_activityпри активности
Redis структура:
session:{user_id}:{token} # hash с данными сессии
user_sessions:{user_id} # set с активными токенами
Основные методы:
from auth.tokens.sessions import SessionTokenManager
sessions = SessionTokenManager()
# Создание сессии
token = await sessions.create_session(user_id, username=username)
# Проверка сессии
payload = await sessions.verify_session(token)
# Обновление сессии
new_token = await sessions.refresh_session(user_id, old_token)
# Отзыв сессии
await sessions.revoke_session_token(token)
# Получение всех сессий пользователя
user_sessions = await sessions.get_user_sessions(user_id)
Типы токенов
| Тип | TTL | Назначение | Менеджер |
|---|---|---|---|
session |
30 дней | JWT сессии пользователей | SessionTokenManager |
verification |
1 час | Одноразовые токены подтверждения | VerificationTokenManager |
oauth_access |
1 час | OAuth access токены | OAuthTokenManager |
oauth_refresh |
30 дней | OAuth refresh токены | OAuthTokenManager |
Менеджеры токенов
1. SessionTokenManager - JWT сессии
from auth.tokens.sessions import SessionTokenManager
sessions = SessionTokenManager()
# Создание сессии
token = await sessions.create_session(
user_id="123",
auth_data={"provider": "local"},
username="john_doe",
device_info={"ip": "192.168.1.1", "user_agent": "Mozilla/5.0"}
)
# Создание JWT токена сессии
token = await sessions.create_session_token(
user_id="123",
token_data={"username": "john_doe", "device_info": "..."}
)
# Проверка сессии (совместимость с TokenStorage)
payload = await sessions.verify_session(token)
# Возвращает: {"user_id": "123", "username": "john_doe", "iat": 1640995200, "exp": 1643587200}
# Валидация токена сессии
valid, data = await sessions.validate_session_token(token)
# Получение данных сессии
session_data = await sessions.get_session_data(token, user_id)
# Обновление сессии
new_token = await sessions.refresh_session(user_id, old_token, device_info)
# Отзыв сессии
await sessions.revoke_session_token(token)
# Отзыв всех сессий пользователя
revoked_count = await sessions.revoke_user_sessions(user_id)
# Получение всех сессий пользователя
user_sessions = await sessions.get_user_sessions(user_id)
2. VerificationTokenManager - Одноразовые токены
from auth.tokens.verification import VerificationTokenManager
verification = VerificationTokenManager()
# Создание токена подтверждения email
token = await verification.create_verification_token(
user_id="123",
verification_type="email_change",
data={"new_email": "new@example.com"},
ttl=3600 # 1 час
)
# Проверка токена
valid, data = await verification.validate_verification_token(token)
# Подтверждение (одноразовое использование)
confirmed_data = await verification.confirm_verification_token(token)
3. OAuthTokenManager - OAuth токены
from auth.tokens.oauth import OAuthTokenManager
oauth = OAuthTokenManager()
# Сохранение OAuth токенов
await oauth.store_oauth_tokens(
user_id="123",
provider="google",
access_token="ya29.a0AfH6SM...",
refresh_token="1//04...",
expires_in=3600,
additional_data={"scope": "read write"}
)
# Создание OAuth токена (внутренний метод)
token_key = await oauth._create_oauth_token(
user_id="123",
token_data={"token": "ya29.a0AfH6SM...", "provider": "google"},
ttl=3600,
provider="google",
token_type="oauth_access"
)
# Получение access токена
access_data = await oauth.get_token(user_id, "google", "oauth_access")
# Оптимизированное получение OAuth данных
oauth_data = await oauth._get_oauth_data_optimized("oauth_access", "123", "google")
# Отзыв OAuth токенов
await oauth.revoke_oauth_tokens(user_id, "google")
# Оптимизированный отзыв токена
revoked = await oauth._revoke_oauth_token_optimized("oauth_access", "123", "google")
# Отзыв всех OAuth токенов пользователя
revoked_count = await oauth.revoke_user_oauth_tokens(user_id, "oauth_access")
4. BatchTokenOperations - Массовые операции
from auth.tokens.batch import BatchTokenOperations
batch = BatchTokenOperations()
# Массовая проверка токенов
tokens = ["token1", "token2", "token3"]
results = await batch.batch_validate_tokens(tokens)
# {"token1": True, "token2": False, "token3": True}
# Валидация батча токенов (внутренний метод)
batch_results = await batch._validate_token_batch(tokens)
# Безопасное декодирование токена
payload = await batch._safe_decode_token(token)
# Массовый отзыв токенов
revoked_count = await batch.batch_revoke_tokens(tokens)
# Отзыв батча токенов (внутренний метод)
batch_revoked = await batch._revoke_token_batch(tokens)
# Очистка истекших токенов
cleaned_count = await batch.cleanup_expired_tokens()
5. TokenMonitoring - Мониторинг
from auth.tokens.monitoring import TokenMonitoring
monitoring = TokenMonitoring()
# Статистика токенов
stats = await monitoring.get_token_statistics()
# {
# "session_tokens": 150,
# "verification_tokens": 5,
# "oauth_access_tokens": 25,
# "oauth_refresh_tokens": 25,
# "memory_usage": 1048576
# }
# Подсчет ключей по паттерну (внутренний метод)
count = await monitoring._count_keys_by_pattern("session:*")
# Health check
health = await monitoring.health_check()
# {"status": "healthy", "redis_connected": True, "token_count": 205}
# Оптимизация памяти
optimization = await monitoring.optimize_memory_usage()
# {"cleaned_expired": 10, "memory_freed": 102400}
# Оптимизация структур данных (внутренний метод)
optimized = await monitoring._optimize_data_structures()
TokenStorage (Фасад для совместимости)
from auth.tokens.storage import TokenStorage
# Упрощенный API для основных операций
await TokenStorage.create_session(user_id, username=username)
await TokenStorage.verify_session(token)
await TokenStorage.refresh_session(user_id, old_token, device_info)
await TokenStorage.revoke_session(token)
🔧 Middleware и декораторы
AuthMiddleware
from auth.middleware import AuthMiddleware
# Автоматическая обработка токенов
middleware = AuthMiddleware()
# Извлечение токена из запроса
token = await extract_token_from_request(request)
# Проверка сессии
payload = await sessions.verify_session(token)
GraphQL декораторы
from auth.decorators import auth_required, permission_required
@auth_required
async def protected_resolver(info, **kwargs):
"""Требует авторизации"""
user = info.context.get('user')
return f"Hello, {user.username}!"
@permission_required("shout:create")
async def create_shout(info, input_data):
"""Требует права на создание публикаций"""
pass
ORM модели
Author (Пользователь)
class Author:
id: int
email: str
name: str
slug: str
password: Optional[str] # bcrypt hash
pic: Optional[str] # URL аватара
bio: Optional[str]
email_verified: bool
phone_verified: bool
created_at: int
updated_at: int
last_seen: int
# OAuth данные в JSON формате
oauth: Optional[dict] # {"google": {"id": "123", "email": "user@gmail.com"}}
# Поля аутентификации
failed_login_attempts: int
account_locked_until: Optional[int]
OAuth данные
OAuth данные хранятся в JSON поле oauth модели Author:
# Формат oauth поля
{
"google": {
"id": "123456789",
"email": "user@gmail.com",
"name": "John Doe"
},
"github": {
"id": "456789",
"login": "johndoe",
"email": "user@github.com"
}
}
⚙️ Конфигурация
Переменные окружения
# JWT настройки
JWT_SECRET=your_super_secret_key
JWT_EXPIRATION_HOURS=720 # 30 дней
# Redis подключение
REDIS_URL=redis://localhost:6379/0
# 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
FACEBOOK_APP_ID=your_facebook_app_id
FACEBOOK_APP_SECRET=your_facebook_app_secret
VK_APP_ID=your_vk_app_id
VK_APP_SECRET=your_vk_app_secret
YANDEX_CLIENT_ID=your_yandex_client_id
YANDEX_CLIENT_SECRET=your_yandex_client_secret
# Session cookies
SESSION_COOKIE_NAME=session_token
SESSION_COOKIE_SECURE=true
SESSION_COOKIE_HTTPONLY=true
SESSION_COOKIE_SAMESITE=lax
SESSION_COOKIE_MAX_AGE=2592000 # 30 дней
# Frontend
FRONTEND_URL=https://yourdomain.com
Производительность
Оптимизации Redis
- Pipeline операции для атомарности
- Batch обработка токенов (100-1000 за раз)
- SCAN вместо KEYS для безопасности
- TTL автоматическая очистка
Кэширование
- @lru_cache для часто используемых ключей
- Connection pooling для Redis
- JWT decode caching в middleware