Refresh CSRF Token on AjaxPOST : CodeIgniter

Refresh CSRF Token on AjaxPOST : CodeIgniter

elimariaaaelimariaaa Posts: 30Questions: 11Answers: 0

Hello,

I have the same problem with this discussion.

My CSRF Token does not refresh after I click the next page. You can see it in action here.

You can also check the page source since the script is inline with the page.

Here's my script:

<script type="text/javascript">

var table;

$(document).ready(function() {
    
    //datatables
    table = $('#test-table').DataTable({ 

        "processing": true, //Feature control the processing indicator.
        "serverSide": true, //Feature control DataTables' server-side processing mode.
        "order": [], //Initial no order.
        "ajax": {
            "url": "<?php echo site_url('oss/admin/ajax_receiving'); ?>",
            "type": "POST",
            data: {
                '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>' 
                },
           dataSrc: function ( json ) {
               if(json.csrf_token !== undefined) $('meta[name=csrf_token]').attr("content", json.csrf_token);
               return json.data;
           }
        },
        "columnDefs": [
        { 
            "targets": [ 0 ], //first column / numbering column
            "orderable": false, //set not orderable
        },
        ],

    });

});

</script>

I'm not sure but my guess is this part is not being called:

          dataSrc: function ( json ) {
               if(json.csrf_token !== undefined) $('meta[name=csrf_token]').attr("content", json.csrf_token);
               return json.data;
           }

I could just set the $config['csrf_regenerate'] = TRUE; to FALSE but I don't want that.

Any help is highly appreciated. Thanks!

Answers

  • bindridbindrid Posts: 730Questions: 0Answers: 119

    dataSrc does not return data. It just tells DataTables where to find the data in the return object. By default that would be {data:{your data}}

    DataTables uses the success: option to grab the data that is being returned.

    If want or need to see the data returned, one of the options is something like

    ajax: {

     blah blah blah 
    dataFilter: function(response){
       // make changes to the response as needed
       return response;
    }
    

    }

  • elimariaaaelimariaaa Posts: 30Questions: 11Answers: 0

    Hi Bindrid,

    Noted. Since dataSrc is not what I needed, I also don't think dataFilter is the one. Basically, what I want is to include a newly generated csrf token every time I call the ajax.

  • bindridbindrid Posts: 730Questions: 0Answers: 119

    Modify your data option a bit. As it is now, you are passing the token but stomping on the data tables request object.

    Try something like (and I am sorry if I got the php part wrong. In 18 years of web programming, I have never been hired to do php.)

     data:  function(dtRequest) {
         dtRequest[ '<?php echo $this->security->get_csrf_token_name(); ?>'] = '<?php echo $this->security->get_csrf_hash(); ?>' ;
    
        return dtRequest;
     },
    
  • elimariaaaelimariaaa Posts: 30Questions: 11Answers: 0

    It's still the same. :(

  • bindridbindrid Posts: 730Questions: 0Answers: 119
    edited June 2017

    The problem night not be your code. It might be something else.
    I opened up your page with my console open. I first load I get

    SCRIPT5007: Unable to get property 'handleEvent' of undefined or null reference
    recaptcha__en.js (39,1270) 
    

    which, I think, is completely unrelated.
    When I go to a second page, I get a 403 error

    HTTP403: FORBIDDEN - The server understood the request, but is refusing to fulfill it.
    (XHR)POST - http://oss-dev.forexworld.us/oss/user/ajax_receiving
    

    So the problem might not be DataTables, at all

    Can you turn off the csrf feature for a moment to check to make sure that is not causing the 403 error?

    Also, if you make the following changes (just for dev), we can see what, exactly, is being returned once you get past the 403 error.

    <script type="text/javascript">
    
    var table;
    
    $(document).ready(function() {
        $(function() {
    
            //datatables
            table = $('#test-table').DataTable({
    
                "processing": true, //Feature control the processing indicator.
                "serverSide": true, //Feature control DataTables' server-side processing mode.
                "order": [], //Initial no order.
                "ajax": {
                    "url": "http://oss-dev.forexworld.us/oss/user/ajax_receiving",
                    "type": "POST",
                    data: function(dtRequest) {
                        dtRequest[ 'csrf_test_name'] = '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>';
                        return dtRequest;
                    },
                    dataFilter:function(response) {
                        console.log(response);
                        return response;
                    },
                    error: function(err){
                        console.log(err);
                    }
                },
                "columnDefs": [
                {
                    "targets": [ 0 ], //first column / numbering column
                    "orderable": false, //set not orderable
                },
                ],
    
            });
    
        });
    
    });
    
        </script>
    
  • allanallan Posts: 61,740Questions: 1Answers: 10,111 Site admin

    I think your problem is that the PHP is being evaluated when the page is first loaded, and not thereafter. Therefore it will only ever use the original token.

    If you are generating a new token after every request, are you including it in the JSON returned to the client? If so, you would need to listen for xhr and get the new token that way.

    Then use ajax.data as a function to use the new token (i.e. write it to a variable which can be read by that function).

    Allan

This discussion has been closed.