Slim3 - Use Middleware to Check User Is Logged In

One of the most common tasks I have to perform in developing web applications is check that the user is logged in and redirect them to the login page if they are not. Also, there are certain routes, such as /login, and /register that should not incur a redirect because they need to be publicly accessible to users who have not logged in. The easiest way to do this in Slim 3 is to use middleware that will be applied to every request and will perform this logic. The relevant code is below:

...

$slimSettings = array('determineRouteBeforeAppMiddleware' => true);

if (ENVIRONMENT === 'dev')
{
    $slimSettings['displayErrorDetails'] = true;
}

$slimConfig = array('settings' => $slimSettings);
$app = new Slim\App($slimConfig);

// Check the user is logged in when necessary.
$loggedInMiddleware = function ($request, $response, $next) {
    $route = $request->getAttribute('route');
    $routeName = $route->getName();
    $groups = $route->getGroups();
    $methods = $route->getMethods();
    $arguments = $route->getArguments();

    # Define routes that user does not have to be logged in with. All other routes, the user
    # needs to be logged in with.
    $publicRoutesArray = array(
        'login',
        'post-login',
        'register',
        'forgot-password',
        'register-post'
    );

    if (!isset($_SESSION['USER']) && !in_array($routeName, $publicRoutesArray))
    {
        // redirect the user to the login page and do not proceed.
        $response = $response->withRedirect('/login');
    }
    else
    {
        // Proceed as normal...
        $response = $next($request, $response);
    }

    return $response;
};

// Apply the middleware to every request.
$app->add($loggedInMiddleware);


// Define app routes

// Show the logged in dashboard page
$app->get('/', function (Slim\Http\Request $request, \Slim\Http\Response $response, $args) {
    // redirect the user to the logged in page.
    $homeController = new HomeController($request, $response, $args);
    return $homeController->index();
})->setName('home');


// Show the login page
$app->get('/login', function (Slim\Http\Request $request, \Slim\Http\Response $response, $args) {
    $homeController = new HomeController($request, $response, $args);
    return $homeController->index();
})->setName('login');

...

As you can see, I have named every route with setName() and then check the route name in the middleware against the public routes. If the route is not a public route and the user is not logged in, then they are redirected to the login page. By having the middleware apply to every request, Whenever you create a new route, the application will assume it requires the user to be logged in. If you need the route to be publicly accessible, you just need to remember to add the name of the route to the $publicRoutesArray variable.

Accessing Route Information In Middleware

You may have noticed that I set determineRouteBeforeAppMiddleware to true in the settings which I pass to the slim application at the start. Without this, you will not be able to access the name of the route from within the middleware and will retrieve a null object. Refer here.

Taking It Further

It would be easy to copy this middleware and tweak it a bit to check specific routes that require admin access and redirect them if they are not an admin.

References

Author

Programster

Stuart is a software developer with a passion for Linux and open source projects.

comments powered by Disqus
We are a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for us to earn fees by linking to Amazon.com and affiliated sites. More info.