Search code examples
routescsrfmiddlewareslim-3

Slim3 exclude route from CSRF Middleware


I'm building a webshop based on the slim3 framework. I need to handle a server-to-server POST-request to confirm if payment was successful. I added csrf to the container like this:

$container['csrf'] = function($container) {
    return new \Slim\Csrf\Guard;
};

and added it to the app like this:

$app->add($container->csrf);

And it works good. But now i need to be able to add an exception to a certain route so i get the post reques they are sending. I'couldn't find a working solution so far.

Any advice?


Solution

  • If you need to exclude one route from a middleware, there are two options:

    Option 1: group your routes.

    You can group all routes except the one:

    <?php
    $app->group('', function() {
    
        // All routes declarations....
    
    })->add($container->csrf); // Add middleware to all routes within the group
    
    // Declare your "exceptional" route outside the group
    $app->post('my-special-route-that-has-no-csrf-middleware', 'routeProcessor');
    

    Option 2: use your own middleware

    Instead of using \Slim\Csrf\Guard directly, use your own middleware that extends it. Your middleware will check the route, and if route is the "exceptional" one, it will skip.

    Add this to settings since you need to access route within middleware:

    $container['settings'] => [
        'determineRouteBeforeAppMiddleware' => true
    ];
    

    Create the middleware extending orginial \Slim\Csrf\Guard:

    <?php
    class MyCsrfMiddleware extends Slim\Csrf\Guard
    {
        // This method is processing every request in your application
        public function processRequest($request, $response, $next) {
            // Check if it's your "exceptional" route
            $route = $request->getAttribute('route');
            if ($route == 'my-special-path') {
                // If it is - just pass request-response to the next callable in chain
                return $next($request, $response);
            } else {
                // else apply __invoke method that you've inherited from \Slim\Csrf\Guard
                return $this($request, $response, $next);
            }
        }
    }
    
    /////////////
    
    $container['csrf'] = function($container) {
        return new MyCsrfMiddleware; // Now the container returns your middleware under 'csrf' key
    };
    

    Now simply add the middleware to \Slim\App instance:

    $app->add('csrf:processRequest');