"""Admin auth: bcrypt-less password check + JWT issuance and verification.""" import os from datetime import datetime, timedelta, timezone import jwt from fastapi import Header, HTTPException ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "admin") JWT_SECRET = os.environ.get("JWT_SECRET", "dev-secret-change-me") JWT_ALGO = "HS256" TOKEN_TTL_HOURS = int(os.environ.get("JWT_TTL_HOURS", "24")) def issue_token() -> str: payload = { "sub": "admin", "iat": datetime.now(timezone.utc), "exp": datetime.now(timezone.utc) + timedelta(hours=TOKEN_TTL_HOURS), } return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGO) def verify_token(token: str) -> bool: try: jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGO]) return True except Exception: return False async def require_auth(authorization: str = Header(default=None)): if not authorization or not authorization.lower().startswith("bearer "): raise HTTPException(status_code=401, detail="Missing bearer token") token = authorization.split(" ", 1)[1].strip() if not verify_token(token): raise HTTPException(status_code=401, detail="Invalid or expired token") return True