Refresh CSRF Token on AjaxPOST Datatables: CodeIgniter Refresh CSRF Token on AjaxPOST Datatables: CodeIgniter codeigniter codeigniter

Refresh CSRF Token on AjaxPOST Datatables: CodeIgniter


Refresh CSRF token on AjaxPOST Datatables: CodeIgniter

The above statement is self explanatory & has a clear meaning that:

We have to Refresh our CSRF Token before making any AjaxPOST requests

So, How we will Refresh CSRF Token in CodeIgniter & What is the meaning ff Refresh CSRF in CodeIgniter.


CSRF tokens are only required when you are making a POST requests (ajax post or normal form based post)


Alternatively, you will require to have new CSRF token & hash value before making any AjaxPOST requests. Once Ajax call is done you must update the token and hash value settings in your html or save as variable in your javascript code.


Alternatively, you can exclude the required url from CSRF (You can tell CodeIgniter "Dear CodeIgniter listen, When I will use this url, you are not allowed to check CSRF token and never asked me to attach/send CSRF token within request. Understood? Yes Master) using the config element $config['csrf_exclude_uris'] = array('controller/method', '...');


Alternatively, you can set long time period to expire CSRF token using the config element $config['csrf_expire'] = 300;. Here it is 5 minutes defined to expire the CSRF token, Before the expire time (which start with first POST timestamp) you can use old CSRF token which was generated by CodeIgniter, when you had triggered the first POST request. If no POST request triggered then after first POST request within 5 minutes, CodeIgniter will expire the existing CSRF token and after that you would need to get New CSRF Token again. Sounds Complex.. Not a problem

Suppose you reload the page & CodeIgniter sets the New CSRF Hash, you can use that to make a AjaxPOST request. But if don't make any request or reload the page, after that within 5 minutes, The old CSRF will be expired. Now if you call AjaxPOST request again, you get 500/403 error in your response. That means CodeIgniter expired the old CSRF hash because you hadn't made any request again during CSRF expiration time (5 minutes), and after that when you are sending an HTTP POST request with OLD CSRF Token & That is actually gone.... Clear :)

So, what we can do to get new CSRF token when making an AjaxPOST..?

  • Well, for the GET request you do not need to send any CSRF token.
  • But for the POST Yes! you have to send CSRF with in AjaxPOST if you areusing CodeIgniter CSRF Security $config['csrf_protection'] =TRUE;

The logic behind is, get new CSRF hash before you making any AjaxPOST by using GET. Set it somewhere in DOM or attach in your AjaxSetup.

I am new in CodeIgniter .. :( Do you have any example..?

(Bulma!! Why you hit my Car again...) Yes Sure!!! :)

Here is View Html Code:

<!DOCTYPE html><html lang="en"><head>        <meta charset="utf-8">    <meta name="<?=$this->security->get_csrf_token_name()?>" content="<?=$this->security->get_csrf_hash()?>"/>    <title>CodeIgniter CSRF Refresh Demo</title>    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>    <script type="text/javascript">    // Set CodeIgniter base_url in JavaScript var to use within    var _BASE_URL_ = "<?=base_url()?>";    var _CSRF_NAME_ = "<?=$this->security->get_csrf_token_name()?>";    (function($) {        /**         * New jQuery function to set/refresh CSRF token in Body & to attach AjaxPOST         * @param  {[type]} $ [description]         * @return {[type]}   [description]         */         $.fn.CsrfAjaxSet = function(CsrfObject) {            // getting meta object from body head section by csrf name            var CsrfMetaObj = $('meta[name="' + _CSRF_NAME_ + '"]'),            CsrfSecret = {};            // if CsrfObject not set/pass in function            if (typeof CsrfObject == 'undefined') {                // assign meta object in CsrfObject                CsrfObject = CsrfMetaObj;                // get meta tag name & value                CsrfSecret[CsrfObject.attr('name')] = CsrfObject.attr('content');            }            // CsrfObject pass in function            else {                // get Csrf Token Name from JSON                var CsrfName = Object.keys(CsrfObject);                // set csrf token name & hash value in object                CsrfSecret[CsrfName[0]] = CsrfObject[CsrfName[0]];            }            // attach CSRF object for each AjaxPOST automatically            $.ajaxSetup({                data: CsrfSecret            });        };        /**         * New jQuery function to get/refresh CSRF token from CodeIgniter         * @param  {[type]} $ [description]         * @return {[type]}   [description]         */         $.fn.CsrfAjaxGet = function() {            return $.get(_BASE_URL_ + 'Csrfdata', function(CsrfJSON) {                $(document).CsrfAjaxSet(CsrfJSON);            }, 'JSON');                    };    })(jQuery);    // On DOM ready attach CSRF within AjaxPOST    $(document).CsrfAjaxSet();</script></head><body><button class="button">Click Me to Trigger AjaxPOST</button>    <script type="text/javascript">        // on DOM ready        $(document).ready(function(){            // my button             $btn = $('.button');            // on button click            $btn.on('click', function(e){                // stop default event                e.preventDefault();                // trigger refresh csrf token                var CSRF = $(document).CsrfAjaxGet();                // use callback to put your AjaxPOST & Done!                CSRF.success(function(){                    $.ajax({                        url: _BASE_URL_ + 'Controller/Method',                        method: 'POST',                        success: function(data){                            alert('Success');                        },                        error: function(xhr, status, error){                            alert(error);                        }                    });                });            });        });    </script></body></html>

Here is Controller:

<?php (defined('BASEPATH') or exit('No direct script access allowed'));/** * Class Csrfdata to return fresh CSRF hash value */class Csrfdata extends CI_Controller{    public function __construct()    {        parent::__construct();    }    /**     * Return CodeIgniter CSRF name & Hash on request     * @return [type] [description]     */    public function index()    {        if ($this->input->get()) {            $csrf = array();            $csrf_name = $this->security->get_csrf_token_name();            $csrf_hash = $this->security->get_csrf_hash();            $csrf[$csrf_name] = $csrf_hash;            echo json_encode($csrf);        }    }}/* End of file Csrfdata.php *//* Location: ./application/controllers/Csrfdata.php */

Hope you enjoyed the answer & any suggestions, comments are much appreciated... as always .. :D


Thank you Neeraj! Your solution worked for me.

I used the following code for AJAX DataTable in CodeIgniter. This is to trigger your CSRF Refresh method upon getting results from DataTable's AJAX call.

$('#table').DataTable({     "ajax": {        "url": "<?php echo site_url(); ?>list",        "type": "POST",        "dataSrc": function ( json ) {            $(document).CsrfAjaxGet();            return json.data;        }     }});


Please add this line in your page in script tag.

$(function($) {    // this script needs to be loaded on every page where an ajax POST    $.ajaxSetup({        data: {            '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'        }    });  // now write your ajax script });

Let me know if it not works