Skip to content
Go back

Adding JWT Authentication & Custom Headers in k6

Edit page

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>      |
        +------------------------------+

Over four weeks, you’ll move from basic scripting all the way to building a complete performance testing suite. Each post will build on the last with clear examples, walkthroughs, and exercises. By the end, you’ll be comfortable modeling realistic workloads, analyzing results, scaling tests across distributed systems, and integrating everything into automated pipelines.

The focus areas include:

This post sets up everything you’ll need to start.

Environment Setup

Before diving deeper, install everything you need.

  1. Install k6 on your machine

Run:

sudo apt update
sudo apt install k6

or go to K6’s official installation guide and install based on your preferred package manager.

Verify:

k6 version
  1. Choose an Editor

VS Code works well due to its extensions for JavaScript and testing workflows.

  1. Create a Working Directory

This directory will store all blog-series scripts:

mkdir k6-course
cd k6-course

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:

This confirms everything is installed and ready.

Exercises

Try these quick steps:


Edit page
Share this post on:

Next Post
Introduction & Getting Started with k6