v1.3 - client and admin scaffolding

This commit is contained in:
2026-04-25 22:51:36 +12:00
parent bc211ffcc8
commit 8cf9bfb441
54 changed files with 8882 additions and 1248 deletions
+50
View File
@@ -0,0 +1,50 @@
from __future__ import annotations
import base64
import hashlib
import hmac
import json
import time
from typing import Any
from fastapi import HTTPException, status
from app.core.config import settings
def _encode(data: dict[str, Any]) -> str:
raw = json.dumps(data, separators=(",", ":"), sort_keys=True).encode("utf-8")
return base64.urlsafe_b64encode(raw).decode("utf-8").rstrip("=")
def _decode(value: str) -> dict[str, Any]:
padding = "=" * (-len(value) % 4)
raw = base64.urlsafe_b64decode(f"{value}{padding}".encode("utf-8"))
return json.loads(raw.decode("utf-8"))
def _sign(value: str) -> str:
signature = hmac.new(settings.auth_secret.encode("utf-8"), value.encode("utf-8"), hashlib.sha256).digest()
return base64.urlsafe_b64encode(signature).decode("utf-8").rstrip("=")
def issue_token(payload: dict[str, Any], ttl_seconds: int = 60 * 60 * 12) -> str:
body = {**payload, "exp": int(time.time()) + ttl_seconds}
encoded = _encode(body)
return f"{encoded}.{_sign(encoded)}"
def verify_token(token: str) -> dict[str, Any]:
try:
body, signature = token.split(".", 1)
except ValueError as exc:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid authentication token") from exc
expected_signature = _sign(body)
if not hmac.compare_digest(signature, expected_signature):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid authentication token")
payload = _decode(body)
if int(payload.get("exp", 0)) < int(time.time()):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Authentication token has expired")
return payload