1

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);

}
  • Typo. You're missing an `=` in the querystring you build. This is why it's better practice to provide a POJS object to `data` and let jQuery serialise it for you, where possible. – Rory McCrossan Mar 08 '21 at 14:45
  • actually that's happened here while posting the question. My code has `=`. Howevent have edit my question. Result is same stil – adhirath wcities Mar 08 '21 at 15:00
  • In which case check how the `get_csrf_token_name()` and `get_csrf_hash()` methods expect to read the value. It's a little odd having them in the querystring. I would normally expect them to be sent as headers. – Rory McCrossan Mar 08 '21 at 15:05
  • I am not using Form so this is the best I can send the value to controller. I don't know what to do next? – adhirath wcities Mar 08 '21 at 15:11
  • if you are using multi form this answere may help you https://stackoverflow.com/a/69407364/6559546 – soma Oct 01 '21 at 14:22

2 Answers2

1

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,
    
    // ...
});
steven7mwesigwa
  • 5,701
  • 3
  • 20
  • 34
0

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

$config['csrf_regenerate'] = FALSE;
George Sun
  • 968
  • 8
  • 21
soma
  • 61
  • 1
  • 10