Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

etfz's avatar
Level 1

SPA-like - should I disable CSRF for all Sanctum API routes? (why not?)

Hi,

I have a site which - while not really a SPA - performs some requests via Javascript to the backend API. The entire site requires authentication, so I set up Sanctum authentication for all API routes and enabled the "stateful frontend requests" middleware. This worked fine until I noticed POST requests still expect a CSRF token, which I don't really understand. I understand the usual implementation of CSRF tokens using the @csrf directive in forms, but that doesn't seem to apply to a SPA in the same way. I understand I can retrieve CSRF tokens by other means, but it still seems a little strange. Am I misunderstanding something or doing something incorrectly?

Anyway, I found that I can disable this behaviour by excepting something like /api/* in the VerifyCsrfToken middleware. Is this the appropriate way to handle this? Security is not a major concern as the site is not accessible from the Internet.

0 likes
4 replies
etfz's avatar
Level 1

@Tray2 Thanks. I have read that. My questions remain. As I said, I don't really have a SPA. I don't log in using API or anything. It's just some Javascript on a select few pages. I don't even really understand how Sanctum comes into play, as I get the same 419 response even when I remove the auth:sanctum middleware from my API routes. API requests from external sources still work then, however. I know that it's the EnsureFrontendRequestsAreStateful middleware that causes it.

etfz's avatar
etfz
OP
Best Answer
Level 1

Ok, I've realised that I always have a XSRF cookie set, regardless of how I login, so I can just add that anywhere at any time, and I don't need to explicitly request one.

function getCookie(name) {
	let cookies = new Map(document.cookie.split(/\s*;\s*/).map(e => e.split(/\s*=\s*/)))
	let cookie = cookies.get(name)
	return cookie ? decodeURIComponent(cookie) : null
}

fetch('/api/endpoint', {
	method: 'POST',
	headers: {
		'X-XSRF-TOKEN': getCookie('XSRF-TOKEN'),
	},
	// ...,
}

Please or to participate in this conversation.