Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Postman pre-request script to automatically get a bearer token from Auth0 and save it for reuse
const echoPostRequest = {
url: 'https://<my url>.auth0.com/oauth/token',
method: 'POST',
header: 'Content-Type:application/json',
body: {
mode: 'application/json',
raw: JSON.stringify(
{
client_id:'<your client ID>',
client_secret:'<your client secret>',
audience:'<my audience>',
grant_type:'client_credentials'
})
}
};
var getToken = true;
if (!pm.environment.get('accessTokenExpiry') ||
!pm.environment.get('currentAccessToken')) {
console.log('Token or expiry date are missing')
} else if (pm.environment.get('accessTokenExpiry') <= (new Date()).getTime()) {
console.log('Token is expired')
} else {
getToken = false;
console.log('Token and expiry date are all good');
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function (err, res) {
console.log(err ? err : res.json());
if (err === null) {
console.log('Saving the token and expiry date')
var responseJson = res.json();
pm.environment.set('currentAccessToken', responseJson.access_token)
var expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
pm.environment.set('accessTokenExpiry', expiryDate.getTime());
}
});
}
@mokkapati
Copy link

mokkapati commented Mar 23, 2020

How to set the environment variables or setup environment for the above urlencoded code. I am getting 500 error.

@mokkapati
Copy link

mokkapati commented Mar 23, 2020

image
I am getting this error for urlencoded code

@DmitryVdovichencko
Copy link

DmitryVdovichencko commented Apr 27, 2020

Thanks! So helpful nice and simple! 👍 🤘

@ultrablue
Copy link

ultrablue commented May 5, 2020

Sooooooo helpful and sanity-saving. Thank you!!!

@aisupov
Copy link

aisupov commented May 18, 2020

Thank you!

@ANHPearce
Copy link

ANHPearce commented Jun 16, 2020

Love it

@CoreyB26
Copy link

CoreyB26 commented Jul 23, 2020

Works perfectly! I am running Postman in a CI pipeline and needed to be able to get the token automatically and the built in Authentication didn't seem to support that. Thank you for this simple implementation.

@chluther
Copy link

chluther commented Sep 2, 2020

Thank you. I've riffed off of this pattern to obtain bearer token for configuring the Akamai (Janrain) Hosted Login OIDC platform. This has been saved as a collection Pre-request Script.


// collection pre-request script
// obtain parameters from environment configuration

const uri = pm.environment.get("uri");
const customer_id = pm.environment.get("customer_id");
const config_oidc_client_id = pm.environment.get("config_client_id");
const config_oidc_client_secret = pm.environment.get("config_client_secret");
const user = btoa(pm.environment.get('config_client_id') + ':' + pm.environment.get('config_client_secret'));

const echoPostRequest = {
  url: 'https://' + uri + '/' + customer_id +'/login/token',
  method: 'POST',
  timeout: 0,
  header: {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": "Basic " + user
  },
  body: {
    mode: 'urlencoded',
    urlencoded: [
        {key: "grant_type", value: "client_credentials"},
        {key:"scope", value: "*:config/**"}
    ]}
};

var getToken = true;
if (!pm.environment.get('oidc_bearer_token_expiry') || 
    !pm.environment.get('oidc_bearer_token')) {
    console.log('Token or expiry date are missing')
} else if (pm.environment.get('oidc_bearer_token_expiry') <= (new Date()).getTime()) {
    console.log('Token is expired')
} else {
    getToken = false;
    console.log('Token and expiry date are all good');
}
if (getToken === true) {    
    pm.sendRequest(echoPostRequest, function (err, res) {
        var responseJson = res.json();
        console.log(responseJson);
        console.log(err ? err : responseJson);
            if ((err !== null) || (responseJson.error !== "invalid_client")) {
                console.log('Saving the token and expiry date')
                
                // save results to environment configuration
                pm.environment.set('oidc_bearer_token', responseJson.access_token)
    
                var expiryDate = new Date();
                expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
                pm.environment.set('oidc_bearer_token_expiry', expiryDate.getTime());
            }
            else {
                console.log(err);
                console.error('Error: ' + responseJson)
            }
    });
}

@Dumbnikko
Copy link

Dumbnikko commented Sep 22, 2020

Thanks a bunch, helped out a newbie a lot!

@mikenhill
Copy link

mikenhill commented Oct 2, 2020

I'm not sure that the token expiry logic is working as intended. The code (below) uses expiryDate.getSeconds() which returns a value in the range 0..59 the overall result of which is to set the accessTokenExpiry variable to a value which is far in excess of the actual token expiry. What this means is that the script fails to detect when the actual token has expired and attempts to keep using an expired token.
var expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
pm.environment.set('accessTokenExpiry', expiryDate.getTime());

What I believe was intended is as follows:

var expiryDate = new Date();
expiryDate = new Date(expiryDate.getTime() + (res.json().expires_in * 1000));
console.log('expiryDate: ' + expiryDate);
pm.environment.set('accessTokenExpiry', expiryDate.getTime());

Such that when I ran this at Fri Oct 02 2020 08:57:14 GMT+0100 (British Summer Time), the expiry is set as follows:
expiryDate: Fri Oct 02 2020 09:57:14 GMT+0100 (British Summer Time)

@emads3
Copy link

emads3 commented Oct 29, 2020

Thank you

@jlaguilargomez
Copy link

jlaguilargomez commented Nov 12, 2020

Thanks a lot!, it seems to work!

@AdamW00d
Copy link

AdamW00d commented Dec 3, 2020

Thank you!

@Solksjaer
Copy link

Solksjaer commented Jan 21, 2021

I modified your code a little, in order to include a KeyCloak refresh token call using Url Encoded Forms.
Also, I included an environment validation, in order to avoid autorefresh in production.

const client_id = "client_id";
const username= "username";
const allowedEnvs = ["localEnv", "dev"]

console.log("Runing on Environment: " + pm.environment.name);

if(allowedEnvs.indexOf(pm.environment.name) == -1){
    console.warn("Token Reload only allowed on: " + allowedEnvs);
    return;
}

var keycloak_url = pm.environment.get("keycloak_url") + "/auth/realms/MY_REALM/protocol/openid-connect/token";

var access_token = pm.environment.get("access_token");
var access_token_expiry = pm.environment.get("access_token_expiry");
var refresh_token = pm.environment.get("refresh_token");
var refresh_token_expiry = pm.environment.get("refresh_token_expiry");

const refreshTokenRequest = {
  url: keycloak_url,
  method: 'POST',
  header: 'Content-Type:application/x-www-form-urlencoded',
  body: {
    mode: 'urlencoded',
    urlencoded: [
        {key: "client_id", value: client_id},
        {key: "client_secret", value: pm.environment.get("client_secret")},
        {key: "refresh_token", value: refresh_token},
        {key: "grant_type", value: 'refresh_token'}
    ]
  }
};

const newTokenRequest = {
  url: keycloak_url,
  method: 'POST',
  header: 'Content-Type:application/x-www-form-urlencoded',
  body: {
    mode: 'urlencoded',
    urlencoded: [
        {key: "client_id", value: client_id},
        {key: "client_secret", value: pm.environment.get("client_secret")},
        {key: "username", value: username},
        {key: "grant_type", value: 'password'},
        {key: "password", value: pm.environment.get("user_password")}
    ]
  }
};

var sendRequest = newTokenRequest;

if (!access_token || !access_token_expiry || 
    !refresh_token || !refresh_token_expiry) {
    console.log('Tokens or expiry dates are missing');
} else if (access_token_expiry <= (new Date()).getTime() && refresh_token_expiry <= (new Date()).getTime()) {
    console.log('Access and Refresh Token expired');
} else if (access_token_expiry <= (new Date()).getTime()) {
    console.log('Access Token expired');
    sendRequest = refreshTokenRequest;
} else {
    sendRequest = null;
    console.log('Token and expiry date are all good');
}

if (sendRequest != null) {
    pm.sendRequest(sendRequest, function (err, res) {
        var responseJson = res.json();
        console.log(err ? err : responseJson);

        if (err == null && responseJson.error == null) {
            console.log('Saving tokens and expiry dates')
            
            pm.environment.set('access_token', responseJson.access_token)
            pm.environment.set('refresh_token', responseJson.refresh_token)
    
            pm.environment.set('access_token_expiry', new Date().getTime() + (responseJson.expires_in * 1000));
            pm.environment.set('refresh_token_expiry', new Date().getTime() + (responseJson.refresh_expires_in * 1000));
        }
    });
}

@Andrielson
Copy link

Andrielson commented Mar 2, 2021

It works like a charm! Thank you!

@RodolVelasco
Copy link

RodolVelasco commented Mar 17, 2021

I can get the oauth2 using postman authorization form included in Authorization tab. I would like to replicate this behaviour on pre request script and do this process automatically. You have any idea? This is to connect to Azure App Registration.

@bo55vxr
Copy link

bo55vxr commented Mar 25, 2021

@RodolVelasco

I can get the oauth2 using postman authorization form included in Authorization tab. I would like to replicate this behaviour on pre request script and do this process automatically. You have any idea? This is to connect to Azure App Registration.

I am using Azure OAuth2 tokens and basically the script is very much as described but changing the POST request.

const echoPostRequest = {
url: 'https://login.microsoftonline.com/<tenant ID>/oauth2/token','
  method: 'POST',
  body: {
    mode: 'formdata',
    formdata: [
        {key: "client_id", value:"<client ID>"},
        {key: "client_secret", value:"<client secret>"},
        {key: "resource", value:"<resource>"},
        {key: "grant_type", value:"client_credentials"}
    ]
  }
};

Hope that helps

@RodolVelasco
Copy link

RodolVelasco commented Mar 25, 2021

@bo55vxr thanks for your response.

I am using Azure OAuth2 tokens and basically the script is very much as described but changing the POST request.

const echoPostRequest = {
url: 'https://login.microsoftonline.com/<tenant ID>/oauth2/token','
  method: 'POST',
  body: {
    mode: 'formdata',
    formdata: [
        {key: "client_id", value:"<client ID>"},
        {key: "client_secret", value:"<client secret>"},
        {key: "resource", value:"<resource>"},
        {key: "grant_type", value:"client_credentials"}
    ]
  }
};

Hope that helps

I got it done with this script

var clientId = pm.variables.get("clientId");
var clientSecret = pm.variables.get("clientSecret");
var scope = pm.variables.get("scope");
var urlResource = pm.variables.get("urlResource");
var tenant = pm.variables.get("tenant");
var apiEndpointVersion = pm.variables.get("apiEndpointVersion");
pm.sendRequest({
    url: urlResource + tenant + apiEndpointVersion,
    method: "POST",
    header: [
        'Content-Type:application/x-www-form-urlencoded'
    ],
    body: {
        mode: "urlencoded",
        urlencoded: [
            {key: "client_id", value: clientId},
            {key: "client_secret", value: clientSecret},
            {key: "scope", value: scope},
            {key: "grant_type", value: "client_credentials"}
        ]
    },
},
(error, response) => {
    pm.variables.set("rawIdToken", response.json().access_token);
    pm.variables.set("refresh_token", response.json().refresh_token);
});

Where scope has this format:
22xxxxx-xxxx- ..../.default
Url resource is like:
https://login.microsoftonline.com/
apiEndpointVersion is:
/oauth2/v2.0/token
And the other variables are just their values.

@lukw4l
Copy link

lukw4l commented Apr 7, 2021

This is awesome and works like a charm, thank you very much!
I modified the script a bit (used environment variables as input and a urlencoded body) but this script was a very good starting point for further development.

@beliar91
Copy link

beliar91 commented May 11, 2021

This is super useful thank you! That's the exact thing I was looking for, helped me out a lot :).

@jcgaza
Copy link

jcgaza commented May 15, 2021

Hi, how do I add custom permissions on this script? I keep on getting an Insufficient Scope error on mine because I have permissions setup on my routes.

@tboulord
Copy link

tboulord commented Jul 2, 2021

Thank you, perfectly solve my issue (Just had to adapt with urlencoded mode to fit with Keycloack)

@DanielLaberge
Copy link

DanielLaberge commented Jul 16, 2021

For anyone wanting to use an id_token instead of an access_token, I've adapted this script to talk with AWS Cognito User Pools to exchange a refresh_token for an id_token and access_token. You could use it with most OAuth2 endpoints, not just Cognito.

https://gist.github.com/DanielLaberge/5c311b7adb835efc004fcc8e1ea7822a

Thanks for the original script, @bcnzer

@deniswou
Copy link

deniswou commented Jul 20, 2021

Thank you very much, it helped me a lot

@grempe
Copy link

grempe commented Jul 28, 2021

Here's a minor tweak on the Auth0 script that makes use of four environment specific variables you can set. This is useful if you are testing multiple environments, each with different Auth0 credentials. Only the echoPostRequest section is modified.

You'll need to set auth0_domain, auth0_client_id, auth0_client_secret, auth0_audience variables.

const echoPostRequest = {
  url: `https://${pm.environment.get('auth0_domain')}/oauth/token`,
  method: 'POST',
  header: 'Content-Type:application/json',
  body: {
    mode: 'application/json',
    raw: JSON.stringify(
    {
        "client_id": pm.environment.get('auth0_client_id'),
        "client_secret": pm.environment.get('auth0_client_secret'),
        "audience": pm.environment.get('auth0_audience'),
        grant_type:'client_credentials'
    })
  }
};

var getToken = true;

if (!pm.environment.get('accessTokenExpiry') || 
    !pm.environment.get('currentAccessToken')) {
    console.log('Token or expiry date are missing')
} else if (pm.environment.get('accessTokenExpiry') <= (new Date()).getTime()) {
    console.log('Token is expired')
} else {
    getToken = false;
    console.log('Token and expiry date are all good');
}

if (getToken === true) {
    pm.sendRequest(echoPostRequest, function (err, res) {
    console.log(err ? err : res.json());
        if (err === null) {
            console.log('Saving the token and expiry date')
            var responseJson = res.json();
            console.log(responseJson.access_token)
            pm.environment.set('currentAccessToken', responseJson.access_token)
    
            var expiryDate = new Date();
            expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
            pm.environment.set('accessTokenExpiry', expiryDate.getTime());
        }
    });
}

@parksanghun
Copy link

parksanghun commented Oct 29, 2021

Nice! Thank you!!!

@Glideh
Copy link

Glideh commented Nov 26, 2021

Good script, thx all.
One can also get the expiry from the token (if not returned explicitly by the API):

const payload = JSON.parse(atob(responseJson.access_token.split('.')[1]));
console.log(new Date(payload.exp * 1000));

Details:

  • Split the token by '.'
  • Take the payload (second element between [0]: header and [2]: signature)
  • Base 64 decode the string with atob()
  • JSON.parse() the decoded payload
  • Expiration timestamp can be found in the exp key
  • Eventually exp can be converted to a Date() multiplying it by 1000

@joelrdzdio
Copy link

joelrdzdio commented Dec 7, 2021

Very nice, I was struggling trying to do something like this, and then decided to search and see if anybody had done it already. Found it and it works great. Thank you!

@abdurayimov-work
Copy link

abdurayimov-work commented Dec 15, 2021

Here is my trick:

  1. Created an environment and variable Authorization inside it.
    https://monosnap.com/file/Vn4WvhXMNsnOFPmB4sC8GU4gilfMPz

  2. Added a folder called "User". In folder settings I defined pre-request:
    https://monosnap.com/file/AWMMTcSs6TtJw3Eqet3gMBLmOdcDA5

pm.sendRequest({
    url: 'https://' + pm.variables.get('api_domain') + '/api/auth/login',
    method: 'POST',
    header: {
        'content-type': 'application/json',
    },
    body: {
        mode: 'raw',
        raw: JSON.stringify({ 
            email: pm.variables.get('admin_email'),
            password: pm.variables.get('admin_password'),
            captcha_token: "no_for_local"
        })
    }
}, function (err, res) {
    pm.environment.set("Authorization", "Bearer " + res.json().token);
});
  1. In request created inside this folder I set this header:
    https://monosnap.com/file/H0n2VnrxU1cwriJokXvlJU7I2f6qGl

  2. Each request you created inside this folder will run above script before execution:
    https://monosnap.com/file/KK3qzgDKXj27iQqlCOgdyxDFuBtl9e

@cg-at-bespokenai
Copy link

cg-at-bespokenai commented Mar 10, 2022

amazing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment