Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CodeIgniter 2, Ion Auth gives a CSRF error message upon profile edit

I've been using CodeIgniter version 2.1.4 with Ion Auth for quite some time and everything was working great. Yesterday, I updated Ion Auth to the latest version and now I get a CSRF error whenever I try to "edit" any user profile.

"This form post did not pass our security checks."

I get this error after modifying the controllers/auth.php file so that the various Ion Auth views are loaded into my own template. After all, what good is this if I cannot integrate it into my site design. However, I also get this error in an older version of Safari even when the auth.php controller is not modified at all.

This is my simple modification to the auth.php controller file.

Replaced this line:

$view_html = $this->load->view($view, $this->viewdata, $render);

With this line:

$view_html = $this->template->load('default', $view, $this->viewdata, $render);

Yes, my load function (in the Template.php file located in /libraries/) has been working just fine since the beginning (many months ago). Even with the new version of Ion Auth, my template loading function is working... however, I just keep getting the security error as described above.


After doing some research, the cause of the error is Ion Auth's CSRF security routine. These two functions are called throughout the auth.php controller and display the error above whenever the _valid_csrf_nonce() function returns false.

function _get_csrf_nonce()
{
    $this->load->helper('string');
    $key   = random_string('alnum', 8);
    $value = random_string('alnum', 20);
    $this->session->set_flashdata('csrfkey', $key);
    $this->session->set_flashdata('csrfvalue', $value);

    return array($key => $value);
}

function _valid_csrf_nonce()
{
    if ($this->input->post($this->session->flashdata('csrfkey')) !== FALSE &&
        $this->input->post($this->session->flashdata('csrfkey')) == $this->session->flashdata('csrfvalue'))
    {
        return TRUE;  // <-- no error
    }
    else
    {
        return FALSE; // <-- error
    }
}

As a temporary (or permanent?) workaround, I've enabled the "CSRF Protection" option on line 298 in the CodeIgniter config/config.php file.

$config['csrf_protection'] = TRUE;  // enabled CSRF protection
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;

Then I suppressed the CSRF protection in Ion Auth by always returning true from the function.

function _valid_csrf_nonce()
{
    return TRUE;
}

However, I really want to understand the root cause here. Why am I getting all these CSRF errors simply by using older browsers or by trying to put the Ion Auth views within my own templates? Everything is on the same server using the same domain.

(edit: yes, the CI session library is being auto-loaded and apparently working fine. I can stay logged in, after all.)

like image 746
Sparky Avatar asked Dec 25 '22 18:12

Sparky


1 Answers

I never did get to the root cause, however I have a theory that might explain some of this:

The Ion Auth CSRF Protection depends on flashdata, where flashdata only survives "the next" call to the server. My custom template loader might be calling the server twice since it first calls my loader function where the page is constructed, and then calls CodeIgniter's view function.

However, this theory does not really explain why an unmodified version of Ion Auth still fails in Safari. Feel free to post another answer if you can add anything substantial or conclusive to this.


As per a personal response from Ben Edmunds, the developer of Ion Auth...

"We added CSRF protection to the Ion Auth examples before CI built them into the framework so you might be best just removing them from the Ion Auth example controller and views if you’re using a newer version of CI with that built in."

Since I'm already using the latest version of CodeIgniter (2.1.4), I've decided to go this route.

The temporary workaround from my OP is now permanent:

I've enabled the "CSRF Protection" option on line 298 in the CodeIgniter config/config.php file.

$config['csrf_protection'] = TRUE;  // enabled CSRF protection

Then I suppressed the CSRF protection in Ion Auth by always returning true from this function.

function _valid_csrf_nonce()
{
    return TRUE;  // effectively disables Ion Auth's CSRF protection
}

And finally, the developer commenting on using CodeIgniter's CSRF protection instead:

"Cool, that's really a better solution anyway since it's integrated throughout your application."

like image 152
Sparky Avatar answered Dec 31 '22 13:12

Sparky