l3nox
l3nox

Reputation: 15

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?

Upvotes: 0

Views: 3755

Answers (2)

mail testing
mail testing

Reputation: 11

beforeSend: function (xhr) {
        xhr.setRequestHeader('X-CSRF-Token', <?= json_encode($this->request->getAttribute('csrfToken')) ?>);
    },

Upvotes: 0

502_Geek
502_Geek

Reputation: 2126

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

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

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

If everything is correct, add the following line inside your ajax call after 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.

Upvotes: 1

Related Questions