"""API key authentication. Klucz przyjmowany z header `X-API-Key` lub `Authorization: Bearer `. Gdy `settings.api_keys` jest puste — auth jest wyłączony (dev mode). Dodatkowo (anti-tamper): gdy `ALLOWED_APP_SIG_HASH` jest ustawione, każdy request musi zawierać `X-App-Signature` z SHA256 (hex) signing certu APK. Mismatch → 403. Re-packaging APK innym keystorem (debug → release) wykryty natychmiast. """ from __future__ import annotations from fastapi import Header, HTTPException, status from app.config import get_settings def require_api_key( x_api_key: str | None = Header(default=None, alias="X-API-Key"), authorization: str | None = Header(default=None), x_app_signature: str | None = Header(default=None, alias="X-App-Signature"), ) -> None: settings = get_settings() if settings.app_sig_check_enabled: sig = (x_app_signature or "").strip().lower().replace(":", "") if not sig or sig not in settings.allowed_app_sig_hashes: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="invalid or missing app signature", ) if not settings.auth_enabled: return # local/dev — wszystko otwarte candidate: str | None = None if x_api_key: candidate = x_api_key.strip() elif authorization and authorization.lower().startswith("bearer "): candidate = authorization[7:].strip() if not candidate or candidate not in settings.api_keys: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid or missing API key", headers={"WWW-Authenticate": "Bearer"}, )