diff --git a/src/api.py b/src/api.py index f6f0945..bd029b9 100644 --- a/src/api.py +++ b/src/api.py @@ -1,12 +1,16 @@ import requests -from fastapi import FastAPI +from fastapi import Depends, FastAPI from fastapi.responses import ORJSONResponse, RedirectResponse from fastapi.middleware.cors import CORSMiddleware +from src.auth import verify_token from src.scraper import fide_scraper -app = FastAPI(default_response_class=ORJSONResponse) +app = FastAPI( + default_response_class=ORJSONResponse, + dependencies=[Depends(verify_token)], +) app.add_middleware( CORSMiddleware, diff --git a/src/auth.py b/src/auth.py new file mode 100644 index 0000000..a7d36d5 --- /dev/null +++ b/src/auth.py @@ -0,0 +1,34 @@ +import os +import secrets + +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer + +API_TOKENS: set[str] = set() + +_tokens_env = os.environ.get("API_TOKENS", "") +if _tokens_env: + API_TOKENS = {token.strip() for token in _tokens_env.split(",") if token.strip()} + +security = HTTPBearer(auto_error=False) + + +def verify_token(credentials: HTTPAuthorizationCredentials | None = Depends(security)) -> None: + if not API_TOKENS: + return + + if credentials is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Missing authentication token", + headers={"WWW-Authenticate": "Bearer"}, + ) + + token = credentials.credentials + + if not any(secrets.compare_digest(token, valid_token) for valid_token in API_TOKENS): + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid authentication token", + headers={"WWW-Authenticate": "Bearer"}, + )