-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.py
More file actions
58 lines (45 loc) · 1.8 KB
/
Copy pathauth.py
File metadata and controls
58 lines (45 loc) · 1.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
"""
auth.py — API key authentication for all protected routes.
How it works:
- Client sends header: X-API-Key: <your-key>
- FastAPI checks it against the API_KEY env var
- Missing or wrong key → 403 Forbidden
- Correct key → request proceeds
Setup:
1. Set API_KEY in Render environment variables (or .env locally)
2. Add `dependencies=[Depends(verify_api_key)]` to any route or the whole app
The health check endpoint is intentionally left unprotected so load
balancers and uptime monitors can ping it without credentials.
"""
import os
import secrets
from fastapi import Security, HTTPException, status
from fastapi.security import APIKeyHeader
API_KEY_NAME = "X-API-Key"
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
# Read from environment — set this in Render dashboard or .env
_API_KEY = os.getenv("API_KEY", "")
def verify_api_key(api_key: str = Security(api_key_header)) -> str:
"""
FastAPI dependency — inject into any route to require authentication.
Usage:
@app.post("/predict", dependencies=[Depends(verify_api_key)])
def predict(...): ...
If API_KEY env var is not set, auth is disabled (useful for local dev
without a key configured). A warning is logged in that case.
"""
if not _API_KEY:
# No key configured — allow all requests (local dev mode)
return "no-auth"
if not api_key:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Missing API key. Add X-API-Key header.",
)
# Use secrets.compare_digest to prevent timing attacks
if not secrets.compare_digest(api_key, _API_KEY):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid API key.",
)
return api_key