| 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") |
|
|