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
First published: 16th August 2018