- Add definitions.md: normative terminology disambiguation (Interface, Service, Transport, Token, Identity, Domain, Scope, CredentialProvider, etc.) - Add credentials.md: CredentialProvider trait and CredentialSet enum for outbound auth, mirroring IdentityProvider pattern for inbound auth - Rewrite interface.md: StreamInterface/MessageInterface split (ADR-035), InterfaceRequest/InterfaceResponse, HttpInterface/DnsInterface stubs, ListenerConfig with Stream/Http/Dns variants, credential presentation table - Update auth.md: API keys in DynamicConfig (ADR-037), credential presentation per (Transport, Interface) pair, ApiKeyEntry struct in AuthPolicy - Update configuration.md: API keys, ListenerConfig with Http/Dns variants, expanded TOML config examples - Update call-protocol.md: resolve OQ-IF-01 (InterfaceEvent carries EventEnvelope + Identity), add MessageInterface awareness to protocol adapter layer - Update overview.md: three-layer model now includes StreamInterface/ MessageInterface, CredentialProvider/CredentialSet exports, definitions.md reference, ADRs 035-037 - Update open-questions.md: resolve OQ-IF-01, OQ-IF-02, add OQ-P2-01 through OQ-P2-04, add OQ-CP-01 through OQ-CP-04, add OQ-DEF-01, OQ-DEF-03, OQ-DEF-08 - Update README.md: add definitions.md, credentials.md, ADRs 035-037, phase2 research docs, current state description Key architectural decisions: - ADR-035: StreamInterface/MessageInterface split (two Layer 2 traits) - ADR-036: CredentialProvider as core type (outbound auth, alknet_core::credentials) - ADR-037: API keys as DynamicConfig auth (hash-verified bearer tokens)
3.4 KiB
ADR-037: API Keys as DynamicConfig Auth
Status
Accepted
Context
Alknet's token auth uses Ed25519-signed AuthTokens — the same key material
used for SSH auth. This is appropriate for interactive clients (browsers, CLI)
that can generate and sign Ed25519 key pairs.
But for service accounts, automation, and simple integrations, Ed25519 key pairs are inconvenient. A dashboard backend, a CI/CD pipeline, or a monitoring script needs a simple bearer token that can be stored in an environment variable or config file without managing cryptographic key pairs.
The HTTP interface (Phase 2+) requires bearer token auth for Authorization: Bearer <token> headers. AuthToken works but requires client-side Ed25519
signing. API keys offer a simpler alternative: short bearer tokens verified by
SHA-256 hash lookup, with optional scope restrictions and TTL.
Decision
Add [[auth.api_keys]] section to DynamicConfig:
[[auth.api_keys]]
prefix = "alk_"
hash = "sha256:abc..."
scopes = ["relay:connect", "secrets:derive"]
description = "dashboard service account"
ttl = "30d" # optional
ConfigIdentityProvider::resolve_from_token() handles both token types:
- If the input starts with the configured prefix (default
alk_), treat it as an API key: hash it with SHA-256 and look up the hash in theapi_keystable. - Otherwise, treat it as an
AuthToken: decode, verify Ed25519 signature, check timestamp, resolve fromauthorized_keys.
Both paths produce the same Identity result. In database-backed deployments,
both resolve to the same account UUID.
API keys are stored as SHA-256 hashes (like password hashing — the cleartext key is never stored, only its hash). The prefix enables O(1) routing between AuthToken and API key verification without trying both paths.
The full key is provided to the client exactly once (at creation time). Subsequent verifications only compare hashes.
Consequences
Positive: Simple bearer token auth for HTTP and other non-SSH interfaces. No cryptographic key management for service accounts. Consistent with industry practice (Stripe, GitHub, AWS all use prefixed API keys).
Positive: Both AuthTokens and API keys go through resolve_from_token().
The caller doesn't need to know which type they're using. This keeps the
authentication layer unified.
Positive: Scoped API keys enable fine-grained access control for service
accounts. A monitoring tool gets ["monitoring:read"], not full access.
Negative: API keys are bearer tokens — anyone who obtains the key has the associated permissions. The hash storage and optional TTL mitigate but do not eliminate this risk. Ed25519 AuthTokens remain the preferred auth method for interactive clients.
Negative: API key rotation requires updating DynamicConfig (or the
api_keys database table). The ConfigReloadHandle / ConfigService reload
mechanism handles this, but it's a deliberate operation, not automatic.
Negative: No rate limiting on API key verification is built into this ADR. Rate limiting on the HTTP interface is a separate concern.
References
- ADR-023 (unified auth, shared key material)
- ADR-029 (Identity as core type)
- ADR-030 (static/dynamic config split)
- auth.md — Token auth, AuthPolicy, API keys
- configuration.md — DynamicConfig, AuthPolicy
- research/phase2/interface-model.md — API keys in config