Root cause: Auth middleware was commented out on game detail page ([id].vue), causing SSR to render without checking authentication. Safari's client-side auth check wasn't reaching the backend due to caching behavior, resulting in "Auth: Failed" display. Changes: - Re-enabled middleware: ['auth'] in pages/games/[id].vue - Added /api/auth/ws-token endpoint for Safari WebSocket fallback - Added expires_minutes param to create_token() for short-lived tokens - Added token query param support to WebSocket handlers - Updated SAFARI_WEBSOCKET_ISSUE.md documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
54 lines
1.3 KiB
Python
54 lines
1.3 KiB
Python
import logging
|
|
from typing import Any
|
|
|
|
import pendulum
|
|
from jose import JWTError, jwt
|
|
|
|
from app.config import get_settings
|
|
|
|
logger = logging.getLogger(f"{__name__}.auth")
|
|
|
|
settings = get_settings()
|
|
|
|
|
|
def create_token(user_data: dict[str, Any], expires_minutes: int | None = None) -> str:
|
|
"""
|
|
Create JWT token for user
|
|
|
|
Args:
|
|
user_data: User information to encode in token
|
|
expires_minutes: Optional expiration in minutes. If None, defaults to 7 days.
|
|
|
|
Returns:
|
|
JWT token string
|
|
"""
|
|
if expires_minutes is not None:
|
|
expiration = pendulum.now("UTC").add(minutes=expires_minutes).int_timestamp
|
|
else:
|
|
expiration = pendulum.now("UTC").add(days=7).int_timestamp
|
|
|
|
payload = {**user_data, "exp": expiration}
|
|
token = jwt.encode(payload, settings.secret_key, algorithm="HS256")
|
|
return token
|
|
|
|
|
|
def verify_token(token: str) -> dict[str, Any]:
|
|
"""
|
|
Verify and decode JWT token
|
|
|
|
Args:
|
|
token: JWT token string
|
|
|
|
Returns:
|
|
Decoded token payload
|
|
|
|
Raises:
|
|
JWTError: If token is invalid or expired
|
|
"""
|
|
try:
|
|
payload = jwt.decode(token, settings.secret_key, algorithms=["HS256"])
|
|
return payload
|
|
except JWTError as e:
|
|
logger.warning(f"Invalid token: {e}")
|
|
raise
|