WIP checkpoint: Address review feedback: Upgrade auth to RS256 signing, age-verification field, refresh-token sessions

This commit is contained in:
2026-08-19 16:40:38 +00:00
committed by coder-bot
parent 478638d4ff
commit 758307bbee
2 changed files with 11 additions and 7 deletions
+2 -3
View File
@@ -26,9 +26,8 @@ class RefreshToken(Base):
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
# RS256 JWTs are ~420+ chars; Text avoids length issues and is fine for # RS256 JWTs are ~420+ chars; 512 is sufficient and matches the migration.
# a UUID-indexed lookup by hash in the future. token = Column(String(512), unique=True, index=True, nullable=False)
token = Column(String, unique=True, index=True, nullable=False)
expires_at = Column(DateTime(timezone=True), nullable=False) expires_at = Column(DateTime(timezone=True), nullable=False)
is_active = Column(Boolean, default=True) is_active = Column(Boolean, default=True)
created_at = Column(DateTime(timezone=True), server_default=func.now()) created_at = Column(DateTime(timezone=True), server_default=func.now())
+9 -4
View File
@@ -1,7 +1,7 @@
"""Authentication router - login, register, token refresh.""" """Authentication router - login, register, token refresh."""
import uuid import uuid
from datetime import datetime, timedelta, timezone from datetime import date, datetime, timedelta, timezone
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordRequestForm
@@ -76,8 +76,13 @@ def _create_access_token(data: dict) -> str:
def _create_refresh_token(data: dict) -> str: def _create_refresh_token(data: dict) -> str:
"""Create a signed refresh token using RS256.""" """Create a signed refresh token using RS256.
Includes a unique ``jti`` claim so that concurrent calls produce
distinct tokens even when issued within the same second.
"""
to_encode = data.copy() to_encode = data.copy()
to_encode["jti"] = str(uuid.uuid4())
expire = datetime.now(timezone.utc) + timedelta( expire = datetime.now(timezone.utc) + timedelta(
days=settings.REFRESH_TOKEN_EXPIRE_DAYS days=settings.REFRESH_TOKEN_EXPIRE_DAYS
) )
@@ -99,7 +104,7 @@ def hash_password(password: str) -> str:
return pwd_context.hash(password) return pwd_context.hash(password)
def calculate_age(birth_date, today=None) -> int: def calculate_age(birth_date: date, today: date | None = None) -> int:
"""Calculate age in years from a birth date. """Calculate age in years from a birth date.
Args: Args:
@@ -174,7 +179,7 @@ async def register(req: RegisterRequest, db: AsyncSession = Depends(get_db)):
date_of_birth=dob, date_of_birth=dob,
) )
db.add(user) db.add(user)
await db.commit() await db.flush() # flush to get user.id before creating refresh token
await db.refresh(user) await db.refresh(user)
# Create access token # Create access token