How to push request a CSRF Token in k6 performance testing tool - ReferenceError

Viewed 46

I am quite new to k6 and load testing and I could not figure out why I am not able to push a token from one request to another, to test the login process in a Laravel-built web app. I hope somebody can help me out with this issue.

So my script looks like the following:

First request from where I want the token:

import { parseHTML } from 'k6/html';
import { sleep, group, check } from "k6";
import http from 'k6/http'

export const options = {}

export default function main() {
  let response

   group('page_1 - http://localhost:81/login', function () {
    response = http.get('http://localhost:81/login', {
      headers: {
        host: 'localhost:81',
        'user-agent':
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0',
        accept:
          'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
        'accept-language': 'en-US,en;q=0.5',
        'accept-encoding': 'gzip, deflate, br',
        connection: 'keep-alive',
        cookie:
          'XSRF-TOKEN=eyJpdiI6InY5ckZiaGdFTkI4Q0YyRi8rdmtyNUE9PSIsInZhbHVlIjoiT0NjZXlWWVBubTE5Zjh6cXBmNmZFWTdZKzBjVXlEOGhheGR0aVUybURSSGRZbEFmQ0N2RW5BQ3pOYzBQUXgweXhUaGNpRDhrcTV5SHBJUkEvU0FYTmN3eCswYTFsVnhQdk8wL1dkeHMvOTNXRTU4dnk2WjJ0QWFCSWdyQzEwQkwiLCJtYWMiOiIyODI1YmFkMDI1MzlkOGY4ODEyMDg4YWU5M2I5MWE3NmI3Yjg2ODczYTBkMzhhNmZiZTU5ODNlZDBjOGViNWIzIn0%3D; dev_session=eyJpdiI6ImNGalhPQW9GTWlYLzdsaEg1Qk0zdnc9PSIsInZhbHVlIjoiVU5jQ21OZmkyUDVnUmd2WUxUc3Z5dWhRbzBJTm1HWFhmQ1RuNzdFaEpRb1IzdVlIa1VhUkNXYTBlc2IxMHRMajl6UTAzYmFVTHZheEdTV2RrYU84d3pmdEUxYUlkaVFFT3J5YUVWSE1wVklRektqemVmbjhmK3hLWHo2ZmlMYlgiLCJtYWMiOiI3MTQ2ODg0Yjk4YjhhNjg2Yzg1YjllZjdmMWMyNzVkY2ZmNGM1NjAzYWUyN2NlMmE0ZjAwOTAyNWMwNGI2YmM2In0%3D',
        'upgrade-insecure-requests': '1',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'none',
        'sec-fetch-user': '?1',
        'sec-gpc': '1',
      }, 
    })
      
  // Query the HTML for an input field named "_token".
  const elem = response.html().find('input[name=_token]');

  // Get the value of the attribute "value" and save it to a variable
  const token = Elem.attr('value');

  // Now you can concatenate this extracted value in subsequent requests that require it.

  // console.log() works when executing k6 scripts locally and is handy for debugging purposes
  console.log('The value of the hidden field is: ' + token);
  
  check(response, { 
      list_OK: (r) => r.status === 200,
    });
  })

Second request - I want to use the token from the previous request to log in:

    group('page_2 - http://localhost:81/customlogin', function () {
        const url = 'http://localhost:81/customlogin';
        const payload = JSON.stringify({
    _token: `${token}`,
    email: 'user',
    password: '1234',
    });
  const params = {
    headers: {
        'Content-Type': 'application/json',
      host: 'localhost:81',
          'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0',
          accept:
            'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
          'accept-language': 'en-US,en;q=0.5',
          'accept-encoding': 'gzip, deflate, br',
          'content-type': 'application/x-www-form-urlencoded',
          origin: 'http://localhost:81',
          connection: 'keep-alive',
          referer: 'http://localhost:81/login',
          cookie:
            'XSRF-TOKEN=eyJpdiI6ImlnZFZCUGF1b1FYUlJOdTJHNDd2Vnc9PSIsInZhbHVlIjoiTXhhdnZyQzlPamRFQ21rajdQVEZXcThzWittZndqU2d1L0hyN1BmRTA2a2RBbEpYZUhIUlRpWjh1RWJoQ1Y5dWJoTWVnaXEzZ1NVTjBndG1tenUyN2phY1lMdkIxSzBGek5aYndlSmRxaEhVTGY4WkNCcE1UY3N6YmowUnkrTkciLCJtYWMiOiJlNDIxNjhkYTc1NjYxNTVkNWZhOWViZDYwMGU1ODRkNmQ2ZGU0NjgyMjU5NjIxMzQ0MjYyYzRjMmJkYTVmNjUwIn0%3D; dev_session=eyJpdiI6IndxWXpobW9BUm1GSHNVZkorN0N0OGc9PSIsInZhbHVlIjoiSE82by9aRnBXQjFkNG5JMHFkVzUzc3kraUZOYUdIdjNlUGN6a3c2SjBSZy9TaVNxNmRsWnQzMTltMGt0MGQvWUoxQndyQXFvd2theWViNU94Z2FXaXlGTkc4ZVdERGY2KzRpUUZDZDIxNG85UFhhanRiajBCWElmcmthMWE0R3IiLCJtYWMiOiJjMDllMmRmNGJjNDRlMjM2MmZmZTViOWEwZmUzNWQ3MzNjZDI1NWQwYmU3MjE4OTZiMTRhN2U0NWNkMTcxMDAzIn0%3D',
          'upgrade-insecure-requests': '1',
          'sec-fetch-dest': 'document',
          'sec-fetch-mode': 'navigate',
          'sec-fetch-site': 'same-origin',
          'sec-fetch-user': '?1',
          'sec-gpc': '1',
    },
  };
  response = http.post(url, payload, params);
    console.log(response)
    check(response, {
      list_OK: (r) => r.status === 200,
    });
  })

After running the script I get an error message saying:

> ReferenceError: token is not defined

Thank you for your passionate help!

1 Answers

In this case you are defining a variable in the first call to group (const token ....` and then try to use it in the second call.

This has nothing to do with CSRF or k6, but with javascript ... and arguably scoping in most other languages.

But in order for both functions to see the same variable you will need to define it earlier - so for example next to your let response in the start of the default function.

Also remove const from the current definition as otherwise it won't work ;)

Related