Due to RFC proposed standards, most of the implementation today is based on OAuth 2.0 Bearer Token Profile. OAuth 2.0 Bearer Token profile brings a simplified scheme for authentication. This RFC specification describes how to use bearer tokens in HTTP requests to access OAuth 2.0 protected resources. Any party in possession of a bearer token (a "bearer") can use it to get access to the associated resources (without demonstrating possession of a cryptographic key). To prevent misuse, bearer tokens need to be protected from disclosure in storage and in transport.
Before looking into the OAuth 2.0 MAC profile, it is necessary to have a high-level overview of the OAuth 2.0 message flow. OAuth 2.0 has mainly three phases.
- Requesting an Authorization Grant.
- Exchanging the Authorization Grant for an Access Token.
- Access the resources with the Access Token.
OAuth 2.0 core specification does not mandate any token type. At the same time, at any point the token requester - client - cannot decide which token type it needs. It is purely up to the Authorization Server to decide which token type is to be returned in the Access Token response. So, if the token type comes into action in phase-2, then Authorization Server returns the OAuth 2.0 Access Token.
The access token type provides the client with the information required to successfully utilize the access token to make a protected resource request (along with type-specific attributes). The client must not use an access token if it does not understand the token type.
Each access token type definition specifies the additional attributes (if any) sent to the client together with the "access_token" response parameter. It also defines the HTTP authentication method used to include the access token when making a protected resource request.
For example, the following is what you get for Access Token response irrespective of which grant type you use.
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"mF_9.B5f-4.1JqM", "token_type":"Bearer", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA" }
The above is for Bearer, the following is for MAC:
HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store { "access_token":"SlAV32hkKG", "token_type":"mac", "expires_in":3600, "refresh_token":"8xLOxBtZp8", "mac_key":"adijq39jdlaska9asud", "mac_algorithm":"hmac-sha-256" }
Here you can see MAC Access Token response has two additional attributes. mac_key
and the mac_algorithm
. Each access token type definition specifies the additional attributes (if any) sent to the client together with the "access_token" response parameter.
This MAC Token Profile defines the HTTP MAC access authentication scheme, providing a method for making authenticated HTTP requests with partial cryptographic verification of the request, covering the HTTP method, request URI, and host. In the above response, access_token
is the MAC key identifier. Unlike in Bearer, MAC token profile never openly provides this information.
The access_token or the MAC key identifier is a string identifying the MAC key used to calculate the request MAC. The string is usually opaque to the client. The server typically assigns a specific scope and lifetime to each set of MAC credentials. The identifier may denote a unique value used to retrieve the authorization information (e.g. from a database), or self-contain the authorization information in a verifiable manner (i.e. a string consisting of some data and a signature).
The mac_key
is a shared symmetric secret used as the MAC algorithm key. The server does not reissue a previously issued MAC key and MAC key identifier combination.
In phase-3, the following shows how the Authorization HTTP header looks like when Bearer Token been used.
Authorization: Bearer mF_9.B5f-4.1JqM
This adds a very low overhead on client side. It simply needs to pass the exact access_token
it got from the Authorization Server in phase-2.
Under MAC token profile, this is how it looks like:
Authorization: MAC id="h480djs93hd8", ts="1336363200", nonce="dj83hs9s", mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM="
MAC id
is the MAC key identifier or theaccess_token
from the phase-2.ts
the request timestamp. The value is a positive integer set by the client when making each request to the number of seconds elapsed from a fixed point in time (e.g. January 1, 1970 00:00:00 GMT). This value is unique across all requests with the same timestamp and MAC key identifier combination.nonce
is a unique string generated by the client. The value is unique across all requests with the same timestamp and MAC key identifier combination.
The client uses the MAC algorithm and the MAC key to calculate the request mac.
This is how you derive the normalized string to generate the HMAC. The normalized request string is a consistent, reproducible concatenation of several of the HTTP request elements into a single string. By normalizing the request into a reproducible string, the client and server can both calculate the request MAC over the exact same value.
The string is constructed by concatenating the following HTTP request elements, each followed by a new line character (%x0A):
- The timestamp value calculated for the request.
- The
nonce
value generated for the request. - The HTTP request method in upper case. For example: "HEAD", "GET", "POST", etc.
- The HTTP request-URI as defined by [RFC2616] section 5.1.2.
- The hostname included in the HTTP request using the "Host" request header field in lower case.
- The port as included in the HTTP request using the "Host" request header field. If the header field does not include a port, the default value for the scheme MUST be used (e.g. 80 for HTTP and 443 for HTTPS).
- The value of the "ext" "Authorization" request header field attribute if one was included in the request (this is optional), otherwise, an empty string.
Each element is followed by a new line character (%x0A) including the last element and even when an element value is an empty string.
Either you use Bearer of MAC - the end user or the resource owner is identified using the access_token
. Authorization, throttling, monitoring or any other quality of service operations can be carried out against the access_token
irrespective of which token profile you use.