OAuth 2.0 - getheimdall/heimdall GitHub Wiki

Heimdall implements two OAuth 2.0 flows: Password and Implicit

Table of Contents

Requirements

In order to the OAuth flow to be activated Heimdall needs a structure to be created. An Heimdall App must be created to consume the Api. The way to connect the App to the Api is through a Plan. The diagram that follows shows this relation.

Schema

Plan creation

A Plan must be attached to an Api, so create a Plan and select your Api when creating it.

App creation

With the Plan created, create an App and select your Plan. During the App creation a ClientID will be generated. This is the ClientID that will be used in the authorization flows.

Provider

A Provider is a REST authorization service, it will check the user credentials to allow the access to the protected resources. The Provider must accept a POST request with the user credentials to validate it.

For now the Provider creation is not available in the front end, soo the creation is done using Swagger. To do that visit <url_do_heimdall_api>:9090/v1/index.html and login with admin privileges. Look for the Provider section.

Creation

In this example we will show how to create a Provider that validates the fields "username" and "password" that are sent in the request body. Select the option "Save a new provider".

Provider

This option shows a POST request with a json body that contains your Provider info.

{
  "description": "A Simple Provider with UserName and Password",
  "name": "My Provider",
  "path": "<provider_url>",
  "providerParams": [
    {
      "location": "BODY",
      "name": "username",
      "value": ""
    },
    {
      "location": "BODY",
      "name": "password",
      "value": ""
    }
  ]
}

descrition: a simple Provider description

name: Provider's name

path: Provider's url

providerParams: a parameter list that your provider will use to authenticate the user. Each parameter has its own list of options.

providerParams.location: where in the request the info will be sent. The options are HEADER, BODY, or null (if null the info will be sent via queryParams).

providerParams.name: parameter name

providerParams.value: default value, leave blank to use the request value

Utilization

To use the Provider you are going to need its id. To access that information select the option GET - Find all providers with filter and pageable a search using the name of your provider.

[
  {
    "id": 1,
    "name": "My Provider",
    "description": "A Simple Provider with UserName and Password",
    "path": "<provider_url>",
    "providerParams": [
      {
        "id": 1,
        "name": "password",
        "location": "BODY",
        "value": "",
        "creationDate": "2020-01-01T12:00:00.000",
        "status": "ACTIVE"
      },
      {
        "id": 2,
        "name": "username",
        "location": "BODY",
        "value": "",
        "creationDate": "2020-01-01T12:00:00.000",
        "status": "ACTIVE"
      }
    ],
    "creationDate": "2020-01-01T12:00:00.000",
    "status": "ACTIVE"
  }
]

Authorization endpoints

Endpoint creation

To use the OAuth process an authorization endpoint must be created. In Heimdall we do not provide a default endpoint for that purpose but a interceptor that allows for each Api to create its own. Here we will show a default way to do it, but the user can customize at will.

1. Resource

We recommend that you create a Resource dedicated to the OAuth process. So create a OAuth Resource in youy Api.

2. Operation

In this new Resource add a Operation of type POST with path /oauth/token. At the end of this process you should see something like this in your screen:

Resource

Interceptor addition

Navigate to the Interceptors tab and select your new Resource and operation. Now add a OAuth Interceptor. The content of this Interceptor should be a json as follows.

{
  "providerId": 1,
  "typeOAuth":"AUTHORIZE",
  "privateKey": "<someKey>",
  "timeAccessToken": 600,
  "timeRefreshToken": 1800
}

providerId: your Provider id

typeOAuth: for both password and implicit flow the type should be AUTHORIZE

privateKey: your private key

timeAccessToken: expiration time in seconds for your access token

timeRefreshToken: expiration time in seconds for your refresh token (should be bigger than the time for the access token)

With that your authrization endpoint should be ready to use.

Validation

Now that the authrization endpoint the user can choose witch endpoint of the Api should be verified with the OAuth tokens. To do that the user must add a OAuth interceptor to the Operation, Resource or Plan it wants to. In the example below we will add the authentication to a Resource.

To do that navigate to the Interceptors tab and select the Resource you want to verify with Oauth and add the OAuth interceptor with the json content as follows:

{
  "typeOAuth": "VALIDATE",
  "privateKey": "<someKey>"
}

typeOAuth: the VALIDATE indicates that this resource is protected by the OAuth validation

privateKey: must be used the same private key from the AUTHORIZE Interceptor.

From this point on the setup is completed and you are ready to start one of the flows.

Flows

Password Flow

To start the Password Flow the first step is to make a POST request to the token creation url that was defined earlier. The request should be formatted as follows.

POST <gateway_url>/api_basepath/oauth/token
Content-Type: application/json
username: <userNameValue>
password: <passwordValue>
client_id: <ClientId>

{
  "grant_type": "password"
}

The expected response to this call is an access_token/refresh_token pair.

access_token: is the key used to allow the access to the resource refresh_token: key used to get another access_token once it expires

{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJncmFudF90eXBlIjoicGFzc3dvcmQiLCJpYXQiOjE1MzY2MDU2MTQsImV4cCI6MTUzNjYwNjIxNH0.BSpD-GM0nxa8ptSYXBp4jb_CgtVMtawePt7fOZ0-H1g",
  "refreshToken": "eyJhbGciOiJIUzI1NiJ9.eyJncmFudF90eXBlIjoicGFzc3dvcmQiLCJpYXQiOjE1MzY2MDU2MTQsImV4cCI6MTUzNjYwNzQxNH0.w8a2X-dd71neWfP0wrkfWSwQlj7ZyIn_Z5MNPSbBKjo",
  "token_type": "bearer",
  "expiration": 600
}

Refresh Flow

The Refresh flow is used when the access token generated by the Password Flow expires. To use this just call a POST request as shown below.

POST <gateway_url>/api_basepath/oauth/token
client_id: <ClientId>
refresh_token: <refresh_token>

{
  "grant_type": "refresh_token"
}

A new access_token/refresh_token will be generated, provided that the refresh token is valid.

Implicit Flow

To start the Implicit Flow the first step is to make a POST request to the token creation url that was defined earlier. The request should be formatted as follows.

POST <gateway_url>/api_basepath/oauth/token
Content-Type: application/json
client_id: <client_id>

{
  "grant_type": "implicit"
}

client_id: App's client id

The expected response to this call is the following json.

{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJncmFudF90eXBlIjoiaW1wbGljaXQiLCJpYXQiOjE1MzQ5NjM1NTMsImV4cCI6MTUzNDk2MzU3M30.cg0MIKNwQQyBmQvAzHCsPZxiBfOR9pV07r_AxDn7Ap4",
  "expiration": 600,
  "token_type": "bearer"
}

With the access_token in hand you can start to consume the protected resource by adding the header to the request.

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJncmFudF90eXBlIjoiaW1wbGljaXQiLCJpYXQiOjE1MzQ5NjM1NTMsImV4cCI6MTUzNDk2MzU3M30.cg0MIKNwQQyBmQvAzHCsPZxiBfOR9pV07r_AxDn7Ap4

Each token can only be used once. After consumed the token is marked as invalid and a new access token is added to the response header.

⚠️ **GitHub.com Fallback** ⚠️