Cakephp - CSRF token mismatch

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Cakephp - CSRF token mismatch



I have a project in Cakephp 3.6 in which 3 actions in MessageController are called by Ajax. I have a problem, however, when I send a request to one of the action, XHR returns to me this:



"message": "CSRF token mismatch.",
"url": "/messages/changepriority/8",
"code": 403,
"file": "D:\xampp\htdocs\myapp\vendor\cakephp\cakephp\src\Http\Middleware\CsrfProtectionMiddleware.php",
"line": 195



This is one of the action what I try to call from Ajax:


public function changepriority($id=null)

$this->autoRender = false;
$message = $this->Messages->get($id);
$message->priority = ($message->priority === false) ? true : false;
if ($this->Messages->save($message))
echo json_encode($message);




And this is my ajax:


$(".email-star").click(function()
var idmessage = this.id;
$.ajax(
headers :
'X-CSRF-Token': $('[name="_csrfToken"]').val()
,
dataType: "json",
type: "POST",
evalScripts: true,
async:true,
url: '<?php echo Router::url(array('controller'=>'Messages','action'=>'changepriority'));?>' +'/'+idmessage,
success: function(data)
if(data['priority'] === false)
$("#imp_" + idmessage).removeClass("fas").removeClass('full-star').addClass( "far" );

else
$("#imp_" + idmessage).removeClass("far").addClass( "fas" ).addClass("full-star");


);
);



I have read the documentation about Cross Site Request Forgery, and I tried to turn off the Csrf for these action first with:


public function beforeFilter(Event $event)

$this->getEventManager()->off($this->Csrf);



and then with:


public function beforeFilter(Event $event)

$this->Security->setConfig('unlockedActions', ['index', 'changepriority']);



But nothing. The Xhr return always the CSRF token mismatch.
What can I do ?



Edit:



I change the action in this way:


public function changepriority($id=null)

$this->autoRender = false;
$message = $this->Messages->get($id);
$message->priority = ($message->priority === false) ? true : false;
if ($this->Messages->save($message))
$content = json_encode($message);
$this->response->getBody()->write($content);
$this->response = $this->response->withType('json');
return $this->response;




In that way the action works. Can it be like that?





On an unrelated note, controlls should never echo data!
– ndm
Aug 8 at 9:01





The solution you send to me work, but Is there any way to send a csrf parameter to the controller without using a form?
– l3nox
Aug 8 at 9:44





Yes, see my comment to D3ad L0cKs answer.
– ndm
Aug 8 at 9:49






Yes, I've seen the comment, but I do not really understand how to do it
– l3nox
Aug 8 at 10:07





You just need to replace $(...).val() with the <?= json_encode(...); ?> example.
– ndm
Aug 8 at 11:19


$(...).val()


<?= json_encode(...); ?>




1 Answer
1



First check your $('[name="_csrfToken"]').val() output.


$('[name="_csrfToken"]').val()



If you didn't get any output, need to check csrfToken hidden field is exist or not. Just right click in your page and click View Page Source


csrfToken


View Page Source



If not exist, you don't follow proper way when you create Form. Basically, when forms are created with the CakeViewHelperFormHelper, a hidden field is added containing the CSRF token.


CakeViewHelperFormHelper



If everything is correct, add the following line inside your ajax call after header


header


beforeSend: function (xhr)
xhr.setRequestHeader('X-CSRF-Token', $('[name="_csrfToken"]').val());
,



Ps. Disabling the CSRF is not recommended by cakePHP and most of the developer aware of this. Hope this help.





Side note, there's usually no need for a form, as the current CSRF token can be read from the request object.
– ndm
Aug 8 at 9:04






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard