Hi I am looking for the process of regeneration of csrf token in codeigniter when ever a form is submitted using ajax. I want the token to be regenerated without page refres
in the callback add an array of the csrf hash.
The solution that worked for me is that for subsequent ajax post when CSRF is enabled for every request is to make a GET request in AJAX Success when request fails because token has expired. Then have a hidden field that continue to be updated with latest token and if at the time of making request it has expired you make a GET REQUEST to fetch latest TOKEN and then evoke click event on function that submits form or function making POST request which means the function has to be passed "this" or ID as part of parameter.This makes the user not to realize the process of renewing token in the background
if it's not on session then you controller will be like this
public function save_date() // or whatever function you like
{
$regen_token = $this->security->get_csrf_hash();
$data = array(
"data" => $this->input->post('datas'),
);
$insert = $this->w_m->save($data);
echo json_encode(array("regen_token" => $regen_token));
}
in your ajax will be look like this:
$.ajax({
url: "your url",
type: "POST",
data: { your data },
dataType: "JSON",
success: function(data)
{
$("name or id of your csrf").val(JSON.stringify(data.regen_token)).trigger("change"); // this will be the function that every post you'll request and it automatically change the value of your csrf without refreshing the page.
},
error: function(errorThrown)
{
console.log(errorThrown);
}
});
There are two solutions I use at different times depending on the situation.
1. Slightly messy way but recommended
Get the token name and hash value in your controller and set it somewhere on your page as a data field (wherever you choose). For instance
// get the data and pass it to your view
$token_name = $this->security->get_csrf_token_name();
$token_hash = $this->security->get_csrf_hash();
// in your view file, load it into a div for instance
<div id="my_div" data-token="<?php echo $token_name; ?>" data-hash="<?php echo $token_name; ?>"
Now in your js ajax code, you can just read the data values in "my_div" to get the right data for your ajax call.
It is made much easier if you have a genuine form on your page, in which case rather than using some div, just do not use form_open on the form, but instead create the hidden form field yourself, so you can read it easily via js.
<input type="hidden" id="my_data" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />
This is the important bit: Of course after sending post data, you need to refresh the token hash value (in your form input field or a div data, however you have chosen to do it). Write a js function called 'refresh_csrf_data' and use 'GET' to get the data and update the fields. This function can then be called whenever you have done an ajax post.
So every ajax call reads the token data, does the call, then refreshes the token data ready for the next call.
2. Easy but less secure
Alternatively, you can disable CSRF for your ajax calls by using the
$config['csrf_exclude_uris'] = array('controller/method');
in the config file for CSRF settings.
3. Even easier but also less secure and I do not use it Finally, you could turn off regenerating CSRF hash on every submission
$config['csrf_regenerate'] = FALSE;
But, do so with caution. This can open you up to certain types of attacks.
The answer that is best for you depends entirely on the type of page, the usage, if users are logged in at the time or not, is it mission critical stuff or minor stuff, is it financial etc.
Nothing is entirely secure, so it is a compromise sometimes. Personally I would do it with CSRF on full regenerate, no exceptions in the URI's, and reload the token and hash data whenever I needed to. It seems complicated and it is to explain, but once you have done it once, it is genuinely easy to do again and again whenever you need it, and your site will be far more secure than simply avoiding the issue with the other options.
I find using the form helper function works better with Codeigniter CSRF and stops throwing the CSRF error If you use normal html input will keep throwing CSRF error.
Here is a example AJAX
<?php echo form_open('controller/example', array('id' => 'form-login'));?>
<?php
$username_array = array(
'name' => 'username',
'id' => 'username',
'class' => ''
);
echo form_input($username_array);
?>
<?php
$password_array = array(
'name' => 'password',
'id' => 'password',
'class' => ''
);
echo form_password($password_array);
?>
<?php
$submit_array = array(
'name' => 'submit',
'id' => 'submit',
'class' => '',
'value' => 'Submit',
'type' => 'submit'
);
echo form_input($submit_array);
?>
<?php echo form_close();?>
<script type="text/javascript">
$('#submit').click(function(e){
e.preventDefault();
var post_data = {
'username' : $('#username').val(),
'password' : $('#password').val(),
'<?php echo $token_name; ?>' : '<?php echo $token_hash; ?>'
};
$.ajax
({
type: 'post',
url: "<?php echo base_url('example/');?>",
data: post_data,
dataType: 'json',
success: function(response)
{
if (response['success'] == true) {
// Success
} else {
// Error
}
}
});
});
</script>
Example
public function index() {
$data['token_name'] = $this->security->get_csrf_token_name();
$data['token_hash'] = $this->security->get_csrf_hash();
$this->load->view('login_view', $data);
}
public function example() {
$data = array('success' => false, 'messages' => array());
$this->form_validation->set_rules('username', 'username', 'required');
$this->form_validation->set_rules('password', 'password', 'required');
if ($this->form_validation->run() == false) {
foreach ($_POST as $key => $value) {
$data['messages'][$key] = form_error($key);
}
} else {
$data['success'] = true;
}
echo json_encode($data);
}