Interface IApiKeyStore
- Namespace
- Stratara.Abstractions.ApiKeys
- Assembly
- Stratara.Abstractions.dll
Issues, validates, and revokes API keys — the machine-to-machine authentication plane. Keys are stored hashed (never in plaintext) and flow through the same membership/permission plane as human sign-ins: a machine key acts as its own actor with tenant-scoped roles, a personal access token acts as its bound user.
public interface IApiKeyStore
- Extension Methods
Remarks
Fail-closed validation: unknown, revoked, and expired keys all return null. The
erasure sweeps (RemoveAllForTenantAsync(Guid, CancellationToken), RemoveAllForUserAsync(Guid, CancellationToken))
exist so tenant- and user-erasure flows can clear the key plane in one call.
Methods
GetForTenantAsync(Guid, CancellationToken)
Lists the tenant's keys (descriptors only — raw keys are unrecoverable).
Task<IReadOnlyList<ApiKeyDescriptor>> GetForTenantAsync(Guid tenantId, CancellationToken cancellationToken = default)
Parameters
tenantIdGuidThe tenant whose keys to list.
cancellationTokenCancellationTokenToken to observe while listing.
Returns
- Task<IReadOnlyList<ApiKeyDescriptor>>
The tenant's keys; empty when none exist.
ImportAsync(ApiKeyImportRequest, CancellationToken)
Stores a machine key whose raw value the caller already holds — for setups where the key must be known before the store exists: container orchestration, CI provisioning, self-hosted bundles, end-to-end test hosts. Idempotent, so it can run on every boot.
Task<ApiKeyDescriptor> ImportAsync(ApiKeyImportRequest request, CancellationToken cancellationToken = default)
Parameters
requestApiKeyImportRequestThe import parameters, including the raw key.
cancellationTokenCancellationTokenToken to observe while importing.
Returns
- Task<ApiKeyDescriptor>
The stored descriptor — newly created, or the existing one on a repeat import.
Remarks
The supplied value must match ApiKeyFormat — generate it with CreateRawKey(). The shape requirement is load-bearing: stores keep the key's digest unsalted because a generated key carries 256 bits of entropy, and a hand-picked value would quietly invalidate that.
Importing a value that is already stored is a no-op that returns the existing descriptor. The stored key is never mutated — a differing name, role set, or expiry leaves the stored key as it is, so a changed configuration can neither escalate a key's roles nor extend its life unnoticed. Compare the returned descriptor when that matters. Nothing about the "shown once" guarantee of IssueAsync(ApiKeyIssueRequest, CancellationToken) changes: import returns no raw key, because the caller already has it.
Exceptions
- ArgumentException
The raw key does not match the canonical format, or the name is empty.
- InvalidOperationException
The key value is already stored for a different tenant, as a personal access token, or in a revoked or expired state — none of which an import may silently adopt.
IssueAsync(ApiKeyIssueRequest, CancellationToken)
Issues a new key. The returned RawKey is shown once and never persisted. Personal access tokens (a bound user) require the user to hold an active membership in the target tenant.
Task<IssuedApiKey> IssueAsync(ApiKeyIssueRequest request, CancellationToken cancellationToken = default)
Parameters
requestApiKeyIssueRequestThe issuance parameters.
cancellationTokenCancellationTokenToken to observe while issuing.
Returns
- Task<IssuedApiKey>
The raw secret plus the stored descriptor.
Exceptions
- InvalidOperationException
A personal access token was requested for a user without an active membership in the tenant, or roles were supplied for a personal access token.
RemoveAllForTenantAsync(Guid, CancellationToken)
Removes every key bound to the tenant — the key-plane step of a tenant-erasure sweep.
Task RemoveAllForTenantAsync(Guid tenantId, CancellationToken cancellationToken = default)
Parameters
tenantIdGuidThe tenant whose keys to remove.
cancellationTokenCancellationTokenToken to observe while removing.
Returns
RemoveAllForUserAsync(Guid, CancellationToken)
Removes every personal access token bound to the user — the key-plane step of a user-erasure sweep.
Task RemoveAllForUserAsync(Guid userId, CancellationToken cancellationToken = default)
Parameters
userIdGuidThe user whose personal access tokens to remove.
cancellationTokenCancellationTokenToken to observe while removing.
Returns
RevokeAsync(Guid, CancellationToken)
Revokes a key; it never validates again.
Task RevokeAsync(Guid apiKeyId, CancellationToken cancellationToken = default)
Parameters
apiKeyIdGuidThe key to revoke.
cancellationTokenCancellationTokenToken to observe while revoking.
Returns
ValidateAsync(string, CancellationToken)
Validates a presented raw key: hash lookup, then revocation and expiry checks.
Task<ApiKeyDescriptor?> ValidateAsync(string rawKey, CancellationToken cancellationToken = default)
Parameters
rawKeystringThe presented plaintext key.
cancellationTokenCancellationTokenToken to observe while validating.
Returns
- Task<ApiKeyDescriptor>
The key's descriptor, or
nullfor unknown/revoked/expired keys.