import os import httpx from fastapi import Depends, HTTPException, Request from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from jose import JWTError, jwt from app.config import settings ALGORITHMS = ["RS256"] class Auth0Bearer(HTTPBearer): async def __call__(self, request: Request) -> str: auth_header = request.headers.get("authorization") token = None if auth_header and auth_header.lower().startswith("bearer "): token = auth_header.split(" ", 1)[1] else: token = request.cookies.get("access_token") if token: try: payload = await verify_jwt(token) return payload except Exception as e: raise HTTPException(status_code=401, detail="Invalid or expired token") else: raise HTTPException(status_code=401, detail="Not authenticated") async def verify_jwt(token: str): jwks_url = f"https://{settings.AUTH0_DOMAIN}/.well-known/jwks.json" async with httpx.AsyncClient() as client: jwks = (await client.get(jwks_url)).json() unverified_header = jwt.get_unverified_header(token) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"], } if rsa_key: try: payload = jwt.decode( token, rsa_key, algorithms=ALGORITHMS, audience=settings.API_AUDIENCE, issuer=f"https://{settings.AUTH0_DOMAIN}/", ) return payload except JWTError: raise HTTPException( status_code=401, detail="Could not validate credentials" ) raise HTTPException(status_code=401, detail="Unable to find appropriate key")