I enabled the csrf_protection option in codeigniter\'s config file, and used form_open() function to create my forms. But when I submit the form, this error occurs:
I've found a solution to this problem which is quite simple. I removed the div with the display:none style surrounding the csrf_protection input. The div is not relevant since the input type is set to hidden. In CodeIginiterFolder/system/helpers/form_helper.php, I changed the following content (around line 75) :
if (is_array($hidden) AND count($hidden) > 0)
{
$form .= sprintf("<div style=\"display:none\">%s</div>", form_hidden($hidden));
}
for the following one :
if (is_array($hidden) AND count($hidden) > 0)
{
$form .= form_hidden($hidden);
}
change line no 451
$config['csrf_protection'] = true;
to
$config['csrf_protection'] = false;
Because this csrf_protection
is deprecated in CodeIgniter
.
In config/config.php I have
$config['csrf_token_name'] = 'my.token.name';
But when I use var_dump for $_POST I see:
["my_token_name"]=> string(32) "f5d78f8c8bb1800d10af59df8c302515"
CI change my csrf_token_name (sic!)
Solution: I changed
$config['csrf_token_name'] = 'my.token.name';
to
$config['csrf_token_name'] = 'my_token_name';
Now it works.
To everyone who tried everything that was suggested here, and still has this problem.
My issue was the expiration time of the cookie.
$config['csrf_expire'] = 7200;
Afte the cookie expires and the user tries to submit an form, they will get the error
The action you have requested is not allowed.
I added a simple javascript to every page, which fixes the issue for 99% of your users. (the 1% being users who have JS disabled in their browser)
setInterval(function () {
if(alert('Your session has expired!')){}
else window.location.reload();
}, 7200000);
For those that may still be having an issue with this and for completeness I wanted to add some more information.
I ran into this issue an although some of the answers above were helpful there are a few other things to consider when dealing with csrf.
Starting from the top, and to make this as simple as possible.
If your using autoload.php I typically load these. Not all are needed to correct the issue.
Autoload.php
$autoload['libraries'] = array('session','database','form_validation','user_agent', 'encryption');
$autoload['helper'] = array('url', 'file', 'form');
Config.php
$config['base_url'] = 'http://somesite.org:4848/'; // Port if ur running multiple servers same machine
$config['encryption_key'] = 'kidh743ty9fhw9afh4739hq978h'; //Get an encrypt key, make sure its set
//Sessions
$config['sess_driver'] = 'database';
$config['sess_cookie_name'] = '_ss_session';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = 'Sessions';
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;
// Cookies
$config['cookie_prefix'] = '_ss_cookie';
$config['cookie_domain'] = '.somesite.org'; // No leading slash here, cookie will not set
$config['cookie_path'] = '/';
$config['cookie_secure'] = FALSE;
$config['cookie_httponly'] = FALSE;
// Global XSS - This is deprecated in version 3
$config['global_xss_filtering'] = FALSE;
// CSRF
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = '_ss_csrf_token';
$config['csrf_cookie_name'] = '_ss_csrf_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
$config['csrf_exclude_uris'] = array();
The Controller - The best method for handling csrf is to use a redirect and set flash data.
Register.php
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Register extends CI_Controller
{
function __construct(){
parent::__construct();
}
public function index(){
$this->load->view('auth/register');
}
public function validate(){
$full_name = $this->input->post('full_name');
$email = $this->input->post('email');
$password = $this->input->post('password');
$password_again = $this->input->post('password_again');
$agree = $this->input->post('agree');
// do something here, then base your redirect on the response
$some_model_data = $this->register_model->validate($data);
if($this->input->is_ajax_request()){
// echo a json response with the token
// Response array
// use javascript to add the new token to the form
$response = array(
'data' => $some_model_data,
'token'=> $this->security->get_csrf_hash();
);
// json response
echo json_encode($response);
}else{
// redirect to the page
$this->__validate_redirect($some_model_data);
}
}
private function __validate_redirect($where_to){
switch ($where_to->redirect) {
case 'register_page':
redirect(base_url().'register/');
break;
case 'success':
redirect(base_url().'register/success');
break;
default:
redirect(base_url().'register/');
break;
}
}
}
?>
In the view just make sure you either use:
<?php echo form_open(); ?>
This will set the csrf token or use the following inside your form in a hidden input:
<?php echo $this->security->get_csrf_token_name(); ?>
This should be all thats needed to prevent the csrf error for the most part.
The problem solved by this Solution:
set
$config['cookie_secure']
in config file to FALSE if you're using HTTP.