Reputation: 109
I'm trying to perform Ajax calls within CodeIgniter. As had already searched before, when the CSRF protection is active, a hash (randomly generated) must be submitted with each request to the server.
In research I found the following code to always hash to be sent along with the other data through the Ajax request:
$.ajaxSetup({
data: {
arquivo_facil_tk: $.cookie('arquivo_facil_co')
}
});
So I got a positive result on the first call right after the page is loaded. But to attempt a second call, get the error 403. I also found the option of adding this code snippet for each Ajax call I make, but as my software performs several calls, it becomes unfeasible and rude.
How could I fix this? Also tried using the beforeSend event but got the same error.
Upvotes: 1
Views: 2472
Reputation: 1719
I was with the same problem. The solution? I use one CSRF token in entire system, only changing at login/logout (and similar functions).
To avoid several submits from same form (like a double click or even an attack), when I call the form, I also insert a random ID on a transaction table.
When I receive this form, I check for the ID in transaction table. If exist's, do action and erase ID from transaction table. If it doesn't, show message error.
Upvotes: 0
Reputation: 17
The problem is that the csrf token is only valid for one call, so if you want to use ajax on another post request without refreshing the page you need to somehow get the new token without the form being reloaded. You can do this in your codeigniter controller by sending the new token back to the requesting script.
In your CodeIgniter Controller:
$data = array('data'=> 'data to send back to browser');
$csrf = $this->security->get_csrf_hash();
$this->output
->set_content_type('application/json')
->set_output(json_encode(array('data' => $data, 'csrf' => $csrf)));
$data = the data to return to the browser
$csrf = new csrf token to be used by the browser for next ajax post request
Obviously you can output this in other ways but JSON is used mostly with ajax calls. Also include the token this way in every post response to be used for the next post request
Then in your next ajax request (javascript):
var token = data.csrf;
$.ajax({
url: '/next/ajax/request/url',
type: 'POST',
data: { new_data: 'new data to send via post', csrf_token:token },
cache: false,
success: function(data, textStatus, jqXHR) {
// Get new csrf token for next ajax post
var new_csrf_token = data.csrf
//Do something with data returned from post request
},
error: function(jqXHR, textStatus, errorThrown) {
// Handle errors here
console.log('ERRORS: ' + textStatus + ' - ' + errorThrown );
}
});
Also remember that where I've got csrf_token:token
replace crf_token
with the name of your token found in application/config/config.php on line that states $config['csrf_token_name'] = 'csrf_token';
Upvotes: 0
Reputation: 2985
Rather than using ajaxSetup
simply include the CSRF token along with the data
in your actual AJAX call like so:
data: {var: value, arquivo_facil_tk: $.cookie('arquivo_facil_co')}
or if you're serializing forms simply:
data: $(this).serialize() + '&arquivo_facil_tk=' + $.cookie('arquivo_facil_co')
Upvotes: 1