Csrf middleware causing problems


#1

Hello,
I have implemented a custom not found handler and error handler . They both work fine but when i add csrf handler to all my routes and then try a non-existing link i get message : session not found with slim’s own error page. I am having trouble getting to 404 not found page it keeps going to csrf session not found. Is there a way to implement my not found handler inside csrf error handler just to make it more user friendly?


#2

When are you starting the session? Have you looked at \Slim\Csrf\Guard's setFailureCallable()? I would also consider only adding CSRF checks to routes that need it, rather than all routes.


#3

Hi, thanks for your reply.

I have done adding csrf to selected routes and no issue with that. I am trying to understand it more deeply thus added it to all routes. What happens is for undefined routes ,i am still getting csrf error messages instead of my not found handler or even slims default 404 page not found. I tried different things with setcallback failure method. What i am trying to do now is inside of csrf failure method somehow mask it as 404 error page (or anything else).

And no i am not using sessions. Although the doc says that csrf uses session storage as default ( again if i want to change that?) , my forms are working fine on registered routes.


#4

Since you’re getting a session not found error I’d try following the docs and start the session when bootstrapping the app, just to see what happens.


#5

Case 1: Inside of my csrf container I added session_start() and it works as expected now. I am getting 404 not found on non-defined routes . But now,if I am to add my login page,I get new error : session already started .
Case 2: I made my login page , started a session and applied csrf to my secured routes. After logging in,if I enter a wrong path in url,I still get the same csrf message: session not found ,even though session is already started .

Please,explain if this has something to do with it . I want to use redirections to named routes and someone told me to use this.
$config[‘determineRouteBeforeAppMiddleware’]= true;


#6

It sounds like you might need to either search your code for session_start(), or step through your code to see exactly where sessions are, or are not being started. Is this Slim’s CSRF package, or a different one? determineRouteBeforeAppMiddleware shouldn’t be needed based on what you’ve described, but might be if something else in your middleware requires it.


#7

Hi, I am doing everything over again.

<?php

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

require ‘…/vendor/autoload.php’;

$config[‘displayErrorDetails’] = true;
$config[‘addContentLengthHeader’] = false;
$config[‘determineRouteBeforeAppMiddleware’]= true;
$config[‘db’][‘host’] = “localhost”;
$config[‘db’][‘user’] = “root”;
$config[‘db’][‘pass’] = “”;
$config[‘db’][‘dbname’] = “gleda_db”;

$app = new \Slim\App([“settings” => $config]);;

$container = $app->getContainer();

$container[‘view’] = new \Slim\Views\PhpRenderer("…/templates/");

$container[‘logger’] = function($c) {
$logger = new \Monolog\Logger(‘my_logger’);
$file_handler = new \Monolog\Handler\StreamHandler("…/logs/app.log");
$logger->pushHandler($file_handler);
return $logger;
};

$container[‘db’] = function ($c) {
$db = $c[‘settings’][‘db’];
try
{
$pdo = new PDO(“mysql:host=” . $db[‘host’] . “;dbname=” . $db[‘dbname’],
$db[‘user’], $db[‘pass’]);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
catch(PDOException $e)
{
$c->logger->addInfo(“PDO error”);
echo (“Error connecting to database”. $e);
exit();
}

return $pdo;
};

$container[‘notFoundHandler’] = function ($c) {
return function ($request, $response) use ($c) {
return $c[‘response’]
->withStatus(404)
->withHeader(‘Content-Type’, ‘text/html’)
->write(‘Page not found’);
};
};

$container[‘flash’] = function () {
return new \Slim\Flash\Messages();
};

$container[‘csrf’] = function ($c) {

session_start();

return new \Slim\Csrf\Guard;
/*
$guard=new \Slim\Csrf\Guard;

   $guard->setFailureCallable(function ($request, $response, $next) {
    
  	$response=$c->notFoundHandler;
  	
    return $next($request, $response);

});

return $guard; */

};

$container[‘upload_directory’] = DIR . ‘/uploads’;

$app->add($container->get(‘csrf’));

$app->get(’/somepage’,function($request,$response){

$response->getBody()->write(“something”);
return $response;

});

$app->run();

?>

If I remove that session_start() line inside my container,I am back to where I started. The above code works fine, but I am unable to find the effect of that session . It it destroyed when the middleware is done or it persists?


#8

The length of the session will depend on the way PHP is configured, I recall there is a setting in php.ini to handle that. Unless of course you are using cookies or manually destroying the session.

Again, I would try to follow what the docs suggest first, which would be to start the session first, perhaps just before you require the autoloader and not within your middleware.

Also, CSRF will not be checked on that route as it is a GET route.


#9

Thats what i am looking for. In the above code , if i make only 1 route and that is GET ,and if csrf ignores that , then the route should work without starting the session ,right ? My primary question is i am not getting 404 error page,csrf takes over even that.

I appreciate your help very much. I have gone through the document ,just trying out different things for fun.No worries :slight_smile:


#10

Since you have applied the Guard middleware to the route, the Guard middleware will be run. The Guard middleware will then call 1session_start()1 since you have told it to in the container entry. CSRF checks themselves will be ignored, but in your case above session_start() is still being called.

If the session hasn’t been started by the time Guard runs, it will throw an exception.