Client Credentials

Obtaining an access token for a privileged API client

Introduction

In this guide you will learn how an application can use a provided client id and client secret to obtain an OAuth Access Token using the client_credentials grant flow.

An API client uses the client_credentials grant flow when it needs to perform actions without delegated authority from an authenticated user.

The client_credentials grant flow is very simple. The client sends its client ID and client secret to the IBM Security Verify OAuth 2.0 token endpoint and an Access Token is returned.

Pre-requisites

Before an application can obtain an Access Token using the the client credentials grant flow, you must obtain a client id and client secret for your application. If you have administrator access to your Verify tenant, check out Create a privileged API Client. Otherwise, you'll need to ask an administrator to do this for you.

To use the curl examples in this guide you will need the curl utility to call make HTTP calls to REST APIs. Curl is pre-installed on most Linux systems and on MacOS. However, if necessary, you can download curl here.

To use the curl+jq examples in this guide you will also need the jq utility to parse JSON responses from REST API calls. You can download jq here.

Variables

The following variables are needed to run the flow described in this guide:

VariableExample ValueDescription
tenant_urltenant.verify.ibm.comThe URL of your IBM Security Verify tenant.
client_id12345678-1234-1234-1234-123456789012The Client ID generated by IBM Security Verify when the API client is created.
client_secretabcd1234The Client Secret generated by IBM Security Verify when the API client is created.

If you're going to use these variables on the command line with curl, you should export them with these commands:

export tenant_url=tenant.verify.ibm.com
export client_id=12345678-1234-1234-1234-123456789012
export client_secret=abcd1234

Run the flow

The client credentials flow is a simple flow with one call to the OAuth Token endpoint.

The HTTP request has the following format:

POST /v1.0/endpoint/default/token HTTP/1.1
Host: {tenant_url}
Content-Type: application/x-www-form-urlencoded
Content-Length: xxx

grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}

The REST API response has the following format:

{
  "access_token":"xxxxxxxxxxxxxxxxxxxxxxx",
  "grant_id":"xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token_type":"Bearer",
  "expires_in":7200
}

The access token can be extracted from the access_token element of the response.

📘

No refresh token is returned

No refresh token is returned when using the client_credentials grant type. When the Access Token expires, the client simply requests a new token by running the client_credentials flow again.

Using curl to make the request

You can make the token request with curl:

curl -X POST https://${tenant_url}/v1.0/endpoint/default/token -d "client_id=${client_id}&client_secret=${client_secret}&grant_type=client_credentials"

The JSON response is returned to the console. You can copy the access token from here.

Use jq to parse the response

If you have the jq utility, you can use this to parse the JSON response and extract the access_token value. This can then be directly populated into the access_token environment variable for future use:

export access_token=`curl -X POST https://${tenant_url}/v1.0/endpoint/default/token -d "client_id=${client_id}&client_secret=${client_secret}&grant_type=client_credentials" | jq -r .access_token`
echo ${access_token}

Using JavaScript

You can run the client_credentials grant type flow using any language that supports making HTTP requests. Here is JavaScript code that will get an access token:

//Pre-requisites
//var axios = require('axios');
//var qs = require('qs');
//var tenant_url = "Tenant URL";
//var client_id = "Client ID";
//var client_secret = "Client Secret";

var data = {
 'grant_type': 'client_credentials',
 'client_id': client_id,
 'client_secret': client_secret 
};

var request = {
  method: 'post',
  url: 'https://' + tenant_url + '/oidc/endpoint/default/token',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  data : qs.stringify(data)
};

axios(request).then((response) => {
  var tokenData = response.data;
  var access_token = tokenData.access_token;
  console.log(access_token);
  
  //Next code here.
  
}).catch((error) => {
  console.log(error);
});

The expires_in value is the number of seconds until the token expires but note that the time the token was generated is not recorded. It is a good idea to convert this time to an absolute expiry time when receiving a new token.

// Add absolute expiry time to the token data.
// Calculated from current time and expires_in
var date = new Date();
tokenData.expirytime = date.getTime() + (tokenData.expires_in * 1000);

💎

Jon Harry, IBM Security