Signed requests
An authentication pattern where the client proves identity by signing each request with its private key, so the credential never travels with the request and an intercepted signature is bound to a single specific request.
What they are
A signed request is one where the client proves its identity by signing the request itself with a private key, and sending the signature alongside the request. The server verifies the signature using the corresponding public key. The credential, the private key itself, stays on the client; only the signature ever crosses the network.
The signature is bound to the specific request, typically including the HTTP method, the path, a timestamp, a nonce, and a hash of the body. Change any of those and the signature stops verifying.
Why they exist
Most APIs authenticate with a bearer token: a long opaque string the client sends with each request, where possession alone proves identity. Bearer tokens are simple, work over any transport, and travel cleanly through HTTP headers. They have one structural problem: anybody who sees the token can use it.
Tokens leak in ordinary ways. They show up in server logs, browser developer tools, intercepting proxies, error reports, mobile crash dumps, and screenshots in support tickets. Once a token leaks, it works for an attacker exactly the same as for the legitimate client until the token is rotated, and there's no way for the receiving server to tell the two apart.
Signed requests solve the leak problem by never sending the credential at all. The private key never leaves the client. What travels is a signature over the specific request being made. An attacker who captures the signature can replay only that exact request, only within whatever replay window the server enforces.
What goes into a signature
Every signed-request protocol picks a few elements to hash and sign. A typical recipe:
- HTTP method and path. A signature for
POST /v1/secrets/abcdoesn't verify againstDELETE /v1/secrets/abc. - A timestamp. Servers reject signatures older than some window (usually 5 minutes), so a stolen signature from yesterday is dead today.
- A nonce. A random value the server records and refuses to accept twice. Combined with the timestamp, this prevents replay even inside the window.
- A body hash. A SHA-256 (or similar) of the request body, so changing the body invalidates the signature.
The signed string is concatenated, hashed, signed with the client's private key, and sent in a header (commonly X-Signature, Authorization, or a service-specific header). The server reconstructs the same string from the request, looks up the client's public key, and verifies.
When signed requests are right
Signed requests are well-suited to machine-to-machine traffic, where the client is a process that can hold a private key safely and perform per-request signing without burdening a human. They make sense any time the credential's exposure cost is high (broad access, hard to rotate, valuable downstream system) and the client side can be made to do the extra work.
Bearer tokens still make sense at the user-experience layer, where the client is a browser holding a session cookie and can't reasonably do per-request signing. The right answer is usually a mix: bearer tokens for user sessions, signed requests for the machine-to-machine layer where secrets actually move.
How SikkerKey uses them
When your machine talks to SikkerKey, whether through the CLI or an SDK, the request is signed with the machine's Ed25519 private key before it goes out. The signature covers method:path:timestamp:nonce:body_hash, and the headers carry the machine ID, timestamp, nonce, and signature. SikkerKey rejects requests older than 5 minutes, refuses to accept the same nonce twice from the same machine, and verifies the signature against the public key on file. If any check fails, the request is rejected before anything is decrypted.
The practical effect is that copying a credential off a laptop, watching a request go by on the wire, or grepping a log file for a token all turn up nothing useful. The signing key has to be present and active on the machine making the request, and a captured request is dead within five minutes.
See also
SikkerKey is the secrets manager built around the patterns in this glossary. Encrypted vault, machine identity over signed requests, dynamic secrets — set up in minutes.
Start for Free