Authorization through OAuth 2.0

The Drillster API uses the OAuth 2.0 protocol to authorize client applications to use the Drillster API. OAuth has become the de facto authorization standard for web based APIs. The most well known user of OAuth 2.0 is probably Facebook.

Obtaining an access token

OAuth enables users to grant access to their Drillster account by third party applications, but without giving up their Drillster credentials, and remaining in full control over which application may access their account. The end result of a successful OAuth conversation is that the third party obtains a token that represents the user's authorization to use his account. With this token, all of the available API calls can be made on behalf of that user.

An access token looks like this:

These tokens can get pretty lengthy, easily more than 700 characters! If you are storing OAuth tokens in a database, please do not limit the length of the storage field. If you must limit it, be sure to pick a sufficiently large limit. In practice 8Kb is a good upper limit.

The token must be included in all API calls. This is done by including it in the “Authorization” HTTP header:

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJXSHJrck9DMFNEcWY2VjNXYVRrblpRIiwiZXhwIjoxNDYzMDY1MDkyLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZDMyNDQ1YzEtMDAxYi00ZTkyLTgxOWMtOGUxZDcyMGQ1N2RmIiwiY2xpZW50X2lkIjoiZGNlOWM0ZDFiMTZkNGRjOGIzNDI4NjlhM2ZlNTliYjkiLCJzY29wZSI6WyJST0xFX1VTRVIiXX0.QknsrlC7BFYukHCsFhL-XGT10j8dpOcjX1yB4_bOz9k

Note that this is very similar to the way that HTTP Basic authentication works. It also explains why the term “authorization” is used, rather than “authentication”.

For reasons of backward compatibility, OAuth may also be used instead of Bearer. Only the latter is part of the OAuth 2 standard. Note that both names are case sensitive!

With curl, a request for a user’s repertoire can be made as follows:

$ curl -X GET -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJXSHJrck9DMFNEcWY2VjNXYVRrblpRIiwiZXhwIjoxNDYzMDY1MDkyLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZDMyNDQ1YzEtMDAxYi00ZTkyLTgxOWMtOGUxZDcyMGQ1N2RmIiwiY2xpZW50X2lkIjoiZGNlOWM0ZDFiMTZkNGRjOGIzNDI4NjlhM2ZlNTliYjkiLCJzY29wZSI6WyJST0xFX1VTRVIiXX0.QknsrlC7BFYukHCsFhL-XGT10j8dpOcjX1yB4_bOz9k" \

This document explains the OAuth authorization process, up to the point of obtaining an access token. Please refer to the API documentation to find out what you can do with the API once you have obtained a valid OAuth access token.

Registering your application

In order to get started, you must first register your application with Drillster. This sounds like a lot of work, but in reality it isn’t. All you need to do is think of a name for your application or project, and provide a redirection URI, which is the page of your client application where the user is sent to after authentication and authorization, and is explained later in this document.

Screen shot

What registering does, is assign a client ID and a client secret to your application. These codes look very much like the OAuth access token. Example:

Client ID: 874a16d4ac764ce4a545f0cca4584c63
Client secret: 5782b2e7532b48b5a0798f2ad6644614

The client ID uniquely identifies your application or project in the Drillster system. The client ID is not a secret. In fact, it is included in some of the authentication steps in plain sight of the user.

The client secret is, unsurprisingly, a secret. It should only be known to the application developer, and serves as proof that the holder of the secret is in control of the application that is identified by the client ID.

Drillster currently only supports confidential clients. As defined by the OAuth specification, these are clients that are capable of maintaining the confidentiality of their credentials (client secret), typically clients implemented on a secure server. Clients that don't classify as confidential are called public clients, and can currently not use the Drillster API. Public clients are clients that cannot maintain the confidentiality of their credentials, e.g. clients executing on the device used by the user, such as a native app, or a JavaScript application.

Once you have your client ID and secret, you are ready to investigate how to obtain an access token for a user. This is done with an “authorization grant”, in OAuth-speak.

Authorization Code grant type

Although the OAuth specification defines several authorization grant types, Drillster only supports the Authorization Code grant type. This requires that your client application is capable of directing the user to the Drillster authorization server, using HTTP redirect.

From a high level, the process works as follows:

  1. The end user wants to connect a third party application to their Drillster account. The third party application makes a redirect to the Drillster OAuth authorization service. The request includes the client ID, and the URI to direct the end user back to.
  2. The end user is shown the details of your application, and the implications of agreeing to the request. If the end user agrees, the user is redirected back to the configured URI, but with an authorization code included in the URL.
  3. The third party application makes an API call to the token service to exchange the authorization code for an access token.

In order for the authorization code grant to work, the redirect URI passed in as an URL parameter must be exactly equal to the URI set in the configuration.

Here’s what the various steps look like in practice. The redirect of the user session from your application to Drillster includes four parameters:

  • client_id
  • redirect_uri
  • response_type=code
  • state

The client_id and redirect_uri are populated with the values from the client application registration page. The response_code value is “code”, to indicate that the Authorization Code grant type is used.

Although not required by the OAuth specification, it is highly recommended to use the “state” parameter, for security reasons. It is an opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The client application should verify that the returned value is identical to the originally sent value. This should be done to prevent cross-site request forgery. The value of the state parameter can be any value that allows the client application to bind the callback request to the authenticated state of the user. Obviously, it should not be possible for an attacker to know or guess the value. A random value can be used, that is bound to the user's session, or a hash of the user's session ID.

The redirect to the Drillster OAuth authorization server looks like this:

The end user will see a screen with details of your application, and a request for access to the account. The end user is told what the third party application is able to do with the account, and what the restrictions are.

Screen shot

To make the experience as pleasant as possible, it would be helpful if your application contains a good description and an icon.

If the user is already logged in into their Drillster account, the user can simply click the “allow” or “don’t allow” button. If the user is not logged in, the user is asked to log in to allow access, or click the “don’t allow” button.

A positive response causes the user to be redirected to the redirection URI as follows:

The code is the authorization code that can be exchanged for an access token. If the user clicked the “don’t allow” button, the user is also redirected back to the URI, but with an error code:

Assuming that your application has received an authorization code, you must verify that the value of the “state” parameter that is appended to the callback URI, is the same as the one you originally sent in the redirect to the Drillster authorization server. If this is not the case, or the parameter is not present, the process must be aborted.

Now, the code can be exchanged for an access token by making an API call to the token service:

$ curl -X POST \
  -d 'client_id=874a16d4ac764ce4a545f0cca4584c63' \
  -d 'client_secret=5782b2e7532b48b5a0798f2ad6644614' \
  -d 'grant_type=authorization_code' \
  -d 'code=cIEL8h'

The response could look like this:

    "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJXSHJrck9DMFNEcWY2VjNXYVRrblpRIiwiZXhwIjoxNDY1ODI5Mjc0LCJqdGkiOiIwNzBiOGE1MS1hYjFkLTRlZDktODJjZS04YzNmZTlkMTJlMmEiLCJjbGllbnRfaWQiOiIzYWFhZTU1ZDc0ZDk0NmY0YWM2NTY4YTA3MjYxMDk5ZCIsInNjb3BlIjpbIlJPTEVfVVNFUiJdfQ.DmqZWRDMV4zctJ5R_WSsn_axGzfDNGOJJO79_garrM9w8zOvd7ZmAGgtFrVVcUWjfR3AR0RaXGM3wdHoqOs2YleD_AeYcrxDPJkiUDoQXQN3I9qNsediwhcMYj9l5UYlpR6uD3lcRzkCM4L5u4PTqs2RjZL2GBgvUMeQZNowpyK_shT_o_U4Y_LFnBWFf2c9MtKhUAIuNdqQ98jAxwEnS2tO_OUFCZ2JzZyFHmteQYz8q_kl5SE0UdBXmUfl4RKmxmozKyQFIA3p56Qtl65E_t8lJQVLC0OwL-2elAJMgqQy-J-ZHB3b9SMM9HXIDe81J-Sx51-R8bK4Dx28EZIPdg",
    "expires_in": 2591999,
    "jti": "070b8a51-ab1d-4ed9-82ce-8c3fe9d12e2a",
    "refresh_token": "ca9ff8d9-c62e-424c-b57c-68f544d8d07e",
    "scope": "ROLE_USER",
    "token_type": "bearer"

Note that the authorization code is valid for one hour only. This means that the user should complete the redirection back to your application within one hour. Save interplanetary integrations, this should allow plenty of time.

Refreshing access tokens

The access tokens that Drillster issues will expire after some time, and can't be used anymore. You will notice when you make an API call with an expired access token, that it will fail. In the response when requesting a token, an “expires_in” value is included, that tells you how many seconds the access token will remain valid.

When an access token has expired, you have two options. You can initiate the Authorization Code grant another time, as explained above. This requires that the user is currently present at your web site, since he has to authenticate again. If the user is not present, you can refresh the expired access token. To do this, you need the “refresh_token” that you received when obtaining the access token. A new access token can be requested from the token service. Example:

$ curl -X POST \
  -d 'client_id=874a16d4ac764ce4a545f0cca4584c63' \
  -d 'client_secret=5782b2e7532b48b5a0798f2ad6644614' \
  -d 'grant_type=refresh_token' \
  -d 'refresh_token=ca9ff8d9-c62e-424c-b57c-68f544d8d07e'

The token server should respond with a new token, which also includes a new refresh token:

    "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJXSHJrck9DMFNEcWY2VjNXYVRrblpRIiwiZXhwIjoxNDY1ODMyMjE4LCJqdGkiOiIxZDdjM2JmNC02YWYxLTRiZmEtODMwYS0yM2FhODZhYTk4NTgiLCJjbGllbnRfaWQiOiIzYWFhZTU1ZDc0ZDk0NmY0YWM2NTY4YTA3MjYxMDk5ZCIsInNjb3BlIjpbIlJPTEVfVVNFUiJdfQ.G2wcMj0SDLmiTmpg05OWmeFPBRFWasisMvlt6JYRJuJFUI2tcEutnjt8G6WBQknz1utdCqzL8xfyavX_vFq2-37zaMFxQ0snJWABpAi_jK2FP02a5s6g0jtvlzILw6woN2cPhIMs8Ahrkr-D1P5I8j7iLq0VXhn1RPS_zusehmuI9Zu6ik7a_bRWtygQSeWf68ifmZgDGFuisSBLdgSpqwlgjf5yUPZtly1hA8K_GUyMznkJ8uqBA8nEAAIinXjUff9yASdSDZPSECuWiAOcA64i5N9ARTVPcp-nfqbxRKNboK_ZHzYXpbUfH4yPJqKE3_JTfcpNjXNK9ylu005NKQ",
    "expires_in": 2591999,
    "jti": "1d7c3bf4-6af1-4bfa-830a-23aa86aa9858",
    "refresh_token": "6d2af917-9d01-48a7-a079-072c26a6c423",
    "scope": "ROLE_USER",
    "token_type": "bearer"