paulhemb's picture
Update auth.py
8404765 verified
Raw History Blame Contribute Delete
2.64 kB
import jwt
import requests
from fastapi import HTTPException, Security, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from supabase_client import supabase_db
from config import SUPABASE_URL, SUPABASE_JWT_SECRET
import logging
logger = logging.getLogger(__name__)
security = HTTPBearer()
# Cache for JWKS client
_jwks_client = None
def get_jwks_client():
global _jwks_client
if _jwks_client is None:
jwks_url = f"{SUPABASE_URL}/auth/v1/.well-known/jwks.json"
_jwks_client = jwt.PyJWKClient(jwks_url)
return _jwks_client
async def get_current_user(credentials: HTTPAuthorizationCredentials = Security(security)):
token = credentials.credentials
try:
# First attempt: decode using HS256 with the JWT secret
try:
payload = jwt.decode(
token,
SUPABASE_JWT_SECRET,
algorithms=["HS256"],
audience="authenticated"
)
logger.info("Token verified with HS256")
except jwt.InvalidTokenError as hs_error:
# If HS256 fails, try RS256/ES256 using the JWKS
logger.info(f"HS256 failed: {hs_error}, trying JWKS...")
jwks_client = get_jwks_client()
signing_key = jwks_client.get_signing_key_from_jwt(token)
payload = jwt.decode(
token,
signing_key.key,
algorithms=["RS256", "ES256"],
audience="authenticated",
options={"verify_aud": True}
)
logger.info("Token verified with JWKS (RS256/ES256)")
user_id = payload.get("sub")
if not user_id:
raise HTTPException(status_code=401, detail="Invalid token: missing subject")
# Fetch user profile from Supabase (service client bypasses RLS)
profile = supabase_db.table("profiles").select("*").eq("id", user_id).execute()
if not profile.data:
raise HTTPException(status_code=404, detail="User profile not found")
return {
"id": user_id,
"email": payload.get("email"),
"profile": profile.data[0]
}
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Token expired")
except jwt.InvalidTokenError as e:
logger.error(f"Token decode error: {e}")
raise HTTPException(status_code=401, detail=f"Invalid authentication: {e}")
except Exception as e:
logger.error(f"Unexpected error in auth: {e}")
raise HTTPException(status_code=401, detail="Authentication failed")