This is a machine-to-machine authentication proposal with the following requirements:
- Avoid replay attacks. Leaked or intercepted auth tokens cannot be reused at all.
- Impersonation resistant. The server shouldn't have any client secrets or password-equivalent data in any form, if compromised.
For reasons why, see this answer.
Registration
Occurs out-of-band.
The client generates an Ed25519 key pair and gives the public key to the server.
The server generates a random key ID and gives this to the client.
Client creates a unique signed auth token for every HTTP request
Increments nonce (monotonically increasing integer).
Signs key ID and nonce with private key.
Auth token = key-id|nonce|sign_Ed25519(key-id|nonce, privateKey)
This auth token is sent as a http header, using HTTPS.
Server verifies auth token
Extracts key ID and nonce from the token.
Gets the stored public key and last_nonce by key ID.
Verifies the signature with the public key.
Checks that nonce > last_nonce.
If successful, saves the current nonce as last_nonce and processes the request.
Questions:
- Most importantly: Is this secure? Does it fulfill the requirements?
- Any downsides compared with API keys, a similar HMAC header, access tokens, or mTLS? I don't care about message integrity or mutual authentication. I've identified two disadvantages so far: both the client and server are stateful (nonce) and the client cannot send concurrent requests (correct?). Performance is fine, ie. orders of magnitude faster than the request processing time.
- Any existing standard? I don't want to use a too complex PAKE protocol, but maybe there's a simpler one? Found this draft but it seems to sign the whole request (too slow).