adhirath wcities
adhirath wcities

Reputation: 71

Unable to validate CSRF at controller in codeIgniter with ajax

I am new to CSRF and codeigniter. However, I have referred so many solution here and after applying I am able to go some extent but unable to validate the CSRF at controller end. I am getting the error

The action you have requested is not allowed.

I am posting my entire code here. Though I am using this for registration but I am not using Form to submit the request but with the help of ajax.

Config

$config['csrf_protection']  = TRUE;
$config['csrf_token_name']  = 'csrfName';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire']      = 7200;

View

I am not going to post All the fields but few. Firstname, lastname, email, password.. etc are there

<?php 
$csrf = array(
    'csrfName' => $this->security->get_csrf_token_name(),
    'csrfHash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" class="csrfName" value="<?php echo $csrf['csrfName'];?>" />
<input type="hidden" class="csrfHash" value="<?php echo $csrf['csrfHash'];?>" />
<div class="row">
    <div id="join_btn" onclick="email_signup('joinBox')">SIGN UP</div>
</div>

JS

There are other fields as well but i am posting here important one

var csrfValue   = $(".csrfHash").val();
var csrfName    = $(".csrfName").val();
var callParameters = "call=email_signup&csrfHash="+csrfValue+"&csrfName="+csrfName;

$.ajax({
    url:ajaxcalls.php,
    data:callParameters,
    type:"POST",
    cache:false,
    dataType:"json",
    success: function(resp){

    }
});

Controller

function email_signup($params){
    $csrfName = $this->security->get_csrf_token_name();
    $csrfHash = $this->security->get_csrf_hash();

    $result['flag'] = "success";
    echo json_encode($result);

}

Upvotes: 1

Views: 491

Answers (2)

soma
soma

Reputation: 71

If you are using Codeigniter vertion 3.0, add this in config:

$config['csrf_regenerate'] = FALSE;

Upvotes: 0

steven7mwesigwa
steven7mwesigwa

Reputation: 6710

Well, it's because you're doing it all wrong.

Mistake 1:

Your type="hidden" input elements have no name=... attributes.

Mistake 2:

The input element that holds the csrfName i.e (name="<?php echo $csrf['csrfName'];?>") expects a csrfHash as it's value=....

In addition, both the csrfName and csrfHash need to be defined in one input HTML element. Not two.

Cross-site request forgery (CSRF)

So:

<!-- Instead of: -->

<input type="hidden" class="csrfName" value="<?php echo $csrf['csrfName'];?>" /> ❌
<input type="hidden" class="csrfHash" value="<?php echo $csrf['csrfHash'];?>" /> ❌


<!-- Use this: -->

<input type="hidden" name="<?php echo $csrf['csrfName'];?>" class="csrfName" value="<?php echo $csrf['csrfHash'];?>" />  ✅

Suggestions

Since you're using jQuery already, to prepare your POST data, the .serializeArray() method would sound sufficient instead of manually building 'query strings'. i.e:

// ...

let $formData = $("form").serializeArray()

// ...

You can then append any extra data you intend to pass along with the HTML form elements if you wish..i.e:


// ...
let $formData = $("form").serializeArray()

$formData.push({name: 'call', value: 'email_signup'})

$.ajax({
    // ...
    
    data: $formData,
    
    // ...
});

Alternatively, you can build the POST data using FormData().

If you choose this option, don't forget to add processData: false and contentType: false to your $.ajax({...}) object argument. i.e:


let $formData = new FormData($("form").get(0))

$formData.append('call', 'email_signup')

$.ajax({
    // ...
    
    data: $formData,
    processData: false,
    contentType: false,
    
    // ...
});

Upvotes: 1

Related Questions