CSRF error in Ajax POST request

I’m trying to request a Ajax POST, and I’m getting the error 403 (Forbidden) and the error Missing CSRF token body📋
It’s running on the IIS server, and it’s the 4.0 Cake
This is the ajax call, the Headers line I found in another forum, but successless

$.ajax({
	url: url,
	type: 'POST',
	contentType: false,
	processData: false,
	headers: {
		'X-CSRF-Token': "<?= $this->request->getParam('_csrfToken'); ?>"
	 },
	data: function(){
		var data = new FormData();
		idanexo = '#Anexos'+tarefa;
		jQuery.each(jQuery(idanexo)[0].files, function(i, file) {
			 data.append('file-'+i, file);
		});
		data.append( 'Comentario', comentario ); 
		data.append( 'NumTarefa', tarefa ); 
		return data;
	}(),
	success: function(result) {
		viewTarefa(tarefa);
	},
});

In the Application.php, there’s this function:

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    $csrf = new CsrfProtectionMiddleware();

    $middlewareQueue
        // Catch any exceptions in the lower layers,
        // and make an error page/response
        ->add(new ErrorHandlerMiddleware(Configure::read('Error')))

        // Handle plugin/theme assets like CakePHP normally does.
        ->add(new AssetMiddleware([
            'cacheTime' => Configure::read('Asset.cacheTime'),
        ]))

        ->add(new RoutingMiddleware($this));

    // Ensure routing middleware is added to the queue before CSRF protection middleware.
	$middlewareQueue->add($csrf);
	
    return $middlewareQueue;
}
1 Like

You should append the token as a field in the POST data iirc.

data: function(){
  var data = new FormData();
  idanexo = '#Anexos'+tarefa;
  jQuery.each(jQuery(idanexo)[0].files, function(i, file) {
    data.append('file-'+i, file);
  });
  data.append( 'Comentario', comentario ); 
  data.append( 'NumTarefa', tarefa );

  // Add CSRF
  data.append(`_csrfToken`, `<?= $this->request->getParam('_csrfToken'); ?>`);

  return data;
}()

I’m still getting the same error
When I debug the $this->request->getParam(’_csrfToken’) I always get null, I don’t think it should happen

This doesn’t answer your question directly, but instead it shows a working solution of using AJAX with CakePHP 4 and CSRF and as a bonus the form tampering protection too: -

In there it doesn’t access the token directly from getParam(), but uses the CakePHP form creator to populate the hidden field it uses for passing the token (so its in the form, not the header). It may help.

I just realized a minor error of mine…
You should use $this->request->getAttribute('csrfToken') instead of $this->request->getParam('_csrfToken').
Sending it as a header is still fine this way.

1 Like

Thank you, this worked