Codeigniter ajax CSRF problem

Solution 1:

You might like to try this code I've used. It works great:

<script type="text/javascript">
$(function(){
   $('.answerlist').each(function(e){

  $(this).click(function(){

    var valrad = $("input[@name=answer]:checked").val();


    var post_data = {
        'ansid': valrad,
        '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'
    };

        $.ajax({
                type: "POST",
                url: "<?php echo base_url(); ?>online/checkanswer",
                data: post_data,
                success: function(msg){
                  /// do something 
                }
            });

  });

   });


});


</script>

Solution 2:

As others say - you have to post the CSFR token name and its value with the AJAX request parameters. Here is a simple solution to append it automatically to every AJAX request.

Here is what I put on my main view, so this code is on every page before loading the other javascript files:

   <script>
     var csfrData = {};
     csfrData['<?php echo $this->security->get_csrf_token_name(); ?>']
                       = '<?php echo $this->security->get_csrf_hash(); ?>';
   </script>
   <!-- ... include other javascript files -->
  </body>
</html>

And here is a part of a javascript file that I include on every page:

$(function() {
    // Attach csfr data token
    $.ajaxSetup({
       data: csfrData
    });
});

Solution 3:

If you want, you can echo both the token name and the hash somewhere appropriate. Something like this.

 echo $this->security->get_csrf_token_name()

and

 echo $this->security->get_csrf_hash()

Or, you could use form_open() as usual and use the hidden input that is generated for you from your javascript. Disabling the CSRF-functionality is the wrong way to go.

Solution 4:

Having reviewed my situation I believe the best option is to use CSRF but reset the token on each attempt. Otherwise the ideas expressed earlier about re-using the cookie token would allow an attacker to resubmit data hundreds of times using the same token which defeats the object of the point.

As such I have created the following function:

public function resetCSRF(){    

    $this->security = null;

    $_COOKIE[$this->config->item('csrf_cookie_name')] = null;

    load_class('Security', 'core');

    $this->security->csrf_set_cookie();

return $this->security->get_csrf_hash();
}

If for example an ajax based login form fails - call this function in your PHP and then on the javascript side that receives the failure (this solution uses Jquery and a getCookie function from w3schools) would then simply call:

$('input[name="csrf_test_name"]').val(getCookie('csrf_cookie_name'));