Automated Access Token Renewal With Postman

I have been trying to automate the renewal of my FreeAgent OAuth Access Tokens whilst using Postman to develop my API requests. I am not a software developer. This has been difficult! The problems I am trying to solve are:

  • Completely hands-off OAuth Access Token renewal automation in Postman
  • Same automation for both sandbox and production environments
  • Debug logging

The overall process is:

  • Send an API request
  • Check whether the current Access Token has expired
  • If so, renew Access Token
  • If not, continue with request
  • Repeat

In order to achieve this automation, we need to:

  1. Create a Collection variable
  2. Create multiple Environment variables
  3. Create a Pre-request Script
  4. Authorise Postman via OAuth v2

*Note: this tutorial assumes that you have already created your app (e.g. Postman) via the Developer Dashboard and have you OAuth Identifier, OAuth Secret and Redirect URL. See dev docs.

In Postman:

1. Create a Collection variable

Create Collections for your sandbox and productions requests and add the following Collection variable to each:

VARIABLE: ‘ResourceKey’, VALUE: {key}
This will be used to differentiate between FreeAgent sandbox and production environments e.g. ‘ResourceKey’, ‘sand’ and ‘ResourceKey’, ‘prod’

2. Create multiple Environment variables

Create an Environment for FreeAgent and add the following Environment variables:

VARIABLE: ‘Resource_{key}’, VALUE: {api endpoint}
This will be used to send token refresh requests e.g. ‘Resource_sand’, ‘https://api.sandbox.freeagent.com/’

VARIABLE: ‘ClientId’, VALUE: {OAuth identifier}
This will be used to send token refresh requests e.g. ‘ClientId’, ‘xxxxxxxxxxxxxxxxxxxxxx’

VARIABLE: ‘ClientSecret’, VALUE: {OAuth secret}
This will be used to send token refresh requests e.g. ‘ClientSecret’, ‘xxxxxxxxxxxxxxxxxxxxxx’

VARIABLE: ‘AccessToken_{key}’, VALUE: blank
This will store our AccessToken, will be used for all future API requests and will be automatically populated when we send our first request e.g. ‘AccessToken_sand’, ‘’

VARIABLE: ‘AccessTokenIss_{key}’, VALUE: blank
This will store when our Access Token was issued, will be used to check whether our Access Token has expired and will be automatically populated when we send our first request e.g. ‘AccessTokenIss_sand’, ‘’. Note: milliseconds since 01/01/1970.

VARIABLE: ‘AccessTokenExp_{key}’, VALUE: blank
This will store how long our Access Token has before it expires e.g. ‘AccessTokenExp_sand’, ‘’. Note: seconds.

VARIABLE: ‘RefreshToken_{key}’, VALUE: blank
This will store our Refresh Token, will be used to request new Access Tokens and will be automatically populated (note: initially, manually) when we send our first request e.g. ‘RefreshToken_sand’, ‘’.

3. Create a Pre-request Script

In your Collections, add the following to the Pre-request Script tab:

const key = pm.collectionVariables.get("ResourceKey");

if (!isAccessTokenExpired(key)) return;

if (!pm.environment.has(`RefreshToken_${key}`)) throw new Error(`Unable to find the refresh token with key "RefreshToken_${key}"`);

console.log(`Renewing the access token for the resource ${pm.environment.get(`Resource_${key}`)}`);

pm.sendRequest({
    url: `${pm.environment.get(`Resource_${key}`)}v2/token_endpoint`,
    method: 'POST',
    header: {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: {
        mode: 'urlencoded',
        urlencoded: [
            { key: "client_id", value: pm.environment.get("ClientId") },
            { key: "client_secret", value: pm.environment.get("ClientSecret") },
            { key: "redirect_uri", value: "https://oauth.pstmn.io/v1/callback" },
            { key: "grant_type", value: "refresh_token" },
            { key: "refresh_token", value: pm.environment.get(`RefreshToken_${key}`) }
        ]
    }
}, function (err, res) {
    if (err) {
        throw err;
    }

    const token = res.json();

    if (token.error) {
        throw new Error(token.error);
    }

    pm.environment.set(`AccessToken_${key}`, token.access_token);
    pm.environment.set(`AccessTokenExp_${key}`, token.expires_in);
    pm.environment.set(`AccessTokenIss_${key}`, new Date().getTime());
    pm.environment.set(`RefreshToken_${key}`, token.refresh_token);

    console.log("The token was successfully renewed.");
});

function isAccessTokenExpired(key) {

    if (!pm.environment.has(`AccessTokenIss_${key}`)) {
        return true;
    } else {
        const issued = pm.environment.get(`AccessTokenIss_${key}`);
        const expires = pm.environment.get(`AccessTokenExp_${key}`) * 1000;
        const adjustment = 60 * 1000; // one minute
        const expiresTime = issued + expires - adjustment;
        const nowTime = new Date().getTime();
        return nowTime > expiresTime;
    }
}

Note: All credit for this script goes to Sergei Sergeev and his blog post: Configure Postman to be easily used with any Azure AD protected API (SharePoint, Graph, custom etc.), all I did was parameterise the Refresh Token request URL and modify how Access Token expiry checks occur.

4. Authorise Postman via OAuth

Now we need to get our first Access and Refresh Tokens for each Collection. In Collection > Authorization:

Type: OAuth 2.0
Add auth data to: Request Headers
Access Token: {{AccessToken_{{ResourceKey}}}}
Header Prefix: Bearer
Token Name: some name e.g. ‘Auth Token Sand’
Grant Type: Authorization Code
Callback URL: check ‘Authorise using browser’
Auth URL: {{Resource_{{ResourceKey}}}}v2/approve_app
Access Token URL: {{Resource_{{ResourceKey}}}}v2/token_endpoint
Client ID: {{ClientId}}
Client Secret: {{ClientSecret}}
Scope: blank
State: blank
Client Authentication: Send as Basic Auth Header

Note: The variables should turn ORANGE, if they are RED, check for typos.

Click Get New Access Token

A default browser will open and the Authroization Grant will be processed, returning both Access and Refresh Tokens to Postman. If the popup is denied, enable popups and retry.

Manually store the Refresh Token in your RefreshToken_{key} Environment variables. This will be the last time you will ever have to do this.

CONCLUSION

The next time you send any request via Postman the Pre-request Script will run, it will notice that you don’t have an Access Token issue time and automatically request a new Access Token. In doing so, its expiry time will be stored and then checked prior to all subsequent requests, and refreshed automatically if required.

Now you can play with the API without having to worry about refreshing your Access Tokens.

1 Like

There is also discussion about auto refreshing tokens by @micdev42 here: https://github.com/fac/postman-freeagent-api-collection, including an alternative script and an API Collection for Postman. Sweet :slightly_smiling_face: