{
  "data": [
    {
      "type": "blog",
      "id": "blog/2022/postman-automatic-jwt-authentication-with-expired-token-refresh",
      "url": "https://ktherage.github.io/blog/2022/postman-automatic-jwt-authentication-with-expired-token-refresh/",
      "attributes": {
        "alias": "/blog/postman-automatic-jwt-authentication-with-expired-token-refresh/",
        "title": "Postman : Automatic JWT authentication with expired token refresh",
        "date": "2022-12-20T00:00:00+00:00",
        "description": "A quick and simple way to test the performance of your HTTP calls.",
        "cover": {"image":"img/padlock-fence.jpg","alt":"Silver padlocks on green steel fence","caption":"Photo by <a href=\"https://www.pexels.com/@frank-mcintyre/\">Frank McIntyre</a> on <a href=\"https://www.pexels.com\">Pexels</a>"},
        "published": true,
        "tags": ["Postman","Authentication","API","JavaScript"],
        "excerpt": "You've always wondered how to get automatically authenticated toward your JWT API. I'll tell you how I achieved this in this article.",
        "body": "You’ve always wondered how to get automatically authenticated toward your JWT API. I’ll tell you how I achieved this in this article.\n\n---\n\n## Short Introduction\n\nYou may not know what is Postman, so I&#039;ll describe it to you.\nYou may use any IDE (like PHPStorm, VSCode,…) to help you during the development phase of your project with things like autocompletion, test runs, debugging, and so on.\n\nPostman is quite the same as an IDE but designed especially to create APIs calls. It&#039;s a lot more pleasant to use than the plain old curl command. Learn more about Postman by visiting their website https://www.postman.com/.\n\nWhat about JSON Web Tokens (shortened to JWT in the rest of this article)? JWT is an open-source industry standard that defines a self-contained (i.e. information are held by the token) way for securely transmitting information between parties as a JSON object.\nIn our case, they&#039;ll be used to give us access to an API. Learn more about JSON Web Tokens by visiting their website https://jwt.io/.\n\n---\n\n## The journey to this magical world\n\n### In the begining, was the manual request\nAs a Web Developer, I&#039;m used to call APIs (mine or third party APIs) that requires a JWT, and I usually test them using Postman.\nFor many months, or maybe years, calling an endpoint on those kinds of APIs led me to manually apply the following workflow:\n\n1. Get a token through a saved request attached to my Postman collection (basically authenticating toward my API)\n2. Copy the token string\n3. Create an &quot;Authorization&quot; header\n4. Paste the token string as a &quot;Bearer&quot; token as value for my &quot;Authorization&quot; header (header example: &quot;Authorization:Bearer pastedTokenString&quot;)\n5. Finally, request my endpoint\n\nThis workflow also had me to update manually the JWT token when it has expired. By the time, I got a bit smarter by using Postman&#039;s environment variables in order to have the right token string stored in the proper environment (like having a JWT for the staging environment and one for the production).\n\nBut some months ago I was wondering if, as lazy as I am, there was a better way to make it? I also heard legends about some dev who calls his API calls without worrying about Authentication. So why not me?\n\n### Then was the automatic request\n\nSo like any good (or not 😛) developer, my journey has started on… (already guessed it 😉?) Stack Overflow!\n\nI found this article there, and even if it was not the right solution, it gave me a clearer idea of where to search. In fact, and to be honest, I was searching for a piece of code that I could quickly copy and paste eyes closed 😅.\n\nSo I continued my quest, and I found Utkarsha Baksh&#039;s medium article &quot;Using Postman Pre-request Script to Automatically Set Token&quot; which has a perfect (and not too long) step by step tutorial. It details how to make a simple automatic login request before calling the desired API endpoint using small Postman&#039;s pre-request script. If you are new to that &quot;pre-request script&quot; concept, really shall read this article or take a look at Postman&#039;s documentation.\n\nAmazing plus, there&#039;s a piece of code! So I copy/pasted it, followed the steps, adapted it to my use cases, and it worked 🎊 🎉 🪩!\n\nI never got back on it until… I lost this pre-request script because of a Postman reinstallation and not having a paid version 🫣 😩.\n\nThis leads us to this day (2022/12/12 😉) where I was again doing the same manual routine and remembered that good old time when it was automatic.\n\n### Finally was the consecration\n\nSo another time, I packed my bag and got again on that journey to that wonderful land. The trip was a lot faster that time 😅 and I found a new piece of code that looked more detailed and more respectful of JWT&#039;s refresh mechanism by not always authenticating toward the API when the token is still valid (I mean not expired).\n\nThis code could be found there: https://gist.github.com/Glideh/0f24b8973bb7d79ae8124fa160966df1\n\nThe only cons I&#039;ve found using it directly is that it was not taking advantage of the JWT&#039;s refresh token. So I copy/pasted it and made some changes to allow an automatic refresh of the token.\n\n---\n\n## The code\nTo get a full tutorial on how to define a the following code as a Postman&#039;s pre-request script read Utkarsha Baksh&#039;s medium article: &quot;Using Postman Pre-request Script to Automatically Set Token&quot;\n\n```javascript\n/**\n * fill in the blanks\n */\nconst TOKEN_ENV_VAR_NAME = &#039;token_client&#039;\nconst LOGIN_URL = pm.environment.get(&quot;host&quot;) + &quot;/api/v2/authenticate&quot;\nconst LOGIN_BODY={\n    &quot;app_id&quot;: pm.environment.get(&quot;app_id&quot;),\n    &quot;app_secret&quot;: pm.environment.get(&quot;app_secret&quot;)\n}\n\nconst REFRESH_TOKEN_ENV_VAR_NAME = &#039;refresh_token_client&#039;\nconst REFRESH_URL = pm.environment.get(&quot;host&quot;) + &quot;/api/v2/authenticate/refresh&quot;\nconst REFRESH_BODY={\n    &quot;refreshToken&quot;: pm.environment.get(REFRESH_TOKEN_ENV_VAR_NAME)\n}\n\nfunction isExpiredToken() {\n    const jwt = pm.environment.get(TOKEN_ENV_VAR_NAME)\n    const payload = JSON.parse(atob(jwt.split(&#039;.&#039;)[1]));\n    // Expiration timestamp (in seconds) is located in the `exp` key\n    const millisecBeforeExpiration = (payload.exp * 1000) - (new Date()).getTime();\n    if (millisecBeforeExpiration &lt;= 0) {\n        console.log(&quot;Token is expired&quot;);\n        return true;\n    }\n\n    console.log(`Token is still valid ! Expiring in ${millisecBeforeExpiration / 1000} seconds`);\n    return false;\n}\n\nfunction tokensExists() {\n    const token = pm.environment.get(TOKEN_ENV_VAR_NAME)\n    const refreshToken = pm.environment.get(REFRESH_TOKEN_ENV_VAR_NAME)\n    if (!token) {\n        console.log(&quot;Token not found&quot;);\n        return false;\n    }\n\n    if (!refreshToken) {\n        console.log(&quot;Refresh token not found&quot;);\n        return false;\n    }\n\n    return true;\n}\n\nfunction login() {\n    console.log(&quot;Authenticating&quot;)\n    const body = JSON.stringify(LOGIN_BODY);\n    const request = {\n        url: LOGIN_URL,\n        method: &quot;POST&quot;,\n        header: {\n            &quot;Content-Type&quot;: &quot;application/json&quot;,\n            &quot;Accept&quot;: &quot;application/json&quot;,\n        },\n        body,\n    };\n\n    pm.sendRequest(request, (err, res) =&gt; {\n        if (err || res.code !== 200) {\n            console.log(&quot;Login failed:&quot;);\n            console.log(err);\n            console.log(res);\n\n            throw new Error(&#039;Login failed, check postman\\&#039;s console for details&#039;)\n        }\n        pm.environment.set(TOKEN_ENV_VAR_NAME, res.json().token);\n        console.log(&quot;Token saved&quot;);\n        pm.environment.set(REFRESH_TOKEN_ENV_VAR_NAME, res.json().refreshToken);\n        console.log(&quot;Refresh Token saved&quot;);\n    });\n}\n\nfunction refresh() {\n    console.log(&quot;Refreshing token&quot;)\n    const body = JSON.stringify(REFRESH_BODY);\n    const request = {\n        url: REFRESH_URL,\n        method: &quot;POST&quot;,\n        header: {\n            &quot;Content-Type&quot;: &quot;application/json&quot;,\n            &quot;Accept&quot;: &quot;application/json&quot;,\n        },\n        body,\n    };\n\n    pm.sendRequest(request, (err, res) =&gt; {\n        if (res.code === 498) {\n            console.log(&#039;Refresh token has expired or is invalid&#039;)\n            login()\n            return\n        }\n        if (err || res.code !== 200) {\n            console.log(&quot;Refreshing token failed:&quot;);\n            console.log(err);\n            console.log(res);\n\n            throw new Error(&#039;Refreshing token failed, check postman\\&#039;s console for details&#039;)\n        }\n        console.log(&quot;Token refreshed&quot;);\n        pm.environment.set(TOKEN_ENV_VAR_NAME, res.json().token);\n    });\n}\n\nif (tokensExists()) {\n    if (!isExpiredToken()) {\n        return\n    }\n\n    refresh()\n} else {\n    login()\n}\n```\n\n---\n\n## Thanks\n\nPostman for producing tools that ease API developer&#039;s life\n\nStack overflow and his community for being the developer&#039;s life-buoy\n\nPierre de LESPINAY for the Gist that inspired me this piece of code and the current article\n\nSensioLabs&#039; Team for their help and their reviews on this article"
      }
    }
  ]
}