A guide to OAuth grants

OAuth by it’s nature is a very flexible standard and can adapted to work in many different scenarios. The core specification describes four authorisation grants:

  • Authorisation code grant
  • Implicit grant
  • Resource owner credentials grant
  • Client credentials grant

The specification also details another grant called the refresh token grant.

Furthermore there are a number of other grants that have gone through the IETF ratification process (none of which at the time of writing have been formally standardised):

  • Message authentication code (MAC) tokens
  • SAML 2.0 Bearer Assertion Profiles
  • JSON web token grant

The end goal of each of these grants (except the refresh token grant) is for the client application to have an access token (which represents a user’s permission for the client to access their data) which it can use to authenticate a request to an API endpoint.

In this post I’m going to describe each of the above grants and their appropriate use cases.

As a refresher here is a quick glossary of OAuth terms (taken from the core spec):

  • Resource owner (a.k.a. the User) – An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.
  • Resource server (a.k.a. the API server) – The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
  • Client – An application making protected resource requests on behalf of the resource owner and with its authorisation. The term client does not imply any particular implementation characteristics (e.g. whether the application executes on a server, a desktop, or other devices).
  • Authorisation server – The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorisation.

Authorisation code grant (section 4.1)

The authorisation code grant is the grant that most people think of when OAuth is described.

If you’ve ever signed into a website or application with your Twitter/Facebook/Google/(insert major Internet company here) account then you’ll have experienced using this grant.

Essentially a user will click on a “sign in with Facebook” (or other IdP) and then be redirected from the application/website (the “client”) to the IdP authorisation server. The user will then sign in to the IdP with their credentials, and then – if they haven’t already – authorise the client to allow it to use the user’s data (such as their name, email address, etc). If they authorise the request the user will be redirected back to the client with a token (called the authorisation code) in the query string (e.g. http://client.com/redirect?code=XYZ123) which the client will capture and exchange for an access token in the background.

This grant is suitable where the resource owner is a user and they are using a client which is allows a user to interact with a website in a browser. An obvious example is the client being another website, but desktop applications such as Spotify or Reeder use embedded browsers.

Some mobile applications use this flow and again use an embedded browser (or redirect the user to the native browser and then are redirected back to the app using a custom protocol).

In this grant the access token is kept private from the resource owner.

If you have a mobile application that is for your own service (such as the official Spotify or Facebook apps on iOS) it isn’t appropriate to use this grant as the app itself should already be trusted by your authorisation server and so the _resource owner credentials grant would be more appropriate.

Implicit grant (section 4.2)

The implicit grant is similar to the authentication code grant described above. The user will be redirected in a browser to the IdP authorisation server, sign in, authorise the request but instead of being returned to the client with an authentication code they are redirected with an access token straight away.

The purpose of the implicit grant is for use by clients which are not capable of keeping the client’s own credentials secret; for example a JavaScript only application.

If you decide to implement this grant then you must be aware that the access token should be treated as “public knowledge” (like a public RSA key) and therefore it must have a very limited permissions when interacting with the API server. For example an access token that was granted using the authentication code grant could have permission to be used to delete resources owned by the user, however an access token granted through the implicit flow should only be able to “read” resources and never perform any destructive operations.

Resource owner credentials grant (section 4.3)

When this grant is implemented the client itself will ask the user for their username and password (as opposed to being redirected to an IdP authorisation server to authenticate) and then send these to the authorisation server along with the client’s own credentials. If the authentication is successful then the client will be issued with an access token.

This grant is suitable for trusted clients such as a service’s own mobile client (for example Spotify’s iOS app). You could also use this in software where it’s not easy to implement the authorisation code – for example we bolted this authorisation grant into OwnCloud so we could retrieve details about a user that we couldn’t access over LDAP from the university’s Active Directory server.

Client credentials grant (section 4.4)

This grant is similar to the resource owner credentials grant except only the client’s credentials are used to authenticate a request for an access token. Again this grant should only be allowed to be used by trusted clients.

This grant is suitable for machine-to-machine authentication, for example for use in a cron job which is performing maintenance tasks over an API. Another example would be a client making requests to an API that don’t require user’s permission.

When someone visits a member of staff’s page on the University of Lincoln staff directory the website uses it’s own access token (that was generated using this grant) to authenticate a request to the API server to get the data about the member of staff that is used to build the page. When a member of staff signs in to update their profile however their own access token is used to retrieve and update their data. Therefore there is a good separation of concerns and we can easily restrict permissions that each type of access token has.

Refresh token grant (section 1.5)

The OAuth 2.0 specification details a fifth grant which can be used to “refresh” (i.e. renew) an access token which has expired.

Authorisation servers which support this grant will also issue a “refresh token” when it returns an access token to a client. When the access token expires instead of sending the user back through the authorisation code grant the client can use to the refresh token to retrieve a new access token with the same permissions as the old one.

My problem with the grant is that it means the client has to maintain state of each token and then either on a cron job keep access tokens up to date or when it tries to make a request and it fails then go and update the access token and repeat the request.

I personally prefer to issue access tokens that last longer than the user’s session cookie so that when they next sign in they’ll be issued a new token anyway.


The extension grants

The following grants are currently going through the standardisation process.

N.B. My explanation from here on is how ** I ** (as a developer) am interpreting the specifications – all three of the following grants specs need further work in my opinion to better explain their purpose and how they compare to the core grants.

MAC token grant (draft 3 at time of writing)

The MAC token grant can be used alongside another grant (the specification describes using it alongside the authentication code grant) to further improve the security of requests to the API server by including the addition of a MAC (message authentication code) signature along with the access token in order to both authenticate the request and prove the identity of the client making the request (because it prevents tampering and forgery). In some ways it is similar to the OAuth 1.0 request process.

When the authorisation server returns an access token to a client it also includes a key which the client uses to generate the MAC signature. The MAC signature is generated by combining the parameters of the request and then hashing them against the key.

This grant could be used when additional security measures are needed to ensure that the client querying an API is definitely who it is identifying itself as. It can also prevent access tokens being used by unauthorised clients (if an access token has been compromised by a man in the middle attack) because a valid signature (which can only be generated by the client which knows the MAC key associated with the access token) is required for each request.

SAML 2.0 Bearer Assertion Profiles (draft 15 at time of writing)

A SAML assertion is an XML payload which contains a security token. They are issued by identity providers and consumed by a service provider who relies on its content to identify the assertion’s subject for security-related purposes. It is quite literally an assertion as to who someone (or what something) is.

This grant allows a client to exchange an existing SAML assertion for an access token, meaning the user doesn’t have to authenticate again with an authorisation server. In some ways it resembles the concept of the refresh token grant.

An example use case of this grant would be a publishers website receiving an assertion from the UK Federation (after a user from a UK education institution has authenticated with their institution’s own resource server), converting the assertion into an access token and then querying the users institution’s API server to request additional details about the user.

JSON web token grant (draft 6 at time of writing)

The JSON web token grant is similar to the SAML assertion grant but uses JSON as the serialisation format instead of XML. This means that a JWT (JSON web token) can comfortable fit inside a HTTP authorization header.

A potential use case could be a web based client application that also has a mobile version, the web version could somehow share the existing access token with the mobile application which in turn requests its own access token. Possibly? Maybe? I’ll admit I can’t think of a better example.

Hawk: a new HTTP authentication scheme

Eran Hammer (formerly editor of the OAuth specifications) has introduced a new HTTP authentication scheme called Hawk.

Hawk is described as a HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial HTTP request cryptographic verification. It is related to his other new project Oz which is a web authorisation protocol promoted as an alternative to OAuth. Eran has made it clear that he doesn’t want to write a new specification after the leaving the OAuth working group and so he is intending to describe Hawk (and Oz) through code and leave it up to someone else to write a formal specification.

What is Hawk?

An overview of Hawk is provided in the README file in the repository:

Hawk is an HTTP 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.

Similar to the HTTP Basic access authentication scheme, the Hawk scheme utilizes a set of client credentials which include an identifier and key. However, in contrast with the Basic scheme, the key is never included in authenticated requests but is used to calculate a request MAC value which is included instead.

The Hawk scheme requires the establishment of a shared symmetric key between the client and the server, which is beyond the scope of this module. Typically, the shared credentials are established via an initial TLS-protected phase or derived from some other shared confidential information available to both the client and the server.

The primary design goals of this mechanism are to:

  • simplify and improve HTTP authentication for services that are unwilling or unable to employ TLS for every request,
  • secure the shared credentials against leakage when sent over a secure channel to the wrong server (e.g., when the client uses some form of dynamic configuration to determine where to send an authenticated request), and
  • mitigate the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client failure to validate the server’s identity as part of its TLS handshake.

Unlike the HTTP Digest authentication scheme, Hawk provides limited protection against replay attacks which does not require prior interaction with the server. Instead, the client provides a timestamp which the server can use to prevent replay attacks outside a narrow time window. Also unlike Digest, this mechanism is not intended to protect the key itself (user’s password in Digest) because the client and server both have access to the key material in the clear.

To clarify, MAC (Message Authentication Code) is a cryptographic string that is sent alongside a message (such as an HTTP request) to detect tampering and forgery. Both the sender and the receiver will use the same shared secret to generate and verify the MAC. The OAuth 1.0 specification used MAC signatures but these were removed in OAuth 2.0.

Protocol Example

To demonstrate how Hawk authentication works there is a protocol example:

The client attempts to access a protected resource without authentication, sending the following HTTP request to
the resource server:

GET /resource/1?b=1&a=2 HTTP/1.1
Host: 127.0.0.1:8000

The resource server returns the following authentication challenge:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Hawk

The client has previously obtained a set of Hawk credentials for accessing resources on the “http://example.com/”
server. The Hawk credentials issued to the client include the following attributes:

  • Key identifier: dh37fgj492je
  • Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn
  • Algorithm: hmac-sha-256

The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,
1970 00:00:00 GMT) and constructs the normalized request string (newline separated values):

1353832234
GET
/resource/1?b=1&a=2
127.0.0.1
8000
some-app-data

The request MAC is calculated using the specified algorithm “hmac-sha-256” and the key over the normalized request string.
The result is base64-encoded to produce the request MAC:

/uYWR6W5vTbY3WKUAN6fa+7p1t+1Yl6hFxKeMLfR6kk=

The client includes the Hawk key identifier, timestamp, and request MAC with the request using the HTTP “Authorization”
request header field:

GET /resource/1?b=1&a=2 HTTP/1.1
Host: 127.0.0.1:8000
Authorization: Hawk id="dh37fgj492je", ts="1353832234", ext="some-app-data", mac="/uYWR6W5vTbY3WKUAN6fa+7p1t+1Yl6hFxKeMLfR6kk="

The server validates the request by calculating the request MAC again based on the request received and verifies the validity and scope of the Hawk credentials. If valid, the server responds with the requested resource.

Security Considerations

There are a number of security considerations to consider which can be seen here https://github.com/hueniverse/hawk#security-considerations.

Hawk vs. OAuth

The Hawk documentation says that is can be used for client to server authentication but I think it would also make an easier to implement (than OAuth) authentication protocol if you are implementing machine to machine authentication.

For delegating access to protected resources then the documentation recommends Oz as alternative to OAuth. I will review Oz in another post.

PHP Implementation

I’ve had a go at implementing Hawk in PHP – https://github.com/alexbilbie/PHP-Hawk.

Client Usage

Assume you’re hitting up the following endpoint:

https://api.example.com/user/123?foo=bar

And the API server has given you the following credentials:

  • Key – ghU3QVGgXM
  • Secret – 5jNP12yT17Hx5Md3DCZ5pGI5sui82efX

To generate the header run the following:

$key = 'ghU3QVGgXM';
$secret = '5jNP12yT17Hx5Md3DCZ5pGI5sui82efX';
$hawk = Hawk::generateHeader($key, $secret, array(
                'host'    =>  'api.example.com', // you must set this
                `port`  =>  443, // you must set this
                'path'    =>  '/user/123',
                'method'  =>  'GET' // could be POST/DELETE/etc
            ));

You can also pass in additional application specific data with an ext key in the array.

Once you’ve got the Hawk string include it in your HTTP request as an Authorization header.

Server Usage

On your API endpoint if the incoming request is missing an authorization header then return the following two headers:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Hawk

If the request does contain a Hawk authorization header then process it like so:

$hawk = ''; // the authorisation header

// First parse the header to get the parts from the string
$hawk_parts = Hawk::parseHeader($hawk);

// Then with your own function, get the secret for the key from the database
$secret = getSecret($hark_parts['id']);

// Now validate the request
$valid = Hawk::verifyHeader($hawk, array(
        'host'    =>  'api.example.com',
        'port'    =>  443,
        'path'    =>  '/user/123',
        'method'  =>  'GET'
    ), $secret); // return true if the request is valid, otherwise false

Authentication in the Library

Last week, Paul and I sat down to list the IT resources that the library offer to staff and students are and how they authenticate users. We also identified services that allow us to customise the sign in experience in order to achieve at least stage one of our strategy for consistent sign in:

1) To ensure a single, consistent identity for each person, all library (and ICT) applications that we operate internally must have Active Directory sign-in instead of local databases. Almost all of our applications achieve this already.
(source Linkey bid document – section 3.1)

Before proceeding there is some jargon to explain:

  • SAM – A SAM (security accounts manager) ID is a user’s AD username. For staff this will generally be the first letter of their forename + their surname – e.g. for me this is abilbie. For students this is their student number – e.g. 01234567.
  • Password – This a user’s AD password.
  • Employee ID – for staff this is the ID number from our employee database. For students this is the same as their SAM ID.
  • SafeCom PIN – SafeCom is our printing authentication service we use here at the university. Each staff and student has their own PIN number which they use with their employee ID.

This is the list we came up with:

  1. Horizon Information Portal (HIP) – This service allows staff and students to interact with things they’ve borrowed or want to borrow, for example renewing and reserving books and viewing fines. We can edit XSL files which allow us to change the design of HIP. We can also add JavaScript files. HIP authenticates with a user’s employee ID and PIN number.
  2. library.lincoln.ac.uk – Hosted on our WordPress platform. We can completely customise every aspect of the site. Users sign in with their SAM ID and password.
  3. Blackboard – Our VLE. If a user is signed in it will provide infomation about their library account plus they can pay any fines. Digitised material stored is also stored in and access is granted based on a students’ course. Users sign in with their SAM ID and password.
  4. Clio – inter-library loans management website. Users sign in with their SAM ID and password. We can completely customise the experience.
  5. EPrints – our research repository. EPrints is open source so we can change anything. Users sign in with their SAM ID and password.
  6. EZProxy – allows for e-resources access based on IP address proxying. EZProxy is LDAP capable however it can inherit Blackboard/SharePoint authentication sessions. We can completely customise the experience.
  7. Open Athens LA (Local Authentication) – Enables users to securely access to online resources. Provides Athens->Athens, and Athens/SAML->UK Federation->SAML authentication. Users sign in with their SAM ID and password. This should be installed in the coming weeks. We think we can customise the experience.
  8. Resources that have their own username + password. A very subset of online resources the library subscribe don’t work with Athens or EZProxy and so give us a username and password to use. Users are directed to these services through our SharePoint site and are authenticate with these services in two ways:
  9. The username and password are automatically injected into the service’s authentication screen with a JavaScript script or
  10. The user is a presented with a 401 dialog and they have to manually enter the username and password.
  11. Thin Clients – The GCW library on the Brayford campus over the summer had a number of thin client computers installed. When physically in front of the computer users’ authenticate with their SAM ID and password but because these machines use virtual instances we could provide a “desktop in the browser” experience via UAG.
  12. Find it @ Lincoln – A search engine of journals and databases that we subscribe to that is hosted remotely by Ebsco. Authentication is delegated to EZProxy.
  13. RefWorks – Allows users to collect references. Authentication is via Athens. We can’t customise the look and feel of RefWorks itself but we hope we can customise how our Open Athens LA looks.
  14. Aspire – Reading List software provided by Talis. Authentication is via Athens. See above note about customising Athens LA.
  15. Journals A to Z / OpenURL resolver – As above
  16. Databases – A combination of Athens and EZProxy authentication.
  17. Printing – The physical printers in the library require authentication using a user’s employee ID and their PIN number.
  18. Self service kiosks – These kiosks authenticate users by requiring them to scan their staff/student card (which has a code 39 barcode of their employee ID and then typing in their PIN onscreen. We can’t customise this experience.
  19. Print top up kiosks – These kiosks authenticate users by requiring them to type in their SAM ID and password. We can’t customise this experience.

Visually of this looks like:

http://i.imgur.com/nEKo4.png

When the UAG is installed we should be able to easily hook up services that require SAM ID and password over LDAP. Other services that use alternative authentication such as HIP will require us to write some middleware that will translate between SAM ID + password to employee ID + PIN.

Assuming it is as simple as that, then when these services are hooked up to the UAG then the map will look like this:

http://i.imgur.com/dyV6C.png

The model assumes that eventually the UAG will be like a Gateway for users to access most resources.

LDAP inject means that once a user has authenticated with the UAG their SAM ID and password will be stored in a session, and then when the user visits a service that uses LDAP authentication to the AD, UAG will inject their username and password into the sign-in form and click the submit button for them. At the end of the day single sign-in is essentially a user experience which takes some of the pain with accessing resources away from them.

How OAuth 2.0 works

The following sequence describes how the OAuth 2.0 web-server flow works. The web-server flow is the most common OAuth flow which most implementations support.

Before we begin there is some terminology that needs to be understood:

  • Resource owner (a.k.a. the User)
    An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.
  • Resource server
    The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
  • Client
    An application making protected resource requests on behalf of the resource owner and with its authorisation. The term client does not imply any particular implementation characteristics (e.g. whether the application executes on a server, a desktop, or other devices).
  • Authorisation server
    The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorisation.

The web-server flow

1) The client redirects the user to the authentication server with the following information

  • The client’s ID (client_id)
  • A redirect URI where the user will returned to after they’ve authenticated with the authentication server and approved the client (redirect_uri)
  • The type of response that the client accepts (response_type)
  • A list of data which the client wishes to access on behalf of the user (scope)
  • A state parameter which is an anti-CSRF token (state)
	HTTP/1.1 302 Found
	Location: https://auth-server.tld/authorise?response_type=code
	&client_id=6BZF3wT52E7PaIlF1luRrKM4LMfkl649
	&redirect_uri=http://client.tld/signin/redirect
	&scope=basic,contacts
	&state=84Y632oM3j

2) The user signs into the authentication server and, if they haven’t already, approves the client to access their data. The user is informed which data the client wishes to access (defined by the scope parameter). If the user has already approved the application the server will check if the scope parameter matches that of the previous request and if it doesn’t will ask the user to sign in again.

3) The authentication server redirects the user back to the client (based on the redirect_uri parameter) with an authorisation code and the anti-CSRF token in the query string

	HTTP/1.1 302 Found Location: http://client.tld/signin/redirect
	?code=Al0wQaeTYsji97oRWk2l6Y940wdca3J2
	&state=84Y632oM3j

4) The client then exchanges the authorisation code for an access token by authenticating itself with the authentication server

	POST http://auth-server.tld/access_token HTTP/1.1
	Content-Type: application/x-www-form-urlencoded
	client_id=6BZF3wT52E7PaIlF1luRrKM4LMfkl649
	&client_secret=Al0wQaeTYsji97oRWk2l6Y940wdca3J2
	&redirect_uri=http://client.tld/signin/redirect
	&code=Al0wQaeTYsji97oRWk2l6Y940wdca3J2
	&grant_type=authorization_code

5) The authorisation server will perform the following validation:

  • Check that the client_id and client_secret are valid parameters
  • Check that the [authorisation] code matches the client_id and the redirect_uri

If the parameter pass the validation checks then the authentication server will respond with the access token that the client needs to access the user’s data. The server may also include a refresh token in the response.

	HTTP/1.1 200 OK
	Content-Type: application/json;charset=UTF-8
	Cache-Control: no-store
	Pragma: no-cache
	
	{
		"access_token":"2YotnFZFEjr1zCsicMWpAA",
		"expires_in":3600,
		"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
	}

Accessing resources

Once the client has the access token it can then make requests to the resource server for the user’s data

	POST http://resource-server.tld/user/details HTTP/1.1
	Content-Type: application/x-www-form-urlencoded
	
	access_token=2YotnFZFEjr1zCsicMWpAA

Angst against OAuth

Tim Bray, a developer at Google wrote in a recent blog post that he believes:

The new technology coming down the pipe, OAuth 2 and friends, is way too hard for developers; there need to be better tools and services if we’re going to make this whole Internet thing smoother and safer.

As someone who has been working with OAuth 2.0 for almost 18 months now I disagree with Tim’s position that OAuth 2.0 is “way too hard” for developers. The web-server flow essentially is a simple two step process:

  1. A redirection from the client to the authorisation server
  2. A POST request to the authorisation server to swap the authorisation code for an access token

I find it hard to believe that those two simple steps are too much for developers to implement in their applications.

It’s true that OAuth 1.0a was a pain to implement – just take a look at Twitter’s OAuth 1.0a guide to see how complicated it is in compared to the v2.0 flow I’ve described above – however as more and more service providers offer OAuth 2.0 endpoints I believe that developers will realise how easy it is to actually implement.