Jump to content

Using CSRF protection with AJAX doesn't work as expected


abdus
 Share

Recommended Posts

Hey,
I've been trying to implement some progressive enhancements to take advantage of modern browsers, modern JS and CSS capabilities etc. One thing I've got stuck is to CSRF protection using $session->CSRF.

I'm echoing hidden token using <?= session()->CSRF->renderInput('contact') ?> inside the form, and I can validate the token with plain POST request (without AJAX) just fine using session()->CSRF->hasValidToken('contact').

For AJAX, I'm setting headers x-<tokenname>:<tokenvalue>. It shows up in both Chrome DevTools  correctly, and on backend lke HTTP_X_<TOKENNAME> => <TOKEN_VALUE> as expected, so there's no miscommunication. But, when I try to validate it, it fails no matter what.

After some debugging I realized at each request, a new token is created, which invalidates the one I'm sending. Here are the relevant parts from the core.

Inside /wire/core/SessionCSRF.php, where validation occurs

<?php
public function hasValidToken($id = '') {

    $tokenName = $this->getTokenName($id);
    $tokenValue = $this->getTokenValue($id);
    
    // ...

    if($this->config->ajax && isset($_SERVER["HTTP_X_$tokenName"]) && $_SERVER["HTTP_X_$tokenName"] === $tokenValue) return true;
    if($this->input->post($tokenName) === $tokenValue) return true;

    // if this point is reached, token was invalid
    return false;
}

it gets token name from here where it checks inside $_SESSION variable

<?php 
public function getTokenName($id = '') {
    $tokenName = $this->session->get($this, "name$id");
    // Why can't it find token inside $_SESSION global?
    if(!$tokenName) {
        $tokenName = 'TOKEN' . mt_rand() . "X" . time(); // token name always ends with timestamp
        $this->session->set($this, "name$id", $tokenName);
    }
    return $tokenName;
}

I dont understand why it cannot find correct token and regenerates? Does session not last until browser closes? I can save other data to $session, and get it just fine, am I missing something?

  • Like 1
Link to comment
Share on other sites

  • abdus changed the title to Using CSRF protection with AJAX doesn't work as expected

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...