Authentication
Almost every real API restricts write operations — and often reads too — to authenticated callers. RecipeBox is no different: creating, updating, or deleting a recipe requires proving who you are first. Postman supports the three authentication styles you'll run into constantly: Basic Auth, Bearer Tokens, and API Keys. This lesson works through a full RecipeBox login flow and wires the resulting token into every other request in the collection.
Three Common Authentication Styles
| Style | How credentials travel | Typical use |
|---|---|---|
| Basic Auth | Username and password, base64-encoded, in an Authorization: Basic <encoded> header |
Simple internal tools; not something you'd want over plain HTTP since base64 isn't encryption |
| Bearer Token | A token (often a JWT) obtained by logging in, sent as Authorization: Bearer <token> |
The most common style for modern REST APIs — this is how RecipeBox itself works |
| API Key | A static key sent either as a header (e.g. X-API-Key) or a query parameter (e.g. ?apiKey=...) |
Server-to-server integrations and public API tiers, often paired with rate limiting |
Step 1: Logging In to Get a Token
The Login request in the Auth folder sends RecipeBox credentials to get a token back:
POST {{baseUrl}}/auth/login
Content-Type: application/json
{
"username": "tester@recipebox.example.com",
"password": "P@ssw0rd123"
}
// Response — 200 OK
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600
}
In the Login request's Tests tab, save that token so every later request can read it:
var jsonData = pm.response.json();
pm.test("login succeeded and returned a token", function () {
pm.response.to.have.status(200);
pm.expect(jsonData).to.have.property("token");
});
pm.collectionVariables.set("token", jsonData.token);
This is the same pm.collectionVariables.set() pattern from the chaining lesson — logging in is really just another form of chaining, where the value being passed forward happens to be a token instead of a resource id.
Step 2: Using the Token — Two Ways
Option A: Postman's Auth Tab (Recommended)
- Open
Create Recipe(or any protected request) and click its Authorization tab. - Set Type to Bearer Token.
- In the Token field, enter
{{token}}.
Postman builds the Authorization: Bearer {{token}} header for you at send-time. Better still, set this once at the collection level (RecipeBox API → Authorization tab → Bearer Token → {{token}}) and every request that "inherits auth from parent" picks it up automatically — no need to configure it request-by-request.
Option B: Setting the Header Manually
Functionally identical, done by hand on the Headers tab (or via a pre-request script, as shown last lesson):
Authorization: Bearer {{token}}
Both options send the exact same header over the wire. The Auth tab exists because remembering to type Bearer correctly and re-adding the header to every new request gets tedious and error-prone — but understanding the manual version matters, since it's what the Auth tab is doing for you under the hood, and it's the only option when a token needs extra processing a plain field can't do.
Basic Auth and API Key in Postman's Auth Tab
The same Authorization tab handles the other two styles without any manual header work:
| Type | Fields Postman asks for | Header it builds |
|---|---|---|
| Basic Auth | Username, Password | Authorization: Basic <base64(username:password)> |
| API Key | Key, Value, Add to (Header or Query Params) | X-API-Key: <value> (or appended as a query string param) |
| Bearer Token | Token | Authorization: Bearer <value> |
Verifying Auth Actually Works
Don't just assume the header is being sent correctly — assert against both the success and failure paths:
pm.test("authenticated request succeeds", function () {
pm.response.to.have.status(201);
});
// On a separate request sent with no token / a bad token:
pm.test("unauthenticated request is rejected", function () {
pm.response.to.have.status(401);
});
That second assertion matters as much as the first — an API that silently accepts requests with no valid token at all is a security bug, and it's exactly the kind of thing API-level testing catches that clicking through a UI never would.
password and token in environment variables (ideally marked as secret type in Postman) so they aren't accidentally committed or shared when the collection is exported.pm.expect() per field. JSON Schema Validation covers validating a whole Recipe object's shape in a single assertion.