feat(auth): one-time login links, JWT + refresh, roles, service token, tests

This commit is contained in:
apuc committed 2026-09-26 19:52:32 +03:00
1 parent 4a610ba94a
commit 049b679654
12 files changed
+553 -1

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ class Settings(BaseSettings):
# CORS
cors_origins: list[str] = ["https://opora.my-dpr.ru"]
frontend_base_url: str = "https://opora.my-dpr.ru"
# MinIO / S3
s3_endpoint: str = "http://minio:9000"
+36
View File
@@ -0,0 +1,36 @@
"""Утилиты безопасности: JWT и хеширование токенов."""
import hashlib
import secrets
from datetime import datetime, timedelta, timezone
from jose import jwt
from app.core.config import settings
def create_access_token(user_id: int, session_id: str) -> str:
"""Создать access-токен (JWT)."""
now = datetime.now(timezone.utc)
payload = {
"sub": str(user_id),
"sid": session_id,
"type": "access",
"iat": int(now.timestamp()),
"exp": int((now + timedelta(days=settings.access_token_ttl_days)).timestamp()),
}
return jwt.encode(payload, settings.jwt_secret, algorithm=settings.jwt_algorithm)
def decode_access_token(token: str) -> dict:
"""Декодировать и проверить access-токен."""
return jwt.decode(token, settings.jwt_secret, algorithms=[settings.jwt_algorithm])
def generate_opaque_token() -> str:
"""Сгенерировать случайный opaque-токен (refresh, одноразовая ссылка)."""
return secrets.token_urlsafe(48)
def hash_token(token: str) -> str:
"""SHA-256 хеш токена (для хранения в БД)."""
return hashlib.sha256(token.encode()).hexdigest()