Disruptive Technologies Disruptive Developers

Authentication

The recommended way to Authenticate a client of our API is to use a Service Account together with a JWT, OAuth2, flow.

Step 1 - Create JWT

The client creates a JWT with Service Account details and sign it with a shared secret


Step 2 - Exchange JWT for Access Token

The client exchanges the JWT for a bearer Access Token that is valid for 1 hour


Step 3 - Access API with Access Token

The client accesses the API with a bearer Access Token HTTP header


Technical Description

Using a Service Account key and secret, you can request an Access Token for your application to authenticate. This Access Token has an expiry of one hour.

In order to get an Access Token for your application, you will have to create and sign a JSON Web Token (JWT), and send it to our oauth2 endpoint.

For a great overview of what JWT is, and an exhaustive list of client libraries, please see jwt.io.

Our oauth2 endpoint is located at https://identity.disruptive-technologies.com/oauth2/token, and we expect tokens with the following structure:

1
2
3
4
{
  "alg": "HS256",
  "kid": "<Your Service Account Key ID>"
}

Payload

1
2
3
4
5
6
{
  "iat": 1525392000,
  "exp": 1525395600,
  "aud": "https://identity.disruptive-technologies.com/oauth2/token",
  "iss": "<Your Service Account email>"
}

Valid iat and exp

  1. The iat and exp are in a standard unix timestamp format (seconds since January 1, 1970) and is for the sent JWT.

  2. Maximum allowable duration between iat and exp is 1 hour.

Please also note that some standard libraries (like JavaScripts getTime()) do not return seconds by default.

Request

When the token is signed and encoded, you will have a string which could look like this: eyJhIjoiYiIsImFsZyI6IkhTMjU2In0.eyJjIjoiZCJ9.NvnVo_-CTjzxbrpgfP5O3H1bsmo4SCkEt7h7GWUu4M0

The following body form-data parameters (query parameters are not supported) should be in a HTTP POST request to the oauth2 endpoint:

Parameter Value
grant_type urn:ietf:params:oauth:grant-type:jwt-bearer
assertion the JWT, e.g. eyJhIjoiYiIsImFsZyI6IkhTMjU2In0.eyJjIjoiZCJ9.NvnVo_-CTjzxbrpgfP5O3H1bsmo4SCkEt7h7GWUu4M0

Response

The response will be on the form

1
2
3
4
5
{
  "access_token": "0123456789abcdef",
  "token_type": "bearer",
  "expires_in": 3600
}

The expires_in of the received JWT is independent of the configured iat and exp on the sent JWT. The received token will always expire in one hour.

Note: We currently only return an Access Token, and not a Refresh Token. This means that a new Access Token needs to be requested by the client before it expires (within one hour from getting the previous one) to guarantee uninterrupted operation.

Code Example

In order to follow this example, you must have created a Service Account and key as described in the code example and noted down the Key Secret for a Key ID, this is needed later.

Prerequisites

To try out this code example you need to have Python 3 installed.

Create a new folder for this example open a command line console in this folder, run the following 3 lines:

1
2
3
python3 -m venv venv
source venv/bin/activate
pip3 install requests sseclient-py pyjwt

This will

  1. setup a standard Python 3 virtual environment (or venv),
  2. activate this environment and finally
  3. install the required packages via the built in Python package manager.

Keep this console window open as we will use it to run the example.

Code

The following is a demonstration of first getting an Access Token, and then using this Access Token to list the Projects which the Service Account has access to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from datetime import datetime, timedelta
from urllib.parse import urlencode

import jwt
import requests

# Change these to fit the service account you set up
sa_email = "b9u4gfj24te000b24tg0@b99n4us05d8g00f85uig.serviceaccount.d21s.com"
key_id = "b9u4gmb24te000b24teg"
key_secret = "781884dde7b74c259dd3a8874b8b7627"


auth_endpoint = "https://identity.disruptive-technologies.com/oauth2/token"

api_root = "https://api.disruptive-technologies.com/v2"
projects_api = api_root + "/projects"

now = datetime.now()

headers = {
#   "alg" is configured during jwt.encode(...) below
    "kid": key_id
}

payload = {
    "iat": now,
    "exp": now + timedelta(hours=1),
    "aud": auth_endpoint,
    "iss": sa_email
}

encoded_jwt = jwt.encode(payload=payload,
                         key=key_secret,
                         algorithm='HS256',
                         headers=headers)

token_response = requests.post(url=auth_endpoint, data={
    "assertion": encoded_jwt,
    "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer"
}).json()

# This is our access token
access_token = token_response["access_token"]

# Now let's list out the projects

# It can be used as a query string parameter:
projects = requests.get(projects_api + "?" + urlencode({"token": access_token})).json()
print("Request projects via query parameter ({}?token={}):".format(projects_api, access_token))
print(projects)
print()

# Or we can use it as a header:
projects = requests.get(projects_api, headers={"authorization": "bearer " + access_token}).json()
print("Request projects via header ('authorization': 'bearer {}'):".format(access_token))
print(projects)