Abstract
This document describes a way to add origin authentication, message integrity, and replay resistance to HTTP REST requests. It is intended to be used over the HTTPS protocol.
Copyright Notice
Copyright (c) 2011 Joyent, Inc. and the persons identified as document authors. All rights reserved.
Code Components extracted from this document must include MIT License text.
Introduction
This protocol is intended to provide a standard way for clients to sign HTTP requests. RFC2617 (HTTP Authentication) defines Basic and Digest authentication mechanisms, and RFC5246 (TLS 1.2) defines client-auth, both of which are widely employed on the Internet today. However, it is common place that the burdens of PKI prevent web service operators from deploying that methodology, and so many fall back to Basic authentication, which has poor security characteristics.
Additionally, OAuth provides a fully-specified alternative for authorization of web service requests, but is not (always) ideal for machine to machine communication, as the key acquisition steps (generally) imply a fixed infrastructure that may not make sense to a service provider (e.g., symmetric keys).
Several web service providers have invented their own schemes for signing HTTP requests, but to date, none have been placed in the public domain as a standard. This document serves that purpose. There are no techniques in this proposal that are novel beyond previous art, however, this aims to be a simple mechanism for signing these requests.
Signature Authentication Scheme
The "signature" authentication scheme is based on the model that the client must authenticate itself with a digital signature produced by either a private asymmetric key (e.g., RSA) or a shared symmetric key (e.g., HMAC). The scheme is parameterized enough such that it is not bound to any particular key type or signing algorithm. However, it does explicitly assume that clients can send an HTTP Date header.
Authorization Header
The client is expected to send an Authorization header (as defined in RFC 2617) with the following parameterization:
Signature Parameters
keyId
REQUIRED. The keyId field is an opaque string that the server can use to look up the component they need to validate the signature. It could be an SSH key fingerprint, an LDAP DN, etc. Management of keys and assignment of keyId is out of scope for this document.
algorithm
REQUIRED. The algorithm parameter is used if the client and server agree on a non-standard digital signature algorithm. The full list of supported signature mechanisms is listed below.
headers
OPTIONAL. The headers parameter is used to specify the list of HTTP headers used to sign the request. If specified, it should be a quoted list of HTTP header names, separated by a single space character. By default, only one HTTP header is signed, which is the Date header. Note that the list MUST be specified in the order the values are concatenated together during signing. To include the HTTP request line in the signature calculation, use the special request-line value. While this is overloading the definition of headers in HTTP linguism, the request-line is defined in RFC 2616, and as the outlier from headers in useful signature calculation, it is deemed simpler to simply use request-line than to add a separate parameter for it.
extensions
OPTIONAL. The extensions parameter is used to include additional information which is covered by the request. The content and format of the string is out of scope for this document, and expected to be specified by implementors.
signature
REQUIRED. The signature parameter is a Base64 encoded digital signature generated by the client. The client uses the algorithm and headers request parameters to form a canonicalized signing string. This signing string is then signed with the key associated with keyId and the algorithm corresponding to algorithm. The signature parameter is then set to the Base64 encoding of the signature.
Signing String Composition
In order to generate the string that is signed with a key, the client MUST take the values of each HTTP header specified by headers in the order they appear.
If the header name is not
request-linethen append the lowercased header name followed with an ASCII colon:and an ASCII space.If the header name is
request-linethen append the HTTP request line, otherwise append the header value.If value is not the last value then append an ASCII newline
\n. The string MUST NOT include a trailing ASCII newline.
Example Requests
All requests refer to the following request (body omitted):
The "rsa-key-1" keyId refers to a private key known to the client and a public key known to the server. The "hmac-key-1" keyId refers to key known to the client and server.
Default parameterization
The authorization header and signature would be generated as:
The client would compose the signing string as:
Header List
The authorization header and signature would be generated as:
The client would compose the signing string as (+ "\n" inserted for readability):
Algorithm
The authorization header and signature would be generated as:
The client would compose the signing string as:
Signing Algorithms
Currently supported algorithm names are:
rsa-sha1
rsa-sha256
rsa-sha512
dsa-sha1
hmac-sha1
hmac-sha256
hmac-sha512
Security Considerations
Default Parameters
Note the default parameterization of the Signature scheme is only safe if all requests are carried over a secure transport (i.e., TLS). Sending the default scheme over a non-secure transport will leave the request vulnerable to spoofing, tampering, replay/repudiation, and integrity violations (if using the STRIDE threat-modeling methodology).
Insecure Transports
If sending the request over plain HTTP, service providers SHOULD require clients to sign ALL HTTP headers, and the request-line. Additionally, service providers SHOULD require Content-MD5 calculations to be performed to ensure against any tampering from clients.
Nonces
Nonces are out of scope for this document simply because many service providers fail to implement them correctly, or do not adopt security specifications because of the infrastructure complexity. Given the header parameterization, a service provider is fully enabled to add nonce semantics into this scheme by using something like an x-request-nonce header, and ensuring it is signed with the Date header.
Clock Skew
As the default scheme is to sign the Date header, service providers SHOULD protect against logged replay attacks by enforcing a clock skew. The server SHOULD be synchronized with NTP, and the recommendation in this specification is to allow 300s of clock skew (in either direction).
Required Headers to Sign
It is out of scope for this document to dictate what headers a service provider will want to enforce, but service providers SHOULD at minimum include the Date header.
References
Normative References
[RFC2616] Hypertext Transfer Protocol -- HTTP/1.1
[RFC2617] HTTP Authentication: Basic and Digest Access Authentication
[RFC5246] The Transport Layer Security (TLS) Protocol Version 1.2
Informative References
Appendix A - Test Values
The following test data uses the RSA (2048b) keys, which we will refer to as keyId=Test in the following samples:
And all examples use this request:
Default
The string to sign would be:
The Authorization header would be:
All Headers
Parameterized to include all headers, the string to sign would be (+ "\n" inserted for readability):
The Authorization header would be: