feat: simplify auth flow - replace JWT with session cookies
Replace complex JWT + refresh token authentication with simple session-based auth using signed cookies. **Removed:** - JWT token service (jwt_service.py) - Refresh token store (refresh_store.py) - Refresh token model and database table - JWKS fetching and OIDC token verification - python-jose dependency **Added:** - Session service (session.py) with HMAC-SHA256 signed cookies - Auth dependencies module for shared auth logic - Session-based auth endpoints **Updated:** - All API endpoints to use session-based auth - Config: removed JWT settings, added SESSION_SECRET/SESSION_TTL_HOURS - Tests: rewritten for session-based flow - Frontend: no changes needed (already uses cookies) Quality gates: ruff ✓, mypy ✓, typecheck ✓, lint ✓
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import uuid
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Cookie, Depends, HTTPException, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.auth.session import decode_session_cookie
|
||||
from src.config import Settings
|
||||
from src.database import SessionLocal
|
||||
from src.models.user import User
|
||||
|
||||
|
||||
async def get_db_session():
|
||||
async with SessionLocal() as session:
|
||||
yield session
|
||||
|
||||
|
||||
async def get_current_user_id(
|
||||
session_cookie: Annotated[str | None, Cookie()] = None,
|
||||
) -> uuid.UUID:
|
||||
if not session_cookie:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="missing session")
|
||||
|
||||
settings = Settings()
|
||||
try:
|
||||
payload = decode_session_cookie(settings=settings, cookie_value=session_cookie)
|
||||
return uuid.UUID(str(payload["user_id"]))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid session")
|
||||
|
||||
|
||||
async def get_current_user(
|
||||
session_cookie: Annotated[str | None, Cookie()] = None,
|
||||
db_session: AsyncSession = Depends(get_db_session),
|
||||
) -> User:
|
||||
if not session_cookie:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="missing session")
|
||||
|
||||
settings = Settings()
|
||||
try:
|
||||
payload = decode_session_cookie(settings=settings, cookie_value=session_cookie)
|
||||
user_id = uuid.UUID(str(payload["user_id"]))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid session")
|
||||
|
||||
user = await db_session.get(User, user_id)
|
||||
if user is None:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="user not found")
|
||||
return user
|
||||
Reference in New Issue
Block a user