Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSRF issue when using AJAX submit via link in Yii2

Tags:

ajax

php

yii

yii2

I'm using Yii2 and have been using a link that does a POST via AJAX to retrieve some data and it has been working fine; however I have noticed that if I remove a form from the page it no longer works and does not send a CSRF token in the headers for some reason.

I also have several hidden forms on the page that are there in both situations.

Here is a run down of the two situations:

Working Situation:

ALL CSRF's on the page are the same - the meta tag named csrf-token, the main form on the page as well as all the hidden forms, they all use the SAME CSRF token and this is the same token that is sent in the headers with the request.

... now I change the scenario so I can produce the non-working version.

Not Working Situation:

There is NO main form on the page in this situation. The meta tag named csrf-token has a different CSRF token from the last request, but for some reason all the hidden forms have the same CSRF token from the previous request/page load.

When I click on the link that POST's via AJAX no CSRF token is sent in the headers.

If it matters:

The main form is loaded with ActiveForm::begin(...) whilst the hidden forms are loaded with Html::beginForm(...).

Any idea what is going on here? Why doesn't it work? Why do the hidden forms have the CSRF token from the prior request?

like image 211
Brett Avatar asked Aug 21 '15 18:08

Brett


1 Answers

Working: Ok, So my understanding for the problem is when you use ActiveFrom it creates a New CSRF Token and stores in a cookie, say xxxxxx, So the Main form and the corresponding HTML forms in that page read from this cookie for the csrf value.

Not Working : Now, You are into a new page So the Yii engine creates a csrf in server side(thats why you see the meta tag with a new csrf token), and unless you call the ActiveForm, there is no way the cookie is updated in client side. So all the other HTML forms tries to read from the cookie value to get the csrf value, which ends up to be old one.

So unless you potentially call a function which creates the token dynamically, I don't see a value be changing. So the value remains the same.

My thinking would be trying out

'_csrf="<?php echo Yii::$app->request->csrfToken ?>" '

in the HTML page where you dont have an Main form to return value from the request.

I've not tried, But should work.

Or for Ajax

<head>
   .......
   <?= Html::csrfMetaTags() ?>
</head>

var csrfToken = $('meta[name="csrf-token"]').attr("content");
$.ajax({
         url: 'request',
         type: 'post',
         dataType: 'json',
         data: {param1: param1, _csrf : csrfToken},
});
like image 132
Muthu Rg Avatar answered Nov 09 '22 04:11

Muthu Rg