from __future__ import annotations import hmac from datetime import datetime, timedelta, timezone from typing import Any import jwt from fastapi import Depends, HTTPException, Request from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from server.settings import settings _bearer = HTTPBearer(auto_error=False) ALGORITHM = "HS256" def verify_pin(pin: str) -> bool: return hmac.compare_digest(pin.strip(), settings.app_pin.strip()) def create_token() -> str: expire = datetime.now(timezone.utc) + timedelta(days=settings.jwt_expire_days) payload = {"sub": "user", "exp": expire} return jwt.encode(payload, settings.jwt_secret, algorithm=ALGORITHM) def decode_token(token: str) -> dict[str, Any]: try: return jwt.decode(token, settings.jwt_secret, algorithms=[ALGORITHM]) except jwt.PyJWTError as exc: raise HTTPException(status_code=401, detail="Invalid token") from exc async def require_auth( creds: HTTPAuthorizationCredentials | None = Depends(_bearer), ) -> dict[str, Any]: if creds is None or creds.scheme.lower() != "bearer": raise HTTPException(status_code=401, detail="Missing token") return decode_token(creds.credentials)