Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save janzikmund/3047ba4b7031efbabd7ade115f1e3317 to your computer and use it in GitHub Desktop.
Save janzikmund/3047ba4b7031efbabd7ade115f1e3317 to your computer and use it in GitHub Desktop.
Postman Pre-Request script to append CSRF token in header for POST requests in Laravel Sanctum authenticated SPA. Requires active environment with {{url}} variable defined for main app domain.
/**
* Postman Pre-Request script to append CSRF token in header for POST requests in Laravel
* Sanctum authenticated SPA. Requires active environment with {{url}} variable defined
* for main app domain.
*
* Postman Interceptor allows appending cookies from browser, but Laravel CSRF middleware
* only validates CSRF in headers or in _token form field, not in cookies. Axios automatically
* appends the CSRF from cookie to headers, but Postman cannot access intercepted cookies
* and use them, so we have to do one pre-request to get the CSRF token, store it
* in environment so it can be reused, and then append it to headers.
*/
// Query CSRF token and append it before request is made
if (pm.request.method !== 'GET') {
if(pm.environment.get('XSRF-TOKEN')) {
pm.request.headers.upsert({
key: 'x-xsrf-token',
value: pm.environment.get('XSRF-TOKEN'),
});
} else{
let csrfRequestUrl = pm.environment.get('url') + '/sanctum/csrf-cookie';
pm.sendRequest(csrfRequestUrl, function(err, res, {cookies}) {
let xsrfCookie = cookies.one('XSRF-TOKEN');
if (xsrfCookie) {
let xsrfToken = decodeURIComponent(xsrfCookie['value']);
pm.request.headers.upsert({
key: 'x-xsrf-token',
value: xsrfToken,
});
pm.environment.set('XSRF-TOKEN', xsrfToken);
}
});
}
}
/**
* Test/post Request for the above. Check for expired CSRF token and if it happens,
* clear the env variable so it gets refreshed next time
*/
if(pm.response.code === 419) {
pm.environment.unset("XSRF-TOKEN");
}
@layerok
Copy link

layerok commented Oct 31, 2023

Thank you so much, it almost worked for me, I only had to add a 'referer' header. Without this header XSRF-TOKEN cookie wasn't included in the response

...
pm.sendRequest({
    url: csrfRequestUrl,
    method: 'GET',
    header: {
       referer: 'api.erp.local'
    }
}, ...)
...

@dalsochio
Copy link

2024 update:

/**
 * Postman Pre-Request script to append CSRF token in header for POST requests in Laravel
 * Sanctum authenticated SPA. Requires active environment with {{url}} variable defined
 * for main app domain.
 *
 * Postman Interceptor allows appending cookies from browser, but Laravel CSRF middleware
 * only validates CSRF in headers or in _token form field, not in cookies. Axios automatically
 * appends the CSRF from cookie to headers, but Postman cannot access intercepted cookies
 * and use them, so we have to do one pre-request to get the CSRF token, store it
 * in environment so it can be reused, and then append it to headers.
 */

// Query CSRF token and append it before request is made
if (pm.request.method !== 'GET') {
    if (pm.environment.get('XSRF-TOKEN')) {
        pm.request.headers.upsert({
            key: 'x-xsrf-token',
            value: pm.environment.get('XSRF-TOKEN'),
        });
    } else {
        let csrfRequestUrl = pm.environment.get('url') + '/sanctum/csrf-cookie';
        pm.sendRequest(csrfRequestUrl, (error, response) => {
            pm.expect(error).to.equal(null);
            pm.expect(response).to.have.property('code', 204);
            pm.expect(response).to.have.property('status', 'No Content');

            let xsrfCookie = response.headers.find(header =>
                header.key.toLowerCase() === 'set-cookie' &&
                header.value.includes('XSRF-TOKEN')
            );


            if (xsrfCookie) {
                console.log("XSRF Cookie:", xsrfCookie);
                let xsrfToken = decodeURIComponent(xsrfCookie.value.split(';')[0].split('=')[1]);
                pm.request.headers.upsert({
                    key: 'x-xsrf-token',
                    value: xsrfToken,
                });
                pm.environment.set('XSRF-TOKEN', xsrfToken);
            }
        });
    }
}

@abramcatalyst
Copy link

If any of the above did not work for you, You can try this:

/**
 * Postman Pre-Request script to append CSRF token in header for POST requests in Laravel
 * Sanctum authenticated SPA. Requires active environment with {{url}} variable defined
 * for main app domain.
 *
 * Postman Interceptor allows appending cookies from browser, but Laravel CSRF middleware
 * only validates CSRF in headers or in _token form field, not in cookies. Axios automatically
 * appends the CSRF from cookie to headers, but Postman cannot access intercepted cookies
 * and use them, so we have to do one pre-request to get the CSRF token, store it
 * in environment so it can be reused, and then append it to headers.
 */

// Query CSRF token and append it before request is made
if (pm.request.method !== 'GET') {
    // If we already have a CSRF token in the environment, use it
    if (pm.environment.get('XSRF-TOKEN')) {
        pm.request.headers.upsert({
            key: 'x-xsrf-token',
            value: pm.environment.get('XSRF-TOKEN'),
        });
    } else {
        // Define CSRF request URL
        let csrfRequestUrl = pm.environment.get('url') + '/sanctum/csrf-cookie';

        // Perform the CSRF request
        pm.sendRequest(csrfRequestUrl, (error, response) => {
            if (error) {
                console.error('Error fetching CSRF token:', error);
                return;
            }

            if (response.code !== 204) {
                console.error('Unexpected response code:', response.code);
                return;
            }

            // Find the XSRF-TOKEN cookie from response headers
            let xsrfCookieHeader = response.headers.find(header =>
                header.key.toLowerCase() === 'set-cookie' &&
                header.value.includes('XSRF-TOKEN')
            );

            if (xsrfCookieHeader) {
                let xsrfToken = decodeURIComponent(xsrfCookieHeader.value.split(';')[0].split('=')[1]);

                // Set CSRF token in headers for request
                pm.request.headers.upsert({
                    key: 'x-xsrf-token',
                    value: xsrfToken,
                });

                // Store token in environment for reuse
                pm.environment.set('XSRF-TOKEN', xsrfToken);

                console.log("Decoded XSRF Token:", xsrfToken);

            } else {
                console.error('XSRF-TOKEN not found in response headers.');
            }
        });
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment