Table of Contents

Class ApiKeyAuthenticator

Namespace
MailFathom.Infrastructure.Security.ApiKeys
Assembly
MailFathom.Infrastructure.dll

Judges the credential an MCP request presented against the API keys a deployment configured.

public sealed class ApiKeyAuthenticator
Inheritance
ApiKeyAuthenticator
Inherited Members

Remarks

The keys are resolved per request rather than cached, which is what the secret machinery already promises everywhere else: material rotated behind an unchanged reference reaches the next operation with no cache to invalidate and no restart to schedule. The schemes that ship today read a local file or an environment variable, and a future network-backed store caches inside its own adapter, so the cost stays where the policy for it lives.

Comparison never touches the material directly. Each side is reduced to an HMAC-SHA-256 digest under a key this process generates at construction and never publishes, and the digests are compared with FixedTimeEquals(ReadOnlySpan<byte>, ReadOnlySpan<byte>). Hashing first is what keeps the length of a presented credential from leaking: a fixed-time comparison is only fixed-time over equal lengths, and comparing raw material would answer "how long is the real key" to anyone willing to time it. The digest key is per process rather than configured, because nothing outside this process ever needs to reproduce a digest.

Every configured key is evaluated, including one already matched and one already expired. Stopping early would make the time a refusal takes depend on where in the list a key sits, and would make an expired key answer faster than an unrecognized one — which is exactly the distinction the single generic refusal exists to hide.

Constructors

ApiKeyAuthenticator(ISecretReferenceResolver, TimeProvider, ILogger<ApiKeyAuthenticator>)

Initializes a new API key authenticator.

Methods

AuthenticateAsync(IReadOnlyList<ConfiguredSecret>, string?, CancellationToken)

Judges the credential an Authorization header carried.