Source code for qfa.auth
"""Authentication utilities for API key validation."""
import secrets
from qfa.domain.errors import AuthenticationError
from qfa.domain.models import TenantApiKey
[docs]
def validate_api_key(
provided_key: str,
api_keys: list[TenantApiKey],
) -> TenantApiKey:
"""Validate a provided API key against the loaded keys.
Uses ``secrets.compare_digest`` for constant-time comparison.
Compares against **all** keys to avoid timing attacks.
Parameters
----------
provided_key : str
The API key value supplied by the caller.
api_keys : list[TenantApiKey]
The loaded set of valid API keys.
Returns
-------
TenantApiKey
The matching tenant API key.
Raises
------
AuthenticationError
If no loaded key matches *provided_key*.
"""
match: TenantApiKey | None = None
for api_key in api_keys:
if secrets.compare_digest(provided_key, api_key.key.get_secret_value()):
match = api_key
if match is None:
raise AuthenticationError("Invalid API key")
return match