// Authentication credentials.
const serviceAccountKeyID = process.env.DT_SERVICE_ACCOUNT_KEY_ID
const serviceAccountSecret = process.env.DT_SERVICE_ACCOUNT_SECRET
const serviceAccountEmail = process.env.DT_SERVICE_ACCOUNT_EMAIL
// Token refresh variables and constants.
const refreshBuffer = 60 // seconds
let expiration = 0 // unixtime
async function getAccessToken(keyID, secret, email) {
// Check if access token needs a refresh. A buffer is added.
if (expiration - Math.floor(Date.now() / 1000) < refreshBuffer) {
// Print expiration message to console.
console.log('Refreshing...')
// Fetch a new token response.
let res = await refreshAccessToken(keyID, secret, email)
// Update token and expiration.
expiration = Math.floor(Date.now() / 1000) + res.expires_in
accessToken = res.access_token
// Print time until expiration.
let sLeft = expiration - Math.floor(Date.now() / 1000) - refreshBuffer
console.log(`Token expires in ${sLeft}s.`)
async function refreshAccessToken(keyID, secret, email) {
// Construct the JWT header.
// Construct the JWT payload.
'iat': Math.floor(Date.now() / 1000), // current unixtime
'exp': Math.floor(Date.now() / 1000) + 3600, // expiration unixtime
'aud': 'https://identity.disruptive-technologies.com/oauth2/token',
// Sign and encode JWT with the secret.
const jwtEncoded = jwt.sign(
// Prepare POST request data.
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
// Converts the requestObject to a Form URL-Encoded string.
const requestData = Object.keys(requestObject).map(function(key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(requestObject[key])
// Exchange JWT for access token.
const accessTokenResponse = await axios({
url: 'https://identity.disruptive-technologies.com/oauth2/token',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}).catch(function (error) {
// Prints the error response (if any), an re-throws the error.
console.log(error.response.data)
// Return the response data.
return accessTokenResponse.data
async function functionThatCallsAPI(accessToken) {
// Use access token for calling the Rest API here.
// We'll just sleep for a few seconds.
await new Promise(r => setTimeout(r, 5000));
// Do some task, here simulated by an infite loop.
// Call some routine that needs the access token.
await functionThatCallsAPI(getAccessToken(