Code Playground.

How to Send AJAX request with CSRF token in CodeIgniter

CFG

How to Send AJAX request with CSRF token in CodeIgniter

In CodeIgniter, CSRF security isn't empowered as a matter of course. 

In the event that it is been empowered, at that point CodeIgniter creates a hash for every dynamic client and this is utilized to confirm the solicitation. 

Require to send the hash with the AJAX demand else, it gives mistake – "The activity you have mentioned isn't permitted.". 

Right now, show how you can empower CSRF insurance and recover hash for next AJAX solicitation and pass hash in AJAX demand in the CodeIgniter venture. 

  • Table structure 

Right now, am utilizing clients table and included a few records – 

CREATE TABLE `users` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(80) NOT NULL,
  `username` varchar(80) NOT NULL,
  `gender` varchar(10) NOT NULL,
  `email` varchar(80) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • Setup 

Empower CSRF assurance – 

Open application/config/config.php file and update the values of $config['csrf_protection'], $config['csrf_token_name'], and $config['csrf_regenerate'] like this –

$config['csrf_protection'] = TRUE;  // Enable CSRF
$config['csrf_token_name'] = 'csrf_hash_name'; // Token name (You can update it)
$config['csrf_regenerate'] = TRUE; // Set TRUE to regenerate Hash
  • Set TRUE the $config['csrf_protection'], this will empower CSRF. 
  • You can change the estimation of $config['csrf_token_name'] default it is set to 'csrf_test_name'. I transformed it to 'csrf_has_name'. This name is utilized in AJAX solicitation to pass the hash. 
  • Set TRUE the $config['csrf_regenerate'] in the event that you need to recover CSRF hash after every AJAX demand in any case set it FALSE. 

Open application/config/database.php and characterize the Database association. 

$db['default'] = array(
 'dsn' => '',
 'hostname' => 'localhost',
 'username' => 'root', // Username
 'password' => '', // Password
 'database' => 'tutorial', // Database name
 'dbdriver' => 'mysqli',
 'dbprefix' => '',
 'pconnect' => FALSE,
 'db_debug' => (ENVIRONMENT !== 'production'),
 'cache_on' => FALSE,
 'cachedir' => '',
 'char_set' => 'utf8',
 'dbcollat' => 'utf8_general_ci',
 'swap_pre' => '',
 'encrypt' => FALSE,
 'compress' => FALSE,
 'stricton' => FALSE,
 'failover' => array(),
 'save_queries' => TRUE
);

Default controller 

Open application/config/routes.php and alter default_controller incentive to User. 

$route['default_controller'] = 'User';

Burden Database 

To get to the MySQL database require stacking database library. 

Open application/config/autoload.php and include the database in libraries exhibit(). 

$autoload['libraries'] = array("database");
  • Model 

Make a Main_model.php record in the application/models/registry. 

Make getUserDetails() technique which takes a solitary parameter. 

Check if $postData['username'] is set or not. Whenever set at that point get a record from clients table where username=$postData['username']. 

Return the $response Array. 

Completed Code 

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Main_model extends CI_Model {

  function getUserDetails($postData){
 
    $response = array();
 
    if(isset($postData['username']) ){
 
      // Select record
      $this->db->select('*');
      $this->db->where('username', $postData['username']);
      $q = $this->db->get('users');
      $response = $q->result_array();
 
    }
 
    return $response;
  }

}
  • Controller 

Make User.php document in application/controllers/registry. 

Make 2 strategies – 

  • index – Load url partner and user_view see. 
  • userDetails – This strategy is utilized to deal with the AJAX solicitation and return a reaction. 

Peruse POST esteems and allot in $postData. Burden Main_model Model and call getUserDetails() technique where pass $postData. 

Dole out return an incentive in $data and read the new CSRF hash by calling $this->security->get_csrf_hash() for next AJAX ask for and appoint in $data['token']. 

Return $data Array in JSON position. 

Completed Code 

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class User extends CI_Controller {

   public function index(){

     // load base_url
     $this->load->helper('url');

     // load view
     $this->load->view('user_view');
   }

   public function userDetails(){

     // POST data
     $postData = $this->input->post();

     // load model
     $this->load->model('Main_model');

     // get data
     $data = $this->Main_model->getUserDetails($postData);

     // Read new token and assing in $data['token']
     $data['token'] = $this->security->get_csrf_hash();

     echo json_encode($data);
   }

}
  • View 

Make user_view.php document in application/sees/catalog. 

Make a book component and store token name which is indicated in application/config.php record in name trait utilizing <?= $this->security->get_csrf_token_name(); ?>. Store CSRF hash in the component by calling <?= $this->security->get_csrf_hash(); ?>. 

Included some client names in the <select > <option>. Utilized username in the <option > esteem. 

To show chosen client subtleties made <span > components. 

Script – 

Characterize change occasion on #sel_user selector. 

Peruse name quality of .txt_csrfname selector and relegate in csrfName variable. Dole out .txt_csrfname selector esteem in csrfHash variable. 

Dole out chosen alternative incentive in username variable. 

Send AJAX POST solicitation to '<?=base_url()?>index.php/User/userDetails' the place pass {username:username,[csrfName]:csrfHash } as information. 

Here, hash will pass like – [csrfName]: csrfHash. 

On effective callback read the token from reaction and update the .txt_csrfname selector esteem. 

Circle on the response[0] and update <span > components content. 

Completed Code 

<!doctype html>
<html>
<head>
   <title>How to Send AJAX request with CSRF token in CodeIgniter</title>
</head>
<body>

    <!-- CSRF token (Here, name is 'csrf_hash_name' which is specified in $config['csrf_token_name'] in cofig.php file ) --> 
    <input type="text" class="txt_csrfname" name="<?= $this->security->get_csrf_token_name(); ?>" value="<?= $this->security->get_csrf_hash(); ?>"><br>   

    Select Username : <select id='sel_user'>
      <option value='yssyogesh'>yssyogesh</option>
      <option value='sonarika'>sonarika</option>
      <option value='vishal'>vishal</option>
      <option value='sunil'>sunil</option>
    </select>

    <!-- User details -->
    <div >
       Username : <span id='suname'></span><br/>
       Name : <span id='sname'></span><br/>
       Email : <span id='semail'></span><br/>
    </div>

    <!-- Script -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script type='text/javascript'>
    // baseURL variable
    var baseURL= "<?= base_url();?>";

    $(document).ready(function(){

       $('#sel_user').change(function(){
          // CSRF Hash
          var csrfName = $('.txt_csrfname').attr('name'); // Value specified in $config['csrf_token_name']
          var csrfHash = $('.txt_csrfname').val(); // CSRF hash
          
          // Username
          var username = $(this).val();

          // AJAX request
          $.ajax({
            url:'<?=base_url()?>index.php/User/userDetails',
            method: 'post',
            data: {username: username,[csrfName]: csrfHash },
            dataType: 'json',
            success: function(response){

              // Update CSRF hash
              $('.txt_csrfname').val(response.token);

              // Empty the elements
              $('#suname,#sname,#semail').text('');
 
              // Loop on response
              $(response[0]).each(function(key,value){

                 var uname = value.username;
                 var name = value.name;
                 var email = value.email;

                 $('#suname').text(uname);
                 $('#sname').text(name);
                 $('#semail').text(email);
              });

            }
         });
       });
    });
    </script>
</body>
</html>
  • Conclusion

On the off chance that you would prefer not to recover hash for each AJAX, at that point set FALSE to $config['csrf_regenerate'] in config.php document. Right now, new hash will be created by the CSRF expiry time set.




CFG