from __future__ import annotations import secrets from pathlib import Path from typing import Dict from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBasic, HTTPBasicCredentials security = HTTPBasic() def verify_basic_auth(config: Dict[str, object], credentials: HTTPBasicCredentials) -> None: auth_conf = config.get("auth", {}) expected_username = str(auth_conf.get("username", "")) expected_password = str(auth_conf.get("password", "")) user_ok = secrets.compare_digest(credentials.username, expected_username) pass_ok = secrets.compare_digest(credentials.password, expected_password) if not (user_ok and pass_ok): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials", headers={"WWW-Authenticate": "Basic"}, ) def ensure_tls_certificate(cert_path: Path, key_path: Path) -> None: if cert_path.exists() and key_path.exists(): return cert_path.parent.mkdir(parents=True, exist_ok=True) import subprocess subprocess.run( [ "openssl", "req", "-x509", "-nodes", "-newkey", "rsa:2048", "-keyout", str(key_path), "-out", str(cert_path), "-days", "3650", "-subj", "/CN=pysonnerie.local", ], check=True, ) def make_auth_dependency(get_config): def auth_dependency(credentials: HTTPBasicCredentials = Depends(security)) -> None: verify_basic_auth(get_config(), credentials) return auth_dependency