© Prabath Siriwardena 2020
P. SiriwardenaAdvanced API Securityhttps://doi.org/10.1007/978-1-4842-2050-4_22

OAuth 2.0 MAC Token Profile

Prabath Siriwardena1 
(1)
San Jose, CA, USA
 

The OAuth 2.0 core specification doesn’t mandate any specific token type. It’s one of the extension points introduced in OAuth 2.0. Almost all public implementations use the OAuth 2.0 Bearer Token Profile. This came up with the OAuth 2.0 core specification, but as an independent profile, documented under RFC 6750. Eran Hammer, who was the lead editor of the OAuth 2.0 specification by that time, introduced the Message Authentication Code (MAC) Token Profile for OAuth 2.0. (Hammer also led the OAuth 1.0 specification.) Since its introduction to the OAuth 2.0 IETF working group in November 2011, the MAC Token Profile has made a slow progress. The slow progress was mostly due to the fact that the working group was interested in building a complete stack around bearer tokens before moving into another token type. In this chapter, we will take a deeper look into the OAuth 2.0 MAC Token Profile and its applications.

OAuth 2.0 and the road to Hell

One of the defining moments of OAuth 2.0 history was the resignation of OAuth 2.0 specification lead editor Eran Hammer. On July 26, 2012, he wrote a famous blog post titled “OAuth 2.0 and the Road to Hell”1 after announcing his resignation from the OAuth 2.0 IETF working group. As highlighted in the blog post, Hammer thinks OAuth 2.0 is a bad protocol, just like any WS-* (web services) standard. In his comparison, OAuth 1.0 is much better than OAuth 2.0 in terms of complexity, interoperability, usefulness, completeness, and security. Hammer was worried about the direction in which OAuth 2.0 was heading, because it was not what was intended by the web community that initially formed the OAuth 2.0 working group.

According to Hammer, the following were the initial objectives of the OAuth 2.0 working group:
  • Build a protocol very similar to OAuth 1.0.

  • Simplify the signing process.

  • Add a light identity layer.

  • Address native applications.

  • Add more flows to accommodate more client types.

  • Improve security.

In his blog post, Hammer highlighted the following architectural changes from OAuth 1.0 to 2.0 (extracted from http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/):
  • Unbounded tokens: In 1.0, the client has to present two sets of credentials on each protected resource request, the token credentials and the client credentials. In 2.0, the client credentials are no longer used. This means that tokens are no longer bound to any particular client type or instance. This has introduced limits on the usefulness of access tokens as a form of authentication and increased the likelihood of security issues.

  • Bearer tokens: 2.0 got rid of all signatures and cryptography at the protocol level. Instead, it relies solely on TLS. This means that 2.0 tokens are inherently less secure as specified. Any improvement in token security requires additional specifications, and as the current proposals demonstrate, the group is solely focused on enterprise use cases.

  • Expiring tokens: 2.0 tokens can expire and must be refreshed. This is the most significant change for client developers from 1.0, as they now need to implement token state management. The reason for token expiration is to accommodate self-encoded tokens—encrypted tokens, which can be authenticated by the server without a database look-up. Because such tokens are self-encoded, they cannot be revoked and therefore must be short-lived to reduce their exposure. Whatever is gained from the removal of the signature is lost twice in the introduction of the token state management requirement.

  • Grant types: In 2.0, authorization grants are exchanged for access tokens. Grant is an abstract concept representing the end user approval. It can be a code received after the user clicks “Approve” on an access request, or the user’s actual username and password. The original idea behind grants was to enable multiple flows. 1.0 provides a single flow, which aims to accommodate multiple client types. 2.0 adds significant amount of specialization for different client types.

Most of all, Hammer wasn’t in favor of the authorization framework built by OAuth 2.0 and the extensibility introduced. His argument was that the Web doesn’t need another security framework: what it needs is a simple, well-defined security protocol. Regardless of these arguments, over the years OAuth 2.0 has become the de facto standard for API security—and the extensibility introduced by OAuth 2.0 is paying off.

Bearer Token vs. MAC Token

Bearer tokens are just like cash. Whoever owns one can use it. At the time you use it, you don’t need to prove you’re the legitimate owner. It’s similar to the way you could use stolen cash with no problem; what matters is the validity of the cash, not the owner.

MAC tokens, on the other hand, are like credit cards. Whenever you use a credit card, you have to authorize the payment with your signature. If someone steals your card, the thief can’t use it unless they know how to sign exactly like you. That’s the main advantage of MAC tokens.

With bearer tokens, you always have to pass the token secret over the wire. But with MAC tokens, you never pass the token secret over the wire. The key difference between bearer tokens and MAC tokens is very similar to the difference between HTTP Basic authentication and HTTP Digest authentication, which we discussed in Appendix F.

Note

Draft 5 of the OAuth 2.0 MAC Token Profile is available at http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-05. This chapter is based on draft 5, but this is an evolving specification. The objective of this chapter is to introduce the MAC Token Profile as an extension of OAuth token types. The request/response parameters discussed in this chapter may change as the specification evolves, but the basic concepts will remain the same. It’s recommended that you keep an eye on https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-http-mac/ to find out the latest changes taking place.

Obtaining a MAC Token

The OAuth 2.0 core specification isn’t coupled with any of the token profiles. The OAuth flows discussed in Chapter 4 applies in the same way for MAC tokens. OAuth grant types don’t have any dependency on the token type. A client can obtain a MAC token by using any grant type. Under the authorization code grant type, the resource owner that visits the application initiates the flow. The client, which must be a registered application at the authorization server, redirects the resource owner to the authorization server to get the approval. The following is a sample HTTP redirect, which takes the resource owner to the OAuth authorization server:
  • https://authz.server.com/oauth2/authorize?response_type=code&
  • client_id=0rhQErXIX49svVYoXJGt0DWBuFca&
  • redirect_uri=https%3A%2F%2Fmycallback
The value of response_type must be code. This indicates to the authorization server that the request is for an authorization code. client_id is an identifier for the client application. Once the client application is registered with the authorization server, the client gets a client_id and a client_secret. The value of redirect_uri should be same as the value registered with the authorization server. During the client registration phase, the client application must provide a URL under its control as the redirect_uri. The URL-encoded value of the callback URL is added to the request as the redirect_uri parameter. In addition to these parameters, a client application can also include a scope parameter. The value of the scope parameter is shown to the resource owner on the approval screen. It indicates to the authorization server the level of access the client needs on the target resource/API. The previous HTTP redirect returns the requested code to the registered callback URL:
  • https://mycallback/?code=9142d4cad58c66d0a5edfad8952192

The value of the authorization code is delivered to the client application via an HTTP redirect and is visible to the resource owner. In the next step, the client must exchange the authorization code for an OAuth access token by talking to the OAuth token endpoint exposed by the authorization server. This can be an authenticated request with the client_id and the client_secret of the client application in the HTTP authorization header, if the token endpoint is secured with HTTP Basic authentication. The value of the grant_type parameter must be the authorization_code, and the value of the code should be the one returned from the previous step. If the client application set a value for the redirect_uri parameter in the previous request, then it must include the same value in the token request. The client can’t suggest to the authorization server the type of token it expects: it’s entirely up to the authorization server to decide, or it can be based on a pre-agreement between the client and the authorization server at the time of client registration, which is outside the scope of OAuth.

The following cURL command to exchange the authorization code for a MAC token is very similar to what you saw for the Bearer Token Profile (in Chapter 4). The only difference is that this introduces a new parameter called audience, which is a must for a MAC token request:
  • > curl -v -X POST --basic
  •     -u 0rhQErXIX49svVYoXJGt0DWBuFca:eYOFkL756W8usQaVNgCNkz9C2D0a
  •     -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8"
  •     -k -d "grant_type=authorization_code&
  •     code=9142d4cad58c66d0a5edfad8952192&
  •     redirect_uri=https://mycallback&
  •     audience=https://resource-server-URI"
  •     https://authz.server.com/oauth2/token
  • The previous cURL command returns the following response:

  • HTTP/1.1 200 OK
  • Content-Type: application/json
  • Cache-Control: no-store
  •  {
  •         "access_token": "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBM",
  •         "token_type":"mac",
  •         "expires_in":3600,
  •         "refresh_token":"8xLOxBtZp8",
  •         "kid":"22BIjxU93h/IgwEb4zCRu5WF37s=",
  •         "mac_key":"adijq39jdlaska9asud",
  •         "mac_algorithm":"hmac-sha-256"
  • }

Let’s examine the definition of each parameter:

access_token: The OAuth 2.0 access token, which binds the client, the resource owner, and the authorization server together. With the introduction of the audience parameter, this now binds all of those with the resource server as well. Under the MAC Token Profile, by decoding the access token, you should be able to find the audience of the access token. If someone tampers with the access token to change the audience, that will make the token validation fail automatically at the authorization server.

token_type: Type of the token returned from the authorization server. The client should first try to understand the value of this parameter and begin processing accordingly. The processing rules differ from one token type to another. Under the MAC Token Profile, the value of the token type must be mac.

expires_in: The lifetime of the access token in seconds.

refresh_token: The refresh token associated with the access token. The refresh token can be used to acquire a new access token.

kid: Stands for key identifier. This is an identifier generated by the authorization server. It’s recommended that you generate the key identifier by base64 encoding the hashed access token: kid = base64encode (sha-1 (access_token)). This identifier uniquely identifies the mac_key used later to generate the MAC while invoking the resource APIs.

mac_key: A session key generated by the authorization server, having the same lifetime as the access token. The mac_key is a shared secret used later to generate the MAC while invoking the resource APIs. The authorization server should never reissue the same mac_key or the same kid.

mac_algorithm: The algorithm to generate the MAC during API invocation. The value of the mac_algorithm should be well understood by the client, authorization server, and resource server.

The OAuth 2.0 access token is opaque to anyone outside the authorization server. It may or may not carry meaningful data, but no one outside the authorization server should try to interpret it. The OAuth 2.0 MAC Token Profile defines a more meaningful structure for the access token; it’s no longer an arbitrary string. The resource server should understand the structure of the access token generated by the authorization server. Still, the client should not try to interpret it.

The access token returned from the authorization server to the client is encoded with the audience, key identifier, and encrypted value of the mac_key. The mac_key must be encrypted with the public key of the resource server or with a shared key established between the resource server and the authorization server via a prior agreement outside the scope of OAuth. When accessing a protected API, the client must send the access token along with the request. The resource server can decode the access token and get the encrypted mac_key, which it can later decrypt from its own private key or the shared key.

OAuth 2.0 Audience Information

The audience parameter is defined in the OAuth 2.0: Audience Information Internet draft available at http://tools.ietf.org/html/draft-tschofenig-oauth-audience-00. This is a new parameter introduced into the OAuth token request flow and is independent of the token type. Once it’s approved as an IETF proposed standard, the Bearer Token Profile also will be updated to include this in the access token request.

The objective of the audience parameter introduced by the OAuth 2.0: Audience Information Internet draft is to identify the audience of an issued access token. With this, the access token issued by the authorization server is for a specific client, to be used against a specific resource server or a specific set of resource servers. All resource servers should validate the audience of the access token before considering it valid.

After completing the authorization-granting phase, the client must decide which resource server to access and should find the corresponding audience URI. That must be included in the access token request to the token endpoint. Then the authorization server must check whether it has any associated resource servers that can be identified by the provided audience URI. If not, it must send back the error code invalid_request. If all validations pass at the authorization server, the new Internet draft suggests including the allowed audience in the access token. While invoking an API hosted in the resource server, it can decode the access token and find out whether the allowed audience matches its own.

Invoking an API Protected with the OAuth 2.0 MAC Token Profile

Following any of the grant types, you can obtain a MAC token from the authorization server. Unlike with the Bearer Token Profile, this needs more processing at the client end before you invoke an API protected with the MAC Token Profile. Prior to invoking the protected API, the client must construct an authenticator. The value of the authenticator is then added to the HTTP authorization header of the outgoing request. The authenticator is constructed from the following parameters:

kid: The key identifier from the authorization grant response.

ts: Timestamp, in milliseconds, since January 1, 1970.

seq-nr: Indicates the initial sequence number to be used during the message exchange between the client and the resource server, from client to server.

access_token: The value of the access token from the authorization grant response.

mac: The value of the MAC for the request message. Later, this appendix discusses how to calculate the MAC.

h: Colon-separated header fields, used to calculate the MAC.

cb: Specifies the channel binding. Channel bindings are defined in “Channel Bindings for TLS,” RFC 5929, available at http://tools.ietf.org/html/rfc5929. The Channel Bindings for TLS RFC defines three bindings: tls-unique, tls-server-end-point, and tls-unique-for-telnet.

The following is a sample request to access an API secured with an OAuth 2.0 MAC Token Profile.
GET /patient?name=peter&id=10909HTTP/1.1
Host: medicare.com
Authorization: MAC  kid="22BIjxU93h/IgwEb4zCRu5WF37s=",
                    ts="1336363200",
                    seq-nr="12323",
                    access_token="eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBM",
                    mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM=",
                    h="host",
                    cb="tls-unique:9382c93673d814579ed1610d3"

Calculating the MAC

The OAuth 2.0 MAC Token Profile defines two algorithms to calculate the MAC: HMAC-SHA1 and HMAC-SHA256. It also provides an extension for additional algorithms.

The Message Authentication Code (MAC) provides integrity and authenticity assurance for the associated message. The MAC algorithm accepts a message and a secret key to produce the associated MAC. To verify the MAC, the receiving party should have the same key and calculate the MAC of the received message. If the calculated MAC is equal to the MAC in the message, that guarantees integrity and authenticity.

A Hash-based Message Authentication Code (HMAC) is a specific way of calculating the MAC using a hashing algorithm. If the hashing algorithm is SHA-1, it’s called HMAC-SHA1. If the hashing algorithm is SHA256, then it’s called HMAC-SHA256. More information about HMAC is available at http://tools.ietf.org/html/rfc2104. The HMAC-SHA1 and HMAC-SHA256 functions need to be implemented in the corresponding programming language.

Here’s the calculation with HMAC-SHA1:
mac = HMAC-SHA1(mac_key, input-string)
And here it is with HMAC-SHA256:
mac = HMAC-SHA256(mac_key, input-string)

For an API invocation request, the value of input-string is the Request-Line from the HTTP request, the timestamp, the value of seq-nr, and the concatenated values of the headers specified under the parameter h.

HTTP Request-Line

The HTTP Request-Line is defined in Section 5 of the HTTP RFC, available at www.w3.org/Protocols/rfc2616/rfc2616-sec5.html. The request line is defined as follows:
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
The value of Method can be OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, or any extension method. SP stands for space—to be technically accurate, it’s ASCII code 32. Request-URI identifies the representation of the resource where the request is sent. According to the HTTP specification, there are four ways to construct a Request-URI:
Request-URI = "∗" | absoluteURI | abs_path | authority

The asterisk (*) means the request targets not a specific resource but the server itself, for example, OPTIONS * HTTP/1.1.

The absoluteURI must be used when the request is made through a proxy, for example, GET https://resource-server/myresource HTTP/1.1.

abs_path is the most common form of a Request-URI. In this case, the absolute path with respect to the host server is used. The URI or the network location of the server is transmitted in the HTTP Host header. For example:
GET /myresource HTTP/1.1
Host: resource-server

The authority form of the Request-URI is only used with HTTP CONNECT method. This method is used to make a connection through a proxy with tunneling, as in the case of TLS tunneling.

After the Request-URI must be a space and then the HTTP version, followed by a carriage return and a line feed.

Let’s take the following example:
POST /patient?name=peter&id=10909&blodgroup=bpositive HTTP/1.1
Host: medicare.com
The value of the input-string is
POST /patient?name=peter&id=10909&blodgroup=bpositive HTTP/1.1
1336363200
12323
medicare.com

1336363200 is the timestamp, 12323 is the sequence number, and medicare.com is the value of the Host header. The value of the Host header is included here because it is set in the h parameter of the API request under the HTTP Authorization header. All of these entries should be separated by a newline separator character, denoted by in the example. Once the input string is derived, the MAC is calculated on it using the mac_key and the MAC algorithm specified under mac_algorithm.

MAC Validation by the Resource Server

To access any API secured with the OAuth 2.0 MAC Token Profile, the client should send the relevant parameters with the API invocation request. If any of the parameters are lacking in the request or the provided values are invalid, the resource server will respond with an HTTP 401 status code. The value of the WWW-Authenticate header should be set to MAC, and the value of the error parameter should explain the nature of the error:
  • HTTP/1.1 401 Unauthorized
  • WWW-Authenticate: MAC error="Invalid credentials"
  • Let’s consider the following valid API request, which comes with a MAC header:

  • GET /patient?name=peter&id=10909HTTP/1.1
  • Host: medicare.com
  • Authorization: MAC  kid="22BIjxU93h/IgwEb4zCRu5WF37s=",
  •                     ts="1336363200",
  •                     seq-nr="12323",
  •                     access_token="eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBM",
  •                     mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM=",
  •                     h="host",
  •                     cb="tls-unique:9382c93673d814579ed1610d3"

To validate the MAC of the request, the resource server has to know the mac_key. The client must pass the mac_key to the resource server, encoded in the access_token. The first step in validation is to extract the mac_key from the access_token in the request. Once the access_token is decoded, the resource server has to verify its audience. The authorization server encodes the audience of the access_token into the access_token.

Once the access_token is verified and the scopes associated with it are validated, the resource server can cache the mac_key by the kid. The cached mac_key can be used in future message exchanges.

According to the MAC Token Profile, the access_token needs to be included only in the first request from the client to the resource server. The resource server must use the cached mac_key (against the kid) to validate subsequent messages in the message exchange. If the initial access_token doesn’t have enough privileges to invoke a later API, the resource server can request a new access_token or a complete authenticator by responding with an HTTP WWW-Authenticate header.

The resource server must calculate the MAC of the message the same way the client did before and compare the calculated MAC with the value included in the request. If the two match, the request can be considered a valid, legitimate one. But you still need to make sure there are no replay attacks. To do that, the resource server must verify the timestamp in the message by comparing it with its local timestamp.

An attacker that can eavesdrop on the communication channel between the client and the resource server can record messages and replay them at a different time to gain access to the protected resource. The OAuth 2.0 MAC Token Profile uses timestamps as a way of detecting and mitigating replay attacks.

OAuth Grant Types and the MAC Token Profile

OAuth grant types and token types are two independent extension points introduced in the OAuth 2.0 core specification. They don’t have any direct dependency between each other. This chapter only talks about the authorization code grant type, but all the other grant types work in the same manner: the structure of the access token returning from the implicit grant type, the resource owner password credentials grant type, and the client credentials grant type is the same.

OAuth 1.0 vs. OAuth 2.0 MAC Token Profile

Eran Hammer (who was initially the lead editor of the OAuth 2.0 specification) submitted the initial OAuth 2.0 MAC Token Profile draft to the OAuth working group in May 2011, and the first draft (also submitted by Hammer) followed with some improvements in February 2012. Both drafts were mostly influenced by the OAuth 1.0 architecture. After a long break, and after Hammer’s resignation from the OAuth working group, the Internet draft 4 of the MAC Token Profile introduced a revamped architecture. This architecture, which was discussed in this chapter, has many architectural differences from OAuth 1.0 (see Table G-1).
Table G-1

OAuth 1.0 vs. OAuth 2.0 MAC Token Profile

OAuth 1.0

OAuth 2.0 MAC Token Profile

Requires a signature both during the initial handshake and during the business API invocation.

Requires a signature only for the business API invocation.

The resource server must know the secret key used to sign the message beforehand.

The shared secret doesn’t have an associated lifetime.

Doesn’t have any audience restrictions. Tokens can be used against any resource server.

The encrypted shared secret used to sign the message is passed to the resource server, embedded in the access_token.

A lifetime is associated with the mac_key, which is used as the key to sign.

The authorization server enforces an audience restriction on the issued access_tokens, so that those access tokens can’t be used against any resource server.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.190.93