skip to content

A request under an authenticated Postman collection is going out unsigned — how would you trace the cause?

level: seniorimportance: should knowfreq 36%

answer

  1. Only two histories produce an unsigned request
  2. Walk outward, stop at the first string type
  3. Null and absent levels are transparent
  4. A noauth folder ends the search early
  5. Tree position is part of the configuration

basics

~20 s

Reconstruct the lookup by hand: read the request's auth, then each enclosing folder outward, then the collection root. The first block whose type is a real string wins, and a noauth block on that path stops the search.

solid answer

~40 s

There are only two ways a request under an authenticated collection ends up unsigned, and they are distinguishable by reading the file. Either **something nearer declared `noauth`**, which is a valid type, so the lookup stopped there and the root's block was never reached; or **nothing on the path qualified at all**, in which case `getAuth()` returned `undefined` and the runtime skipped its authorization step. Trace it by walking outward exactly as the SDK does: the request's own `auth`, then the innermost enclosing folder, then each folder above, then the root — stopping at the first block whose `type` is a non-empty string. Remember that a missing `auth`, an `"auth": null` and a `{ "type": null }` are all transparent and keep the walk going, so they are never the culprit on their own.

go deeper

for a junior

Be ready to describe the search direction and stop condition: start at the request, move outward through folders to the root, and take the first block whose type is a real name.

for a middle

Be ready to name the two distinct unsigned outcomes — a nearer noauth that ended the walk, and an exhausted walk that resolved nothing — and to say which shapes in the file are transparent to the search.

for a senior

Be ready to run the trace on a real collection and explain why neither outcome produces a warning, so the diagnosis is done by reading the document rather than by inspecting run output.

for a principal

Be ready to argue for conventions that keep this traceable at team scale: explicit opt-outs, few declaration sites, and treating a request's move between folders as a reviewable configuration change.

## Two different unsigned requests A request that arrives at a service with no credentials, under a collection that clearly declares some, has one of two histories. Telling them apart is the whole diagnosis, because the fixes are opposite. 1. **A nearer level opted out.** Some folder between the request and the root — or the request itself — declares `{ "type": "noauth" }`. That is a valid type name, so the parent walk terminated there and returned it as the winner. The root's block was never consulted. The runtime then loaded the `noauth` handler, whose `sign` step returns without touching the request. 2. **Nothing on the path qualified.** Every level from the request outward was silent or unusable, so `getAuth()` returned `undefined`. The runtime gates its authorization step on a resolved auth carrying a `type`, so it bailed out before looking for any handler at all and sent the request as written. Both put the same bytes on the wire and neither produces an error, which is why this has to be diagnosed by reading rather than by watching the run. ## The trace, done the way the resolver does it Walk **outward from the request**, never inward from the collection, because outward is the direction the lookup actually runs and the first hit wins: 1. Read the request's own `auth`. If its `type` is a real string, that is the winner and you are done — including when that string is `noauth`. 2. Read the innermost enclosing folder's `auth`. Same test. 3. Read each folder above it, in order from inside out. 4. Read the collection document's top-level `auth`. 5. If you reach the top with no hit, the answer is "nothing resolved". At every step apply the same predicate the SDK does: the level qualifies only if it has an `auth` member **and** the member's `type` is a string. That makes three shapes transparent — no `auth` member, `"auth": null`, and a block whose `type` is `null`. None of these is ever the cause of a missing credential on its own; they simply pass the question to the next level out. | What you find on the path | What it tells you | | --- | --- | | a `noauth` block below the root | this is the cause; the walk stopped here | | a named scheme below the root | the request is signed, just not with the root's block | | nothing usable anywhere | nothing resolved; the runtime skipped signing | | `"auth": null` at some level | not the cause; keep walking outward | ## What the file will not tell you The hard part of this leaf is that **inheriting and declaring nothing look identical at the request**. A request with no `auth` member might be pulling a fully-configured scheme from three levels up, or might be resolving to nothing at all, and the request's own JSON is byte-for-byte the same in both cases. Nothing at the request records which outcome occurred. That has a second-order consequence worth calling out in a review: **the position of a request in the tree is part of its configuration.** Moving a request from one folder to another can change how it authenticates, or stop it authenticating, with no edit to the request itself and no diff line that mentions credentials. The same is true of adding a `noauth` folder above an existing subtree, or of introducing a root-level block that suddenly starts signing every previously-silent request beneath it. ## Designing so the next person does not have to trace The mitigations are all about making the silence deliberate rather than incidental: - **Declare `noauth` explicitly** on subtrees that must stay unauthenticated. It reads as a decision, it survives later edits to the requests inside, and it makes the stop point visible at the folder rather than inferable from its absence. - **Keep the number of declaration sites small.** One block at the root plus a small number of named exceptions is far easier to trace than blocks scattered across many folders, because the walk is short and the exceptions are enumerable. - **Treat a move between folders as a configuration change**, not a cosmetic one, when reviewing a collection diff. - **Verify by reconstruction, not by the app's display.** Reading the document outward gives the same answer the resolver gives, and it works on a file in version control before anything has been run. ## The one-line summary to give an interviewer Walk outward from the request and stop at the first `auth` block whose `type` is a string. If that block is `noauth`, somebody opted the subtree out and the root never applied. If you reach the top without one, nothing was ever declared and the runtime skipped signing entirely. Anything null or absent along the way is transparent and never the cause.

  • The run produced no warning at all. Does that rule out a resolution problem?
    No — silence is the expected behaviour. An exhausted lookup is not an error, so the runtime simply skips signing, and a resolved `noauth` loads a real handler that succeeds without doing anything. Neither path warns, which is precisely why this is diagnosed by reading the document rather than by watching the run output.
  • A request started signing after someone reorganised folders, with no edit to the request. How is that possible?
    Because the request's position in the tree is what binds it to a block. Moving it under a folder that declares a scheme, or out from under one declaring `noauth`, changes which ancestor the walk reaches first. The request's own JSON is unchanged, so the diff shows a move and nothing about credentials.

It reads like a lookup for a config file up a directory tree: the search stops at the first directory that has one, and an explicit empty file there is very different from no file at all.

saying these in an interview costs you the question

  • Starts the trace at the collection and works inward toward the request
  • Blames an absent auth member rather than looking further out
  • Expects a warning or error when nothing resolves
  • Assumes a root-level block always reaches every request beneath it
  • Treats moving a request between folders as a cosmetic change