Reputation: 71
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
Reputation: 71
If you are using Codeigniter vertion 3.0, add this in config:
$config['csrf_regenerate'] = FALSE;
Upvotes: 0
Reputation: 6710
Well, it's because you're doing it all wrong.
Your type="hidden"
input
elements have no name=...
attributes.
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'];?>" /> ✅
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