PostmanJWTAuthentication

Postman: save a JWT access token automatically after login

The Postman test script that stores access and refresh tokens from any login response, explained line by line, plus how routeman adds it to generated collections for you.

Copying a token from a login response and pasting it into the Authorization tab is the most repeated chore in Postman. A ten-line test script on the login request fixes it for good. This post explains the script, which is the same one routeman writes into every generated collection.

The idea

  1. Set the collection's auth to Bearer Token with the value {{access_token}}. Every request inherits it.
  2. Set the login request's auth to No Auth.
  3. Add a test (post-response) script to the login request that saves the token into access_token.

The script

// store the tokens returned by this login request
let body;
try { body = pm.response.json(); } catch (e) { body = null; }

function find(obj, keys, depth) {
    if (!obj || typeof obj !== 'object' || depth > 4) return undefined;
    for (const k of keys) if (typeof obj[k] === 'string' && obj[k]) return obj[k];
    for (const v of Object.values(obj)) { const r = find(v, keys, depth + 1); if (r) return r; }
    return undefined;
}

const access = find(body, ['access_token', 'accessToken', 'access', 'token', 'jwt',
                           'id_token', 'idToken', 'key', 'auth_token', 'authToken'], 0);
const refresh = find(body, ['refresh_token', 'refreshToken', 'refresh'], 0);

if (access)  { pm.environment.set('access_token', access);  pm.collectionVariables.set('access_token', access); }
if (refresh) { pm.environment.set('refresh_token', refresh); pm.collectionVariables.set('refresh_token', refresh); }

pm.test('login returned a token', function () {
    pm.expect(access, 'no token found in the response').to.be.a('string');
});

Why it's written this way

It doesn't assume a key name

Different back-ends return the token under different keys:

Back-endResponse
djangorestframework-simplejwt{"access": "...", "refresh": "..."}
DRF authtoken{"token": "..."}
dj-rest-auth (token mode){"key": "..."}
FastAPI OAuth2 tutorial{"access_token": "...", "token_type": "bearer"}
flask-jwt-extended examples{"access_token": "..."}
Custom wrappers{"data": {"tokens": {"accessToken": "..."}}}

The script checks the common names first, then searches nested objects up to four levels deep, so all of these work without editing the script.

It doesn't crash on non-JSON

A failed login may return an HTML error page. The try/catch around pm.response.json() keeps the script from throwing, and the final pm.test reports a clear failure instead.

It writes to environment and collection variables

Environment variables are per server, so your staging token doesn't overwrite your local one. Also writing a collection variable means requests still work when no environment is selected.

Refreshing the token

For a refresh endpoint, send the stored refresh token in the body. With SimpleJWT, that's {"refresh": "{{refresh_token}}"}. Give the refresh request the same script, and the new access token replaces the old one.

Non-"Bearer" prefixes

DRF's TokenAuthentication and Knox expect Authorization: Token <key>, not Bearer. In Postman, use API Key auth with key Authorization and value Token {{access_token}}, or add the header at collection level.

Or let routeman write all of this

routeman detects your auth scheme (SimpleJWT, authtoken, Knox, flask-jwt-extended, FastAPI OAuth2, API keys, Basic, sessions), finds your login route and generates:

  • Collection-level auth with the right prefix.
  • The script above on the login request, and {{refresh_token}} in the refresh request's body.
  • A login body that uses {{username}} and {{password}} from the environment, with the password stored as a secret.
  • No Auth on public endpoints.
$ pip install routeman
$ routeman generate
✓ auth: bearer (login: POST /api/v1/auth/token/)

If it picks the wrong login route, override it with --login /api/auth/login/. See authentication in the docs.

Try routeman on your project

$ pip install routeman
$ routeman generate

Read the docs → Ask a question