The journal
Authentication vs authorization in APIs (with request signing)
A clear, practical distinction between API authentication and authorization, focused on how request signing proves who sent the request while separate checks decide what they can do.


A valid signature is meaningful only after the verifier associates the key with a trusted identity and checks the required covered components and freshness. It does not grant permission to read or change a resource.
How authentication works for APIs (and where request signing fits)
Authentication proves identity or key possession. In HTTP APIs, credentials typically travel in headers. For example, the Authorization header "contains the credentials to authenticate a user-agent with a server" (MDN: HTTP headers).
Request signing strengthens authentication by binding a request to a key and protecting integrity. The HTTP Message Signatures headers identify what was signed and carry the signature value:
- Signature-Input: identifies the ordered list of message components covered by each signature and its metadata
- Signature: contains one or more labeled signature values
These header definitions follow RFC 9421, as summarized in MDN's headers reference (MDN: HTTP headers).
Example: a signed POST that also sends a bearer token
POST /invoices HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Digest: sha-256=:uA5J2...==:
Authorization: Bearer eyJhbGciOi...
Signature-Input: sig1=("@method" "@target-uri" "content-digest");created=1730310000;keyid="key-123"
Signature: sig1=:m2F0b...base64sig...==:
{"amount": 12500, "currency": "USD"}
What each part does: the signature provides proof-of-possession for key-123 and protects the covered components (authentication and integrity). The bearer token provides caller context and claims that the API can validate and use for authorization decisions (MDN: HTTP headers; NCSC).
How authorization works
Authorization governs what the authenticated caller can do. NCSC highlights three fundamentals: enforce least privilege, deny by default, and validate permissions on every request (NCSC).
- Scopes and roles: with OAuth 2.0 and OpenID Connect, tokens can carry claims that your API evaluates to allow specific actions. OIDC adds an identity layer; OAuth 2.0 provides delegated access (NCSC).
- Short-lived and bound credentials: prefer short lifetimes and proof-of-possession mechanisms (for example, certificate-bound tokens or DPoP) to reduce replay risk (NCSC).
If you are designing scopes, see our explainer: What are OAuth scopes used for?

Putting it together: a signed-request flow
- Client obtains a token from an identity provider. The token provides claims used for access decisions and, with OIDC, identity context (NCSC).
- Client builds the HTTP request and computes an HTTP Message Signature over selected components, sending Signature-Input and Signature headers (MDN: HTTP headers).
- API verifies the signature (authentication and integrity), validates the token and claims, then authorizes the action using least-privilege policy. Deny by default if any check fails (NCSC).
Common pitfalls to avoid
- Confusing signing with authorization: a valid signature proves sender and integrity; it does not imply permission. Always perform authorization checks per request (MDN; NCSC).
- Relying on weak credentials: avoid basic auth and long-lived static API keys as the only control; prefer short-lived, replay-resistant approaches (NCSC).
- Skipping replay protection: include freshness (for example, created time, nonce) in signatures and detect reuse. See our guide: Protect against replay attacks: practical layers for APIs.
Minimal, correct examples
1) HTTP Message Signatures header shape
Signature-Input: sig1=("@method" "@target-uri" "content-digest");created=1730310000;keyid="key-123"
Signature: sig1=:BASE64_SIGNATURE_BYTES:
Signature-Input enumerates the covered components and signature metadata; Signature carries the value for that label (MDN: HTTP headers).
2) Example token claims your API might authorize against
{
"sub": "user_9f3a",
"scope": "invoice:write invoice:read",
"aud": "https://api.example.com",
"iat": 1730309900,
"exp": 1730310500
}
Evaluate these claims on every request using deny-by-default and least-privilege policies (NCSC).
Put this into practice
Write one allowed and one forbidden action for the same authenticated identity. Test both, along with invalid signing cases, so a valid signature is not mistaken for permission to perform every operation.
Design checklist: keep authentication separate from authorization
FAQ
Is request signing authentication or authorization?
Authentication. It proves possession of a key and protects integrity; you still need separate authorization checks using claims and policy (MDN; NCSC).
Do signed requests replace tokens?
No. Tokens carry context and permissions that your API uses for authorization. Signatures complement tokens by proving the request came from the expected key holder and was not altered (MDN).
Related reading: Protect against replay attacks: practical layers for APIs · What are OAuth scopes used for?