CodeIgniter Forums

Full Version: CodeIgniter 3 - 403 Forbidden on POST from jQuery.ajax() asynchronous request
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am getting a 403 forbidden error on jQuery.ajax() post request.
[b][b][b]application/config/config.php[/b][/b][/b]
Code:
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_ghive';
$config['csrf_cookie_name'] = 'csrf_ghive';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = false;
[b][b]application/views/billing.php[/b][/b]
Code:
<input type="text" class="txt_csrfname" name="<?= $this->security->get_csrf_token_name(); ?>" value="<?= $this->security->get_csrf_hash(); ?>">

<button id="bill_client"><?php echo lang('pay'); ?></button>

<script type="text/javascript" src="<?php echo base_url(); ?>assets/customers/js/bill.js"></script>


[b][b]assets/customers/js/bill.js[/b][/b]

Code:
function add_bill_by_ajax(bill_object,bill_id){
    // CSRF Hash
    var csrfName = $('.txt_csrfname').attr('name'); // Value specified in $config['csrf_token_name']
    var csrfHash = $('.txt_csrfname').val(); // CSRF hash
    $.ajax({
        url:base_url+"Bill/add_bill_by_ajax",
        method:"POST",
        data:{
            order : bill_object,
            sale_id : bill_id,
            close_order : 0,
            //csrf_test_name: $.cookie('csrf_ghive')
            //'<?php echo $this->security->get_csrf_token_name(); ?>':'<?php echo $this->security->get_csrf_hash(); ?>'
           [csrfName]: csrfHash
        },
        dataType: 'json',
        success:function(response) {
           
            if(response>0){
                $('.txt_csrfname').val(response.token);
                set_new_bills_to_view();   
                swal({
                     title: warning,                                                                                      
                     text:  added_bill,                                                                                      
                     confirmButtonText:ok                        
                });
            }

        },
        error:function(){
                console.log("403 Forbidden for ajax error");
                swal({
                       title: warning,                                                                                      
                       text:'403 Forbidden for ajax error',                                                                                      
                       confirmButtonText:ok,                                                  
                       allowOutsideClick: false                                                                                   
                });
               
        }
    });
}


application/controllers/Bill.php

Code:
  function add_bill_by_ajax(){
        $bill_details = json_decode(json_decode($this->input->post($this->security->xss_clean('bill'))));      
        //this id will be 0 when there is new bill, but will be greater then 0 when there is modification
        //on previous order
        $bill_id = $this->input->post('bill_id');
        $close_bill = $this->input->post('close_bill');     
        $data = array();
        $data['token'] = $this->security->get_csrf_hash();
        $data['customer_id'] = trim($bill_details->customer_id);  
        ...

Browser Console errors

Code:
jquery-3.3.1.min.js:2 POST http://localhost/Bill/add_bill_by_ajax 403 (Forbidden)
send @ jquery-3.3.1.min.js:2
ajax @ jquery-3.3.1.min.js:2
add_bill_by_ajax @ custom.js:3764
(anonymous) @ bill.js:2362
dispatch @ jquery-3.3.1.min.js:2
y.handle @ jquery-3.3.1.min.js:2


Browser Network errors

Code:
bill: "{\"customer_id\":\"1\",\"product_price_with_discount\":\"5000.00\",\"product_discount_amount\":\"0.00\",\"product_note\":\"\"}]}"

bill_id: 0
close_bill: 0
csrf_ghive: 6555e8953c1aee584cf2472c1ad14a4d
I generally use ajaxPrefilter(https://api.jquery.com/jquery.ajaxPrefilter/) in my projects:

Code:
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {

        if (options.type.toLowerCase() === "post" && options.processData != false) {

            // initialize `data` to empty string if it does not exist
            options.data = options.data || "";

            // add leading ampersand if `data` is non-empty
            options.data += options.data ? "&" : "";

            // add _token entry
            options.data += csrf_name + "=" + csrf;
        }

I just need to define the values csrf_name, csrf in the header for example, that all requests from my system are sent with this security token.
Preset Apache mod_rewrite Flags modified RewriteRules causing AJAX requests to fail.The solution is either:

1. Deactivate mod_rewrite if you can on your hosting (not recommended)

2. Change .htaccess of codeigniter installation from:

Code:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]
RewriteCond $1 !^(index\.php|images|robots\.txt)

to:

Code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>
This may work for you, but I would not go that way...