Skip to content
Go back

Adding JWT Authentication & Custom Headers in k6

In the previous post, we built our first full user flow with k6. Now it’s time to move closer to real production scenarios—where users authenticate, carry tokens, and send meaningful headers with each request.

In this post, we’ll:

  1. Log in using email/password
  2. Extract a JWT token from the response
  3. Store it for the rest of the test
  4. Call protected endpoints using Authorization: Bearer
  5. Add custom headers such as X-Client-Version and X-Request-Source
  6. Run a multi-step authenticated flow

This is the foundation for every real-world SaaS, e-commerce, dashboard, and API microservice load test.

Table of contents

Open Table of contents

Flow Overview (ASCII Diagram)

        +-------------------+
        |   User Login      |
        |  POST /auth/login |
        +---------+---------+
                  |
                  | extract JWT
                  v
        +---------------------------+
        | Request Protected Resource|
        | GET /my/crocodiles        |
        +-------------+-------------+
                      |
                      | send token + custom headers
                      v
        +------------------------------+
        | Update Item (authenticated)  |
        | PUT /my/crocodiles/<id>      |
        +------------------------------+

Code Walkthrough

Login payload and headers

const loginPayload = JSON.stringify({
  username: "testuser@example.com",
  password: "supersecure",
});

const loginHeaders = {
  "Content-Type": "application/json",
  "X-Client-Version": "1.0.0",
  "X-Request-Source": "k6-learn-series",
};

POST /auth/token/login/ — retrieve JWT

const loginRes = http.post(
  "https://fakeloadtest.com/auth/token/login/",
  loginPayload,
  { headers: loginHeaders }
);

Validate login and token presence with checks

check(loginRes, {
  "login successful": (r) => r.status === 200,
  "token received": (r) => r.json("access-token") !== undefined,
});

# Extract token and short-circuit if missing
const token = loginRes.json("access-token");
if (!token) return;

Build auth headers

const withAuth = { 
    ...commonHeaders, 
    Authorization: `Bearer ${token}` 
};

Putting it all together

import http from "k6/http";
import { sleep, check } from "k6";

export const options = {
  vus: 5,
  duration: "30s",
};

export default function () {
  // --- shared/common headers used for all requests (non-auth + auth)
  const commonHeaders = {
    "Content-Type": "application/json",
    "X-Client-Version": "1.0.0",
    "X-Request-Source": "k6-learn-series",
  };

  // 1. Login and retrieve JWT
  const loginPayload = JSON.stringify({
    username: "testuser@example.com",
    password: "supersecure",
  });

  const loginRes = http.post(
    "https://fakeloadtest.com/auth/token/login/",
    loginPayload,
    { headers: commonHeaders } // use common headers even for login
  );

  check(loginRes, {
    "login successful": (r) => r.status === 200,
    "token received": (r) => r.json("access") !== undefined,
  });

  const token = loginRes.json("access");
  if (!token) return;

  // Build withAuth by copying commonHeaders and adding Authorization
  const withAuth = { 
    ...commonHeaders, 
    Authorization: `Bearer ${token}` 
    };

  // 2. Get Product list (protected endpoint)
  let products = http.get("https://fakeloadtest.com/api/products/");
  check(products, {
    "Get Products": (r) => r.status === 200,
  });
  const list = products.json();

  if (!list.length) return;

  // 3. Update a product
  const id = list[0].id;
  const updatePayload = JSON.stringify({
    name: "UpdatedTest",
    qty: 5,
  });

  let updated = http.put(
    `https://fakeloadtest.com/api/products/${id}/`,
    updatePayload,
    { headers: withAuth }
  );

  check(updated, {
    "update success": (r) => r.status === 200,
  });

  sleep(1);
}

k6-course/auth-flow.js

Now Run:

k6 run auth-flow.js

The script would run with 1 user as a default and give you some nice statistics like:

Now you know exactly how to use authencation token for your apis. This concludes this post. Hope you enjoyed it.

Exercises

Try these quick steps:


Share this post on:

Previous Post
Tags in k6 - Organizing Your Requests and Metrics
Next Post
Validating JSON API Responses in k6