skip to content

Fetching a Token First

Wiring a credential the run has to go and get: one script fetches it, a store carries it, the helper reads it. Interviewers ask where that script hangs, because the obvious place reruns it every time.

part ofAPI & DB clientsoverview, primer and where to startread it →
on this pageshow

explore

questions

4

In a Postman collection, how does a token a pre-request script just fetched reach the oauth2 accessToken attribute?

level: middleimportance: must knowfreq 62%

answer

  1. Three parts, joined by a name
  2. The attribute holds a placeholder, not a credential
  3. Something happens to the auth before signing
  4. resolveVariables rebuilds the RequestAuth
  5. Resolve first, then the handler's sign hook

basics

~20 s

A pre-request script stores the fetched token in a variable scope; the collection's oauth2 accessToken attribute holds a brace token naming it. The runtime resolves auth variables before the handler signs, so signing sees the real value.

solid answer

~40 s

Three parts joined by indirection. An `event` with `listen: "prerequest"` runs a script that fetches the token and writes it into a scope through `pm.environment`, `pm.collectionVariables` or `pm.globals`. The collection's `auth` block declares `type: "oauth2"` with an `accessToken` attribute whose value is not the credential but a brace token, `{{access_token}}`. Preparing each request, the runtime calls `resolveVariables`, which rebuilds the item and a fresh `RequestAuth` through the SDK's `Property#toObjectResolved`. Only then do the pre-send helpers hand the resolved parameters to the `oauth2` handler's `sign`, which reads `accessToken` and writes the credential onto the request. Resolve, then sign — the handler never sees a brace token and never reads a variable scope itself.

code

json · 18 lines
json
{
  "auth": {
    "type": "oauth2",
    "oauth2": [
      { "key": "accessToken", "value": "{{access_token}}", "type": "string" },
      { "key": "addTokenTo", "value": "header", "type": "string" }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": ["pm.collectionVariables.set('access_token', 'from-the-fetch');"]
      }
    }
  ]
}

go deeper

for a junior

Be ready to say that the auth attribute holds a variable name in double braces, not the credential, and that a pre-request script is what puts the value under that name.

for a middle

Explain the ordering: the runtime rebuilds the item and the auth with variables resolved, and only then calls the handler's sign hook. Name the three scopes a script can write into.

for a senior

Show how you debug a signed-but-refused run: compare the key the script writes with the brace token in the auth attribute, and know the handler bails only on a falsy value.

for a principal

Own the argument for keeping acquisition and consumption joined only by a variable name, so the fetch strategy and the carriage switch can each change without touching the other.

## The wiring in one line A collection that goes and gets its own credential has **three moving parts and one join**: a script that fetches the token, a variable scope that carries it, and an auth block that reads it back by name. The join is a **brace token** — the `accessToken` attribute holds `{{access_token}}`, never the credential itself. ## Where each part is declared | Part | Declared as | Whose surface it is | |---|---|---| | the fetch | an `event` entry with `listen: "prerequest"` and a `script` | the collection **format** | | the store | `pm.environment`, `pm.collectionVariables` or `pm.globals` | the **sandbox** | | the read | an `oauth2` array entry with `key: "accessToken"` | the format declares the array; the **runtime** handler reads the key | | the signature | the `oauth2` handler's `sign` hook | the **runtime** | That last row is worth pausing on. The format's `auth` object declares a `type` plus a same-named array of `{key, value}` attributes, and its schema does not enumerate the attribute keys — the key that matters is the one the runtime's `oauth2` handler actually asks for, which is `accessToken` (alongside `addTokenTo`, `tokenType` and `headerPrefix`). ## What happens between the script and the send 1. For each item the runtime queues a `prerequest` event and executes every listener it finds for that item, including listeners declared on its ancestors. Writes the script makes through `pm.environment`, `pm.collectionVariables` or `pm.globals` are carried forward in the run's context. 2. The runtime then enters its `request` step, which calls `resolveVariables`. That rebuilds the item through the SDK's `Property#toObjectResolved` **and rebuilds the auth**, constructing a fresh `RequestAuth` resolved against the same variable definitions. 3. Only then does the runtime enter the HTTP step and run its pre-send helpers. One of them looks up a handler for `auth.type`, calls the handler's `pre`, and — if that gives a go — calls `sign`. 4. `sign` reads `accessToken`, `addTokenTo`, `tokenType` and `headerPrefix` off the auth. By that point `accessToken` is the literal token string, because step two already substituted it. **Resolve, then sign.** That ordering is the whole answer. The handler never sees a brace token and never consults a variable scope on its own — it is handed parameters that are already values. ## Why the indirection instead of writing the header by hand A script *could* build an `Authorization` header itself. When an auth block is also declared, that is actively worse: - The `oauth2` handler's `sign` clears conflicting carriage before it writes: it calls `request.removeHeader('Authorization', { ignoreCase: true })` and `request.removeQueryParams(['access_token'])`. A header the script set by hand is deleted, not merged. - `addTokenTo` chooses between the header and an `access_token` query parameter, and `headerPrefix` controls the prefix that precedes the value. A hand-written header honours neither switch. - Every request that inherits the collection's auth is signed for free; nothing is repeated per item. - The exported collection file carries a variable *name*, not a credential. ## What breaks, and what it looks like - **Name mismatch.** The script writes `token`; the attribute says `{{access_token}}`. Nothing throws. The handler bails out only when `accessToken` is falsy, and an unsubstituted brace string is not falsy — so the request goes out signed with the literal placeholder and the server answers with a rejection. Grep the script and the auth block for the same key when a run signs but is refused. - **Wrong hook.** Only a `prerequest` listener runs before the send. A script hung on `test` fetches the token after the request it was meant to sign has already gone. - **Wrong scope.** The token has to land in a scope the run still holds when the request step runs; a value that dies with the script's own execution is gone before signing. - **Wrong placement.** Declared on the collection, the fetch is part of every item's pre-request work, so the identity service is called once per request in the run. ## The shape to remember The script's job is not to sign anything. Its job is to put a value under a name. The auth block's job is not to fetch anything. Its job is to name the value it wants. The runtime joins the two by substituting variables into the auth immediately before it hands the auth to the handler that signs. Keep the two halves loosely coupled through that name and both halves stay simple: the script can change how it acquires the credential without touching the auth block, and the auth block can move between the header and a query parameter without touching the script.

  • The script sets the variable, the run signs, and the server still rejects it. What do you check first?
    That both halves spell the same name. The handler bails out only when `accessToken` is falsy, and an unsubstituted `{{access_token}}` is a non-empty string — so a key typo produces a request signed with the literal placeholder and refused by the server, with no error from the collection itself. Compare the key the script writes against the brace token in the auth attribute.
  • Why not have the pre-request script set the Authorization header directly instead?
    Because the `oauth2` handler's `sign` clears conflicting carriage before it writes: it removes the `Authorization` header ignoring case, and removes an `access_token` query parameter. A header the script set by hand is deleted, not merged. Writing the header by hand also throws away `addTokenTo` and `headerPrefix`, the switches that decide where and how the credential is carried.
  • Does the handler re-read the variable scope if the value changes mid-request?
    No. Resolution happens once, when the runtime rebuilds the item and the auth for that request. The handler is handed parameters that are already values — it has no access to a variable scope. Anything written to a scope after that point affects the next request, not the one being signed.

The script leaves the key under a named mat; the auth block only knows the mat's name, and someone lifts the mat on the way out the door.

saying these in an interview costs you the question

  • Thinks the auth handler reads variable scopes itself at sign time
  • Believes the accessToken attribute stores the literal credential in the file
  • Says the script must set the Authorization header when auth is declared
  • Assumes braces inside an auth block reach the wire unresolved
  • Confuses the fetch script with the auth block that consumes its value
open as a page

In a Postman collection, why put a brace token in the oauth2 accessToken attribute instead of pasting a credential?

level: juniorimportance: should knowfreq 50%

basics

~20 s

A brace token binds late: the exported file carries only a variable name, and whatever a pre-request script most recently stored under it signs the next request. A pasted credential is frozen into the file and goes stale.

open as a page

In a Postman collection, what does hanging the token-fetch pre-request script on the collection cost?

level: middleimportance: should knowfreq 55%

basics

~20 s

A prerequest event declared on the collection runs before every request in the run, so a token-fetch script there makes one extra call per request. Moving it to a folder, or caching the token in a variable, removes that.

open as a page

Your Postman collection calls the token endpoint once per request in a run. How do you fix that?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Find the prerequest event that fetches the token; on the collection it is gathered for every item. Move it down to the folder that holds the authenticated requests, or guard it with a cached token and a stored expiry.

open as a page