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

Dear Community,

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!

Hi @grubthomas, welcome to the community forum!

From a quick glance It seems that you have defined token only inside the first group call but are trying to use it in the second.

If you do let token; next to the let response at the begining of the function and drop the const from const token = Elem.attr('value'); it should work.

Hope this helps you!

1 Like

Hi mstoykov,

Thank you for your help!

Now it works fine :slight_smile: the token is pushed perfectly in the second request, but I’m still getting an error message saying: “status”:419,“status_text”:“419 unknown status”, so the second request fails, something is still not working properly, so I’m working on it, maybe the method of the push request is not ok somehow (?). Do you have any idea what should I change in the second request?

I am not familiar with the exact way you need to send this and googling 419 status code returns a bunch of laravel related results.

I would expect though that you should remove the cookie header that you are adding as that should have the value that was returned instead of what you are currently setting by hand.

I also would expect you did get this script through some kind of converter?

Just figured it out, the “const payload = JSON.stringify” and “const params” are not necessary for the second request. works fine without them!