Welcome Guest, Not a member yet? Register   Sign In
Ajax with CSRF causing a Double Post to controller
#1

Hi,

I have a system working, and I have narrowed it down to the CSRF in CI.

Currently using 3.1.9, so latest v3.

My config.php looks like this in the CSRF section:


PHP Code:
$config['csrf_protection'] = True;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
$config['csrf_exclude_uris'] = array('aaa/bbb'); 


With csrf_protection set to false, the Ajax and controller work fine. The email at the end of my form sends and the return codes are all correct..

If however, I set csrf_protection to true, things fall apart rather quickly. The issue is not that the csrf is failing to validate, that passes fine. I am sending the CSRF tokens and name correctly, so that is fine. The logs back me up on this.

The issue, is when the CSRF protection in play, the Ajax call is run through the whole system twice. From the longs, it looks like the Ajax call is made twice, however the second time, the data payload (JSON) is missing.

This has the effect of failing the call. As far as I can tell, there is only one call on the web server (according to the Apache log).

I don't know why it would be called twice, there is no Route, it is a standard controller with nothing special.

My current work around is to exclude the URL in the csrf_exclude_uris array. But obviously as this is part of a contact from, I would rather have the protection in place.

I know the code is good, because even while the Ajax return is a failure from the controller, the email that needs to be send, it actually sent, so the contact works, but the feedback is wrong, because the browser is told there is no data in the request. First time it sends the email, second without data, it fails.

If anyone has any idea, where the second call is initiated, I would be grateful.

I can post code, if necessary, but I am not sure that will help.

Thanks for your time and help.
Reply
#2

Is the HTML element starting the process a "submit" button? If so, and if the ajax call is made through javascript and the submit button is not prevented doing its default action (with JQuery event.preventDefault() for example) that might explain the process happening twice. Maybe?

That doesn't really explain why the state of CSRF protection makes a difference. There isn't any code in the CSRF checking process that changes the code execution path if the CSRF token is valid.
Reply
#3

Personally I have disabled regeneration of the CSRF so it will be the same. So that I don't need to get a new one back from the Codeigniter. As the user stays on the same page doing multiple AJAX.
PHP Code:
$config['csrf_regenerate'] = FALSE

But this ain't the cause of your problem. Have you tried a different version of your Javascript library? If you are using one.
Reply
#4

(10-01-2018, 08:55 AM)dave friend Wrote: Is the HTML element starting the process a "submit" button? If so, and if the ajax call is made through javascript and the submit button is not prevented doing its default action (with JQuery event.preventDefault() for example) that might explain the process happening twice. Maybe?

That doesn't really explain why the state of CSRF protection makes a difference. There isn't any code in the CSRF checking process that changes the code execution path if the CSRF token is valid.

Hi Dave,

Thanks for the response. I am using the ev.preventDefault(). My Ajax is called from a button submit, at the end of a .on chain.

It actually look a lot like this, some console log items have been removed.


Code:
var request = $.ajax({
           method: 'POST',
           url: serviceUrl,
           data: { user: userName, email: emailAddr, csrf_cookie_name: cct, comment: userComment },
           dataType: 'json',
           cache: false
       });
       console.log("submitted already");

       request.done(function (resp) {
           $completetitle.html(resp.title);
           $completemessage.text(resp.message);

           buttonSubmit.attr('disabled', false);

           if (resp.status == 'true') {
               $('#myform')[0].reset();
           }

           $complete.foundation('open');
       });

       request.fail(function (resp) {
           $completetitle.html("Network Error");
           $completemessage.html("<p>Something went wrong. The message was NOT sent.</p><p>Please phone instead.</p>");

           $complete.foundation('open');
       });


The code seems to be fine, apart from the double call over at the server. The putting of data into the Modal boxes all works fine.
Reply
#5

(10-01-2018, 10:52 AM)jreklund Wrote: Personally I have disabled regeneration of the CSRF so it will be the same. So that I don't need to get a new one back from the Codeigniter. As the user stays on the same page doing multiple AJAX.
PHP Code:
$config['csrf_regenerate'] = FALSE

But this ain't the cause of your problem. Have you tried a different version of your Javascript library? If you are using one.

Hi jreklund,

I have not tried the regenerate = false, but I am not too worried about posting multiple times.

I have not tried to change my jQuery library, currently using 2.2.4. I might get a chance to try changing it tomorrow, but it is unlikely. Too much on to be sure.
Reply
#6

HI,
I've run into similar issues myself in the past and the solution for me was to use  event.stopImmediatePropagation() function
Here is the link to this function: https://developer.mozilla.org/en-US/docs...ropagation

And here is an example implementation from one of my projects
PHP Code:
 $('#submitbtn').on('click', function (el) {
 
       var formDAta = $('#tagform').serialize();
 
       $.ajax({
 
           url'<?= site_url('tags/saveTags/entities/' . $id) ?>',
 
           method'POST',
 
           dataformDAta,
 
           success: function (data) {
 
               $('.collapse').toggle('toggle');
 
           }
 
       });

 
       // stop from calling this multiple times
 
       el.stopImmediatePropagation();
 
       return false;
 
   }); 
Reply




Theme © iAndrew 2016 - Forum software by © MyBB