Had an interesting realization while building some microservices: API keys are kind of terrible for service-to-service auth.

The problems everyone knows about: keys get committed to repos, rotated inconsistently, stored in plaintext, shared in Slack DMs. But the deeper issue is that an API key doesn’t prove anything about the caller — it just proves they have the key.

I’ve been experimenting with challenge-response auth using LNURL-auth (from the Lightning/Bitcoin ecosystem, but the pattern works independently). The flow:

  1. Service B presents a challenge (random string)
  2. Service A signs the challenge with a key derived specifically for Service B
  3. Service B verifies the signature
  4. No shared secret ever crosses the wire

The per-service key derivation is the interesting part. Service A derives a unique key for each service it talks to from a single root key. So Service B sees a stable identity for Service A, but can’t link A’s identity across services. If Service B gets compromised, you revoke that one derived key — root identity stays intact.

It’s basically what client certificates do but without the CA infrastructure overhead. Anyone explored similar patterns? The LNURL-auth spec is surprisingly simple if you strip away the Bitcoin-specific parts.