{
  "data": [
    {
      "type": "blog",
      "id": "fr/blog/2022/postman-automatic-jwt-authentication-with-expired-token-refresh",
      "url": "https://ktherage.github.io/fr/blog/2022/postman-automatic-jwt-authentication-with-expired-token-refresh/",
      "attributes": {
        "alias": "/blog/postman-automatic-jwt-authentication-with-expired-token-refresh/",
        "title": "Postman : Authentification JWT automatique avec renouvellement de token expiré",
        "date": "2022-12-20T00:00:00+00:00",
        "description": "Une façon rapide et simple de tester les performances de vos appels HTTP.",
        "cover": {"image":"img/padlock-fence.jpg","alt":"Cadenas argentés sur une clôture en acier vert","caption":"Photo par <a href=\"https://www.pexels.com/@frank-mcintyre/\">Frank McIntyre</a> sur <a href=\"https://www.pexels.com\">Pexels</a>"},
        "published": true,
        "tags": ["Postman","Authentication","API","JavaScript"],
        "excerpt": "Vous vous êtes toujours demandé comment vous authentifier automatiquement auprès de votre API JWT. Je vais vous dire comment j'ai fait dans cet article.",
        "body": "Vous vous êtes toujours demandé comment vous authentifier automatiquement auprès de votre API JWT. Je vais vous dire comment j&#039;ai fait dans cet article.\n\n---\n\n## Petite introduction\n\nVous ne savez peut-être pas ce qu&#039;est Postman, alors je vais vous le décrire.\nVous utilisez probablement un IDE (comme PHPStorm, VSCode,…) pour vous aider pendant la phase de développement de votre projet avec des choses comme l&#039;autocomplétion, l&#039;exécution de tests, le débogage, etc.\n\nPostman est assez similaire à un IDE mais spécialement conçu pour créer des appels API. C&#039;est bien plus agréable à utiliser que la simple commande curl. Apprenez-en plus sur Postman en visitant leur site web https://www.postman.com/.\n\nQu&#039;en est-il des JSON Web Tokens (abrégés en JWT dans le reste de cet article) ? JWT est une norme industrielle open source qui définit un moyen autonome (c&#039;est-à-dire que les informations sont contenues dans le token) de transmettre des informations de manière sécurisée entre les parties sous forme d&#039;objet JSON.\nDans notre cas, ils seront utilisés pour nous donner accès à une API. Apprenez-en plus sur les JSON Web Tokens en visitant leur site web https://jwt.io/.\n\n---\n\n## Le voyage vers ce monde magique\n\n### Au début, était la requête manuelle\nEn tant que développeur web, j&#039;ai l&#039;habitude d&#039;appeler des API (les miennes ou celles de tiers) qui nécessitent un JWT, et je les teste généralement avec Postman.\nPendant de nombreux mois, ou peut-être des années, appeler un point de terminaison sur ces types d&#039;API m&#039;a amené à appliquer manuellement le workflow suivant :\n\n1. Obtenir un token via une requête enregistrée attachée à ma collection Postman (essentiellement m&#039;authentifier auprès de mon API)\n2. Copier la chaîne du token\n3. Créer un en-tête « Authorization »\n4. Coller la chaîne du token comme token « Bearer » comme valeur de mon en-tête « Authorization » (exemple d&#039;en-tête : « Authorization:Bearer tokenCopié »)\n5. Enfin, appeler mon point de terminaison\n\nCe workflow m&#039;obligeait également à mettre à jour manuellement le token JWT lorsqu&#039;il avait expiré. Avec le temps, je suis devenu un peu plus malin en utilisant les variables d&#039;environnement de Postman pour stocker la bonne chaîne de token dans l&#039;environnement approprié (comme avoir un JWT pour l&#039;environnement de staging et un pour la production).\n\nMais il y a quelques mois, je me demandais si, aussi paresseux que je suis, il n&#039;y avait pas une meilleure façon de faire ? J&#039;ai aussi entendu des légendes sur certains développeurs qui appellent leurs API sans se soucier de l&#039;authentification. Alors pourquoi pas moi ?\n\n### Puis est venue la requête automatique\n\nDonc, comme tout bon développeur (ou pas 😛), mon voyage a commencé sur… (vous l&#039;avez deviné 😉 ?) Stack Overflow !\n\nJ&#039;ai trouvé cet article là-bas, et même si ce n&#039;était pas la bonne solution, il m&#039;a donné une idée plus claire de l&#039;endroit où chercher. En fait, pour être honnête, je cherchais un morceau de code que je pourrais rapidement copier-coller les yeux fermés 😅.\n\nJ&#039;ai donc poursuivi ma quête, et j&#039;ai trouvé l&#039;article medium d&#039;Utkarsha Baksh « Using Postman Pre-request Script to Automatically Set Token » qui propose un tutoriel parfait (et pas trop long) étape par étape. Il détaille comment faire une simple requête de connexion automatique avant d&#039;appeler le point de terminaison API souhaité en utilisant un petit script de pré-requête Postman. Si vous êtes nouveau sur ce concept de « script de pré-requête », vous devriez vraiment lire cet article ou jeter un œil à la documentation de Postman.\n\nSuper plus, il y a un morceau de code ! Je l&#039;ai donc copié/collé, suivi les étapes, adapté à mes cas d&#039;utilisation, et ça a marché 🎊 🎉 🪩 !\n\nJe n&#039;y suis jamais revenu jusqu&#039;à… ce que je perde ce script de pré-requête à cause d&#039;une réinstallation de Postman et de l&#039;absence de version payante 🫣 😩.\n\nCela nous amène à ce jour (12/12/2022 😉) où je refaisais la même routine manuelle et me souvenais de ce bon vieux temps où c&#039;était automatique.\n\n### Enfin, la consécration\n\nDonc, une fois de plus, j&#039;ai fait mon sac et je suis reparti en voyage vers ce merveilleux pays. Le voyage a été beaucoup plus rapide cette fois 😅 et j&#039;ai trouvé un nouveau morceau de code qui semblait plus détaillé et plus respectueux du mécanisme de rafraîchissement de JWT en ne s&#039;authentifiant pas toujours auprès de l&#039;API quand le token est encore valide (c&#039;est-à-dire pas expiré).\n\nCe code peut être trouvé ici : https://gist.github.com/Glideh/0f24b8973bb7d79ae8124fa160966df1\n\nLe seul inconvénient que j&#039;ai trouvé en l&#039;utilisant directement est qu&#039;il ne profitait pas du refresh token JWT. Je l&#039;ai donc copié/collé et j&#039;ai fait quelques modifications pour permettre un rafraîchissement automatique du token.\n\n---\n\n## Le code\nPour obtenir un tutoriel complet sur la façon de définir le code suivant comme script de pré-requête Postman, lisez l&#039;article medium d&#039;Utkarsha Baksh : « Using Postman Pre-request Script to Automatically Set Token »\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## Remerciements\n\nPostman pour avoir produit des outils qui facilitent la vie des développeurs d&#039;API\n\nStack overflow et sa communauté pour être la bouée de sauvetage des développeurs\n\nPierre de LESPINAY pour le Gist qui m&#039;a inspiré ce morceau de code et l&#039;article actuel\n\nL&#039;équipe SensioLabs pour leur aide et leurs relectures sur cet article"
      }
    }
  ]
}