Cakephp 3.8 CSRF token mismatch

Hi,

I have controllers that keep throwing CSRF token mismatch. on form submit…
But i checked, the token is there and correct in the form, strangely all my controllers with prefix are working properly, those without are not can be a path to solution?

Thanks
Kind regards

at those lines i have debugged

    $cookies = $request->getCookieParams();
    $cookie = Hash::get($cookies, $this->_config['cookieName']);
    $post = Hash::get($request->getParsedBody(), $this->_config['field']);
    $header = $request->getHeaderLine('X-CSRF-Token');

    debug($cookie);
    debug($post);
    debug($header);

and here are the outputs

\src\Http\Middleware\CsrfProtectionMiddleware.php (line 227 )
‘15fd588e03433b36c7d985cda310df52529818f9ccd9b0fa6fb83cc6b049b48fc538ecad67dc93fb8cbdb9c3cf7f21a900ea93cdbe5fb5af996097397aee5ef3’

\src\Http\Middleware\CsrfProtectionMiddleware.php (line 228 )
‘15fd588e03433b36c7d985cda310df52529818f9ccd9b0fa6fb83cc6b049b48fc538ecad67dc93fb8cbdb9c3cf7f21a900ea93cdbe5fb5af996097397aee5ef3’

\src\Http\Middleware\CsrfProtectionMiddleware.php (line 229 )
‘’

\src\Http\Middleware\CsrfProtectionMiddleware.php (line 227 )
null

\src\Http\Middleware\CsrfProtectionMiddleware.php (line 228 )
‘15fd588e03433b36c7d985cda310df52529818f9ccd9b0fa6fb83cc6b049b48fc538ecad67dc93fb8cbdb9c3cf7f21a900ea93cdbe5fb5af996097397aee5ef3’

\src\Http\Middleware\CsrfProtectionMiddleware.php (line 229 )
‘’

So first time the header was missing the token on a regular form (not ajax)
ANd second time the cookie in the params is nulll…

ALSO what i don’t get is why on a single form submission it goes twice through the validation

UPDATE:

Defintely it comes from the fact that this validation is being called twice instead of once, as long as I comment this line
//unset($body[$this->_config[‘field’]]);
Then of course it does not throw the same token mismatch because at teh second check the field is still there but why IT IS CHECKING twice??

You haven’t shown where that unset line is, or anything about where the data is validated, so it’s quite hard to tell why it might be checking twice.

the unset is happening here
protected function _validateAndUnsetTokenField(ServerRequest $request)
{
if (in_array($request->getMethod(), [‘PUT’, ‘POST’, ‘DELETE’, ‘PATCH’], true) || $request->getData()) {
$this->_validateToken($request);
$body = $request->getParsedBody();
if (is_array($body)) {
// unset($body[$this->_config[‘field’]]);
$request = $request->withParsedBody($body);
// debug($body);
}
}
return $request;
}
ANd i think from teh code those function are being call on any PUT, GET, POST,…or i there is getData…
so it means that there in those controllers the _validateAndUnsetTokenField is being called twice…

Thanks for taking of your time (AGAIN lol) to check this…

You could dump the stack trace in this function to find why it’s getting called twice. I’m going to guess that you’ve simply added this middleware to your stack twice, presumably the second one is in code that the “controllers with prefix” aren’t running, hence why they’re fine.

I feel dumb, last time you told me already about stack trace, could not get it to run on my project :frowning:

https://www.php.net/manual/en/function.debug-print-backtrace.php

Hi,
now i feel more dumb, i am pretty good on googling and dr google teachnig but this one I had not find…
“_validateAndUnsetTokenField” is indeed being called twice now how o understand when and how?
Now more dumb, can’t attache the file, the print is 241 pages :frowning:

Thanks
Regards

Use the DEBUG_BACKTRACE_IGNORE_ARGS argument, and that’ll get WAY shorter.

Yeah, the only explanation for that stack trace is that you’ve got the CSRF middleware added twice.

Yes indeed I am trying to figure how and why, thought maybe creating multiplke entities and son, but no way, all this stuff happens on the post/put, i have no control on this …
I thought maybe the isAuthorized frrom the app controller on this event :slight_smile: if (!$this->request->getParam(‘prefix’)) {
return true;
}
beucase this is not happening when i am on prefixed routes…

You very much have control over when and where the middleware is added. Look through your code for CsrfProtectionMiddleware, that should find where you’re adding it. If it’s not immediately obvious from those results why it’s being added twice, then dump the stack trace there to find where those calls are coming from.

P.S. What you included before looks like the output of debug_backtrace, not debug_print_backtrace . The former is machine-friendly output, the latter is much more human-friendly.

The middleware is added once in the routing:

$routes->registerMiddleware(‘csrf’, new CsrfProtectionMiddleware([
‘httpOnly’ => true,
]));
/*
* Apply a middleware to the current route scope.
* Requires middleware to be registered through Application::routes() with registerMiddleware()
*/
$routes->applyMiddleware(‘csrf’);
This the default setup,i don’t add it anymore as a component as deprecated…

From that stack trace, it’s going through middleware in the following order:

  • CSRF
  • Error handler
  • Asset
  • Routing
  • CSRF again

So yeah, it’s being loaded twice. Take a look at where those other ones are added for hints. Dump the stack trace at the point where this routing setup is being handled, to see if it’s being called twice (and if so, from where).

Hi,

ok found out something, it comes from the routing ,
it has
$routes->registerMiddleware(‘csrf’, new CsrfProtectionMiddleware([
‘httpOnly’ => true,
]));
$routes->applyMiddleware(‘csrf’); if i comment this line with the routes without prefix, it goes just once through the process BUT i realized that with routes WITH prefix, it does not process the middleware at all!!!
SO i think i misconfigured something in my routes which I am attaching,it definitely comes from there…


Thanks

I am very much a novice at routing, so I’ll let someone else comment on this, if you can’t sort it out yourself from the documentation. At least you know where it’s coming from now.