Scripts pre-request et test dans Postman

Les scripts pre-request permettent d’exécuter du code JavaScript avant une requête, ou avant n’importe quelle requête d’une collection.

Les scripts test permettent d’exécuter du code JavaScript après une requête, ou après n’importe quelle requête d’une collection.

OIDC - get token

J’utilise les scripts test pour sauvegarder les tokens JWT après l’authentification.

if (pm.response.code < 300) {
  pm.collectionVariables.set("access_token", pm.response.json().access_token);
  pm.collectionVariables.set("refresh_token", pm.response.json().refresh_token);
}

Ça permet à n’importe quelle autre requête d’être authentifiée grâce à un bearer token et à la variable {{access_token}}.

OIDC - refresh token

Les scripts pre-request peuvent être utilisés pour renouveler automatiquement un token d’accès.

Decode

La première étape est de récupérer le token dans sa variable et de le décoder.

const access_token = pm.collectionVariables.get('access_token');
const [header, payload, signature] = access_token.split('.');
const decodedPayload = JSON.parse(
  CryptoJS.enc.Utf8.stringify(
    CryptoJS.enc.Base64.parse(payload)
  ));

Expiry

On peut ensuite vérifier l’expiration du token.

if (decodedPayload.exp < new Date().getTime()/1000) {
  // ...
}

Refresh

Et si le token a expiré, on envoie une requête de renouvellement au serveur d’autorisation, en lui passant

    pm.sendRequest({
        url:  'https://<host>:<port>/auth/realms/<realm>/protocol/openid-connect/token',
        method: 'POST',
        header: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: {
            mode: 'formdata',
            formdata: [
                {'key': 'refresh_token',  'value': pm.collectionVariables.get('refresh_token')},
                {'key': 'grant_type',  'value': 'refresh_token'},
                {'key': 'client_id',  'value': 'jtips'},
                {'key': 'client_secret',  'value': pm.collectionVariables.get('client_secret')}
            ]
        }
    }, function (err, res) {
        if (!err) {
            pm.collectionVariables.set("access_token", res.json().access_token);
            pm.collectionVariables.set("refresh_token", res.json().refresh_token);
        } else {
            console.log('err:', err);
        }
    });

Bearer

Ce script peut être placé au niveau de la requête ou de la collection. Dans ce cas, la requête n’est utile que pour les requêtes qui utilisent le token. On peut le vérifier en début de script.

if (!pm.request.auth || pm.request.auth.type !== 'bearer') {
    return;
}

Synthèse

Voici le script que j’utilise au niveau de ma collection.

// La requête a-t-elle besoin d'un jeton ?
if (!pm.request.auth || pm.request.auth.type !== 'bearer') {
    console.log('Skip oidc');
    return;
}

// Est-ce qu'il y a déjà un jeton d'accès ?
const access_token = pm.collectionVariables.get('access_token');
if (!access_token) {
    console.log('No access token');
    return;
}

// On décode le jeton...
const [header, payload, signature] = access_token.split('.');
const decodedPayload = JSON.parse(
  CryptoJS.enc.Utf8.stringify(
    CryptoJS.enc.Base64.parse(payload)
  ));

// Est-ce qu'il a expiré ?
if (decodedPayload.exp < new Date().getTime()/1000) {
    console.log('Access token expired');
    // On envoie la requête de renouvellement de jeton
    pm.sendRequest({
        url:  'http://localhost:8081/oauth2/token',
        method: 'POST',
        header: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: {
            mode: 'formdata',
            formdata: [
                {'key': 'refresh_token',  'value': pm.collectionVariables.get('refresh_token')},
                {'key': 'grant_type',  'value': 'refresh_token'}
            ]
        }
    }, function (err, res) {
        // Si tout va bien, on remplace les anciens jetons
        if (!err) {
            pm.collectionVariables.set("access_token", res.json().access_token);
            pm.collectionVariables.set("refresh_token", res.json().refresh_token);
        } else {
            console.log('err:', err);
        }
    });

}