Geek Logbook

Tech sea log book

Automating OAuth 2.0 in Postman: storing and refreshing access tokens without copy-paste

Introduction

When working with APIs protected by OAuth 2.0, Postman is commonly used for development and testing. A frequent pain point is manual token handling: requesting an access token, copying it, pasting it into headers, and repeating the process every time it expires.
This article explains how to fully automate OAuth 2.0 token management in Postman, storing the token in variables and refreshing it automatically.

The problem

In typical OAuth 2.0 flows (client credentials, authorization code, refresh token):

  • Access tokens expire.
  • Postman can fetch them, but does not always expose them as reusable variables.
  • Manual copy/paste breaks reproducibility and automation.

The goal is to ensure that:

  1. The token is requested automatically.
  2. It is stored as a variable.
  3. All requests reuse it.
  4. It refreshes automatically when expired.

Solution 1: store the access token from the response

If your API exposes a standard OAuth token endpoint returning JSON, you can capture the token from the Tests tab.

Typical token response

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 3600,
  "token_type": "Bearer"
}

Tests script

const data = pm.response.json();

pm.environment.set("access_token", data.access_token);
pm.environment.set(
  "token_expiry_ts",
  String(Date.now() + data.expires_in * 1000)
);
pm.environment.set("token_type", data.token_type || "Bearer");

Then reuse it in requests:

  • Authorization → Bearer Token → {{access_token}}
    or
  • Custom header:
Authorization: {{token_type}} {{access_token}}

Solution 2: automatic refresh with a Pre-request Script

To avoid manually calling the token endpoint, you can validate the token before every request.

Logic

  • If no token exists, request one.
  • If the token is expired (or about to expire), refresh it.
  • If it is still valid, do nothing.

Reusable Pre-request Script

const expiry = Number(pm.environment.get("token_expiry_ts") || 0);
const now = Date.now();

if (!pm.environment.get("access_token") || now > expiry - 5000) {
  pm.sendRequest(
    {
      url: pm.environment.get("oauth_token_url"),
      method: "POST",
      header: { "Content-Type": "application/x-www-form-urlencoded" },
      body: {
        mode: "urlencoded",
        urlencoded: [
          { key: "grant_type", value: "client_credentials" },
          { key: "client_id", value: pm.environment.get("client_id") },
          { key: "client_secret", value: pm.environment.get("client_secret") }
        ]
      }
    },
    (err, res) => {
      if (err) {
        console.error(err);
        return;
      }

      const token = res.json();
      pm.environment.set("access_token", token.access_token);
      pm.environment.set(
        "token_expiry_ts",
        String(Date.now() + token.expires_in * 1000)
      );
    }
  );
}

This script is best placed:

  • At the collection level (recommended), or
  • On critical requests that require authentication.

What about Postman’s built-in OAuth 2.0?

Postman’s “Get New Access Token” feature:

  • Requests the token.
  • Automatically refreshes it when it expires.

Main limitation:

  • The token is not exposed as a variable, which makes it harder to:
    • Use custom headers.
    • Write scripts.
    • Support non-standard OAuth implementations.

For reproducible and scriptable workflows, manual scripting remains more flexible.


Best practices

  • Use collection variables when multiple requests share the same token.
  • Centralize refresh logic in a single Pre-request Script.
  • Refresh slightly before expiration to avoid race conditions.
  • Never hardcode tokens in requests.

Conclusion

Automating OAuth 2.0 in Postman removes friction, manual errors, and wasted time.
With a few scripts, Postman behaves like a fully automated OAuth client, suitable for development, QA, and technical documentation.