Kodeloka
  1. Kodeloka
  2. Kelas k6
  3. Materi

Modul 10 · Modul 10 dari 15

Autentikasi & Correlation: JWT, Cookie, CSRF, Refresh Token

Menangani alur login yang realistis, mengambil nilai dinamis dari respons, dan menghindari kesalahan yang membuat tes mengukur hal yang salah.

Correlation — Keterampilan Inti Performance Engineer

Correlation adalah proses mengambil nilai dinamis dari respons sebuah request, lalu memakainya di request berikutnya. Contohnya token, CSRF token, session ID, order ID, atau nonce. Skrip yang tidak melakukan correlation hanya akan bekerja sekali lalu gagal terus.

Pola 1 — Login Sekali di setup()

Cocok bila semua VU boleh berbagi satu identitas (misalnya menguji endpoint publik yang butuh API key).

auth-setup.jsjavascript
export function setup() {
  const res = http.post(BASE + '/auth/login', JSON.stringify({
    username: __ENV.TEST_USER,
    password: __ENV.TEST_PASSWORD,
  }), { headers: { 'Content-Type': 'application/json' } });

  if (res.status !== 200) throw new Error('Login gagal: ' + res.status);
  return { token: res.json('access_token') };
}

export default function (data) {
  http.get(BASE + '/api/profil', {
    headers: { Authorization: 'Bearer ' + data.token },
  });
}
⚠️ Keterbatasan pola ini

Anda tidak menguji endpoint login sama sekali, padahal login sering jadi bottleneck terberat (hashing bcrypt/argon2 sengaja dibuat lambat). Selain itu, token bisa kedaluwarsa di tengah tes panjang.

Pola 2 — Login per VU, Cache Token

Ini pola yang paling realistis untuk kebanyakan kasus: setiap VU login sekali di iterasi pertama, lalu memakai ulang tokennya.

auth-per-vu.jsjavascript
// Variabel di scope modul: nilainya PER VU, tidak dibagi antar VU
let token = null;
let tokenKedaluwarsa = 0;

function pastikanToken(user) {
  const sekarang = Date.now();
  // Refresh 60 detik sebelum benar-benar kedaluwarsa
  if (token && sekarang < tokenKedaluwarsa - 60000) return token;

  const res = http.post(BASE + '/auth/login', JSON.stringify({
    username: user.email, password: user.password,
  }), {
    headers: { 'Content-Type': 'application/json' },
    tags: { name: 'Login' },
  });

  if (res.status !== 200) {
    console.error('Login gagal untuk ' + user.email + ': ' + res.status);
    return null;
  }

  token = res.json('access_token');
  tokenKedaluwarsa = sekarang + (res.json('expires_in') || 3600) * 1000;
  return token;
}

Pola 3 — Cookie & Session (aplikasi web klasik)

k6 mengelola cookie secara otomatis per VU. Setelah login, cookie sesi ikut terkirim di request berikutnya tanpa Anda atur.

cookie.jsjavascript
// Otomatis: cookie dari respons login tersimpan di cookie jar VU ini
http.post(BASE + '/login', { email: u.email, password: u.password });
http.get(BASE + '/dashboard');   // cookie sesi otomatis terkirim

// Manual bila perlu kontrol penuh
const jar = http.cookieJar();
jar.set(BASE, 'session_id', 'abc123');
console.log(jar.cookiesForURL(BASE));

// Membersihkan cookie di awal iterasi (mensimulasikan pengguna baru)
jar.clear(BASE);

Pola 4 — CSRF Token

Aplikasi berbasis form (Django, Rails, Laravel) mengirim token CSRF di HTML atau cookie. Anda harus mengambilnya dulu.

csrf.jsjavascript
// Ambil halaman login untuk mendapatkan CSRF token
const halaman = http.get(BASE + '/login');

// Cara A — parsing HTML (k6 punya selektor mirip jQuery)
const csrf = halaman.html().find('input[name=csrfmiddlewaretoken]').attr('value');

// Cara B — regex (lebih cepat, tapi rapuh bila HTML berubah)
const cocok = halaman.body.match(/name="csrf_token" value="([^"]+)"/);
const csrf2 = cocok ? cocok[1] : null;

// Cara C — dari cookie
const csrf3 = http.cookieJar().cookiesForURL(BASE)['csrftoken'][0];

http.post(BASE + '/login', {
  username: u.email, password: u.password, csrfmiddlewaretoken: csrf,
}, { headers: { Referer: BASE + '/login' } });
⛔ Jangan pernah hardcode token hasil rekaman

Menyalin token dari DevTools browser lalu menempelkannya ke skrip akan "berhasil" hari ini dan gagal total besok saat token kedaluwarsa. Lebih buruk lagi: Anda melewati proses login sehingga bottleneck di sana tidak pernah terdeteksi, dan token asli (yang mungkin milik akun nyata) bocor ke repositori Git.

Menangani Token Kedaluwarsa di Tengah Tes

refresh.jsjavascript
function requestDenganRetry(metode, url, body, params) {
  let res = http.request(metode, url, body, params);

  // 401 = token kedaluwarsa -> perbarui lalu ulangi SEKALI
  if (res.status === 401) {
    token = null;                 // paksa login ulang
    const baru = pastikanToken(user);
    if (!baru) return res;
    params.headers.Authorization = 'Bearer ' + baru;
    res = http.request(metode, url, body, params);
  }
  return res;
}