Search code examples
jqueryajaxcodeignitercsrf-protection

CSRF Codeigniter protection and AJAX call


I have to ask help to solve an issue with AJX call in Codeigniter. I have CSRF protection on in my system and usually it works fine even with AJAX/jQuery call. Now I got in trouble with the following code and I'm not able to fix it...just got a great headache What I'm trying to do is call a controller every time a checkbox state is changed (I'm using Switchery ); I'd like to get the switch working correctly several times...not just at the first switch. The javascript code is the following:

			$(document).ready(function() {
			var csrfName = '<?php echo $this->security->get_csrf_token_name(); ?>';
			var csrfHash = '<?php echo $this->security->get_csrf_hash(); ?>';
			var changeCheckbox = document.querySelector('.js-switch'), changeField = document.querySelector('#results');

			changeCheckbox.onchange = function() {
			  	changeField.innerHTML = changeCheckbox.checked;
			    $.ajax({
			        url: 'myphpfile',
			        type: 'POST',        
			        data : {
			            csrfName: csrfHash,
			            "checked": changeCheckbox.checked
			        }, 
			        dataType: "json",
			        success: function(result){
			            $("#results").append(result.error);
			            csrfName = result.csrfHash;
			        }
			    });
			};

			});

The script above doesn't work even at first attempt and I get an 403 error ( forbidden ) so, the csrf hash is not passed at all....this is really weird because if I set ( using the PHP echo code ) the csrf name and csrf hash directly into the S.ajax data brackets, the script works fine...even if just once. So the questions are: why the csrfName and csrfHash variables are not passed along the data? How can I make the AJAX csrf working fine several times? Sorry for my bad english, hope I explained my issues Thanks a lot for any help


Solution

  • Probably what you mean is:

    var data = {"checked": changeCheckbox.checked};
        data[csrfName] = csrfHash; 
    

    and then:

    $.ajax({
        url: 'myphpfile',
        type: 'POST',        
        data : data
    [...]
    

    csrfName is a variable, so if you want to add a property named with the contents of csrfName you have to use object[variable] syntax. By writing:

    data : {
        csrfName: csrfHash
    }
    

    you are creating an object with csrfName property, not its contents.

    Or if you're using ES6, you can write:

    data : {
        [csrfName]: csrfHash,
        "checked": changeCheckbox.checked
    }