<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://ktherage.github.io/fr/xsl/atom.xsl" media="all"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
  <id>https://ktherage.github.io/fr/tags/postman/</id>
  <title>Kévin THÉRAGE | Expert Symfony Developer - Postman</title>
  <subtitle><![CDATA[Kévin THÉRAGE – Expert Symfony Developer. Technical blog on Symfony, PHP, web development with tutorials, best practices and expert advice for developers.]]></subtitle>
  <link href="https://ktherage.github.io/fr/tags/postman/atom.xml" rel="self" type="application/atom+xml" />
  <link href="https://ktherage.github.io/fr/tags/postman/" rel="alternate" type="text/html" />
  <updated>2026-06-08T09:33:14+00:00</updated>
  <author>
    <name>Kévin THÉRAGE</name>
    <uri>https://ktherage.github.io/</uri>
  </author>
  <entry xml:lang="fr">
    <id>https://ktherage.github.io/fr/blog/postman-automatic-jwt-authentication-with-expired-token-refresh/</id>
    <title>Postman : Authentification JWT automatique avec renouvellement de token expiré</title>
    <published>2022-12-20T00:00:00+00:00</published>
    <link href="https://ktherage.github.io/fr/blog/postman-automatic-jwt-authentication-with-expired-token-refresh/" rel="alternate" type="text/html" />
    <content type="html">
      <![CDATA[<p>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.</p>
<hr>
<h2 id="petite-introduction">Petite introduction</h2>
<p>Vous ne savez peut-être pas ce qu'est Postman, alors je vais vous le décrire.
Vous utilisez probablement un IDE (comme PHPStorm, VSCode,…) pour vous aider pendant la phase de développement de votre projet avec des choses comme l'autocomplétion, l'exécution de tests, le débogage, etc.</p>
<p>Postman est assez similaire à un IDE mais spécialement conçu pour créer des appels API. C'est bien plus agréable à utiliser que la simple commande curl. Apprenez-en plus sur Postman en visitant leur site web <a href="https://www.postman.com/" rel="noopener noreferrer">https://www.postman.com/</a>.</p>
<p>Qu'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'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'objet JSON.
Dans 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 <a href="https://jwt.io/" rel="noopener noreferrer">https://jwt.io/</a>.</p>
<hr>
<h2 id="le-voyage-vers-ce-monde-magique">Le voyage vers ce monde magique</h2>
<h3 id="au-debut-etait-la-requete-manuelle">Au début, était la requête manuelle</h3>
<p>En tant que développeur web, j'ai l'habitude d'appeler des API (les miennes ou celles de tiers) qui nécessitent un JWT, et je les teste généralement avec Postman.
Pendant de nombreux mois, ou peut-être des années, appeler un point de terminaison sur ces types d'API m'a amené à appliquer manuellement le workflow suivant :</p>
<ol>
<li>Obtenir un token via une requête enregistrée attachée à ma collection Postman (essentiellement m'authentifier auprès de mon API)</li>
<li>Copier la chaîne du token</li>
<li>Créer un en-tête « Authorization »</li>
<li>Coller la chaîne du token comme token « Bearer » comme valeur de mon en-tête « Authorization » (exemple d'en-tête : « Authorization:Bearer tokenCopié »)</li>
<li>Enfin, appeler mon point de terminaison</li>
</ol>
<p>Ce workflow m'obligeait également à mettre à jour manuellement le token JWT lorsqu'il avait expiré. Avec le temps, je suis devenu un peu plus malin en utilisant les variables d'environnement de Postman pour stocker la bonne chaîne de token dans l'environnement approprié (comme avoir un JWT pour l'environnement de staging et un pour la production).</p>
<p>Mais il y a quelques mois, je me demandais si, aussi paresseux que je suis, il n'y avait pas une meilleure façon de faire ? J'ai aussi entendu des légendes sur certains développeurs qui appellent leurs API sans se soucier de l'authentification. Alors pourquoi pas moi ?</p>
<h3 id="puis-est-venue-la-requete-automatique">Puis est venue la requête automatique</h3>
<p>Donc, comme tout bon développeur (ou pas 😛), mon voyage a commencé sur… (vous l'avez deviné 😉 ?) Stack Overflow !</p>
<p>J'ai trouvé cet article là-bas, et même si ce n'était pas la bonne solution, il m'a donné une idée plus claire de l'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 😅.</p>
<p>J'ai donc poursuivi ma quête, et j'ai trouvé l'article medium d'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'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.</p>
<p>Super plus, il y a un morceau de code ! Je l'ai donc copié/collé, suivi les étapes, adapté à mes cas d'utilisation, et ça a marché 🎊 🎉 🪩 !</p>
<p>Je n'y suis jamais revenu jusqu'à… ce que je perde ce script de pré-requête à cause d'une réinstallation de Postman et de l'absence de version payante 🫣 😩.</p>
<p>Cela 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'était automatique.</p>
<h3 id="enfin-la-consecration">Enfin, la consécration</h3>
<p>Donc, une fois de plus, j'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'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'authentifiant pas toujours auprès de l'API quand le token est encore valide (c'est-à-dire pas expiré).</p>
<p>Ce code peut être trouvé ici : <a href="https://gist.github.com/Glideh/0f24b8973bb7d79ae8124fa160966df1" rel="noopener noreferrer">https://gist.github.com/Glideh/0f24b8973bb7d79ae8124fa160966df1</a></p>
<p>Le seul inconvénient que j'ai trouvé en l'utilisant directement est qu'il ne profitait pas du refresh token JWT. Je l'ai donc copié/collé et j'ai fait quelques modifications pour permettre un rafraîchissement automatique du token.</p>
<hr>
<h2 id="le-code">Le code</h2>
<p>Pour obtenir un tutoriel complet sur la façon de définir le code suivant comme script de pré-requête Postman, lisez l'article medium d'Utkarsha Baksh : « Using Postman Pre-request Script to Automatically Set Token »</p>
<pre><code class="language-javascript hljs javascript" translate="no"><span class="hljs-comment">/**
 * fill in the blanks
 */</span>
<span class="hljs-keyword">const</span> TOKEN_ENV_VAR_NAME = <span class="hljs-string">'token_client'</span>
<span class="hljs-keyword">const</span> LOGIN_URL = pm.environment.get(<span class="hljs-string">"host"</span>) + <span class="hljs-string">"/api/v2/authenticate"</span>
<span class="hljs-keyword">const</span> LOGIN_BODY={
    <span class="hljs-string">"app_id"</span>: pm.environment.get(<span class="hljs-string">"app_id"</span>),
    <span class="hljs-string">"app_secret"</span>: pm.environment.get(<span class="hljs-string">"app_secret"</span>)
}

<span class="hljs-keyword">const</span> REFRESH_TOKEN_ENV_VAR_NAME = <span class="hljs-string">'refresh_token_client'</span>
<span class="hljs-keyword">const</span> REFRESH_URL = pm.environment.get(<span class="hljs-string">"host"</span>) + <span class="hljs-string">"/api/v2/authenticate/refresh"</span>
<span class="hljs-keyword">const</span> REFRESH_BODY={
    <span class="hljs-string">"refreshToken"</span>: pm.environment.get(REFRESH_TOKEN_ENV_VAR_NAME)
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isExpiredToken</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> jwt = pm.environment.get(TOKEN_ENV_VAR_NAME)
    <span class="hljs-keyword">const</span> payload = <span class="hljs-built_in">JSON</span>.parse(atob(jwt.split(<span class="hljs-string">'.'</span>)[<span class="hljs-number">1</span>]));
    <span class="hljs-comment">// Expiration timestamp (in seconds) is located in the `exp` key</span>
    <span class="hljs-keyword">const</span> millisecBeforeExpiration = (payload.exp * <span class="hljs-number">1000</span>) - (<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()).getTime();
    <span class="hljs-keyword">if</span> (millisecBeforeExpiration &lt;= <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Token is expired"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Token is still valid ! Expiring in <span class="hljs-subst">${millisecBeforeExpiration <span class="hljs-regexp">/ 1000} seconds`);
    return false;
}

function tokensExists() {
    const token = pm.environment.get(TOKEN_ENV_VAR_NAME)
    const refreshToken = pm.environment.get(REFRESH_TOKEN_ENV_VAR_NAME)
    if (!token) {
        console.log("Token not found");
        return false;
    }

    if (!refreshToken) {
        console.log("Refresh token not found");
        return false;
    }

    return true;
}

function login() {
    console.log("Authenticating")
    const body = JSON.stringify(LOGIN_BODY);
    const request = {
        url: LOGIN_URL,
        method: "POST",
        header: {
            "Content-Type": "application/</span>json<span class="hljs-string">",
            "</span>Accept<span class="hljs-string">": "</span>application<span class="hljs-regexp">/json",
        },
        body,
    };

    pm.sendRequest(request, (err, res) =&gt; {
        if (err || res.code !== 200) {
            console.log("Login failed:");
            console.log(err);
            console.log(res);

            throw new Error('Login failed, check postman\'s console for details')
        }
        pm.environment.set(TOKEN_ENV_VAR_NAME, res.json().token);
        console.log("Token saved");
        pm.environment.set(REFRESH_TOKEN_ENV_VAR_NAME, res.json().refreshToken);
        console.log("Refresh Token saved");
    });
}

function refresh() {
    console.log("Refreshing token")
    const body = JSON.stringify(REFRESH_BODY);
    const request = {
        url: REFRESH_URL,
        method: "POST",
        header: {
            "Content-Type": "application/</span>json<span class="hljs-string">",
            "</span>Accept<span class="hljs-string">": "</span>application<span class="hljs-regexp">/json",
        },
        body,
    };

    pm.sendRequest(request, (err, res) =&gt; {
        if (res.code === 498) {
            console.log('Refresh token has expired or is invalid')
            login()
            return
        }
        if (err || res.code !== 200) {
            console.log("Refreshing token failed:");
            console.log(err);
            console.log(res);

            throw new Error('Refreshing token failed, check postman\'s console for details')
        }
        console.log("Token refreshed");
        pm.environment.set(TOKEN_ENV_VAR_NAME, res.json().token);
    });
}

if (tokensExists()) {
    if (!isExpiredToken()) {
        return
    }

    refresh()
} else {
    login()
}</span></span></span></code></pre>
<hr>
<h2 id="remerciements">Remerciements</h2>
<p>Postman pour avoir produit des outils qui facilitent la vie des développeurs d'API</p>
<p>Stack overflow et sa communauté pour être la bouée de sauvetage des développeurs</p>
<p>Pierre de LESPINAY pour le Gist qui m'a inspiré ce morceau de code et l'article actuel</p>
<p>L'équipe SensioLabs pour leur aide et leurs relectures sur cet article</p>]]>
    </content>
  </entry>
</feed>
