I\'m writing a REST API with Slim. I have written a small middleware to protect the resources so only authenticated users will be able to access them:
Not exactly what you asking for, but personnaly when i need to check authentification on some routes i do it like this.
config:
$config = array(
...,
'user.secured.urls' => array(
array('path' => '/user'),
array('path' => '/user/'),
array('path' => '/user/.+'),
array('path' => '/api/user/.+')
),
...
);
middleware:
/**
* Uses 'slim.before.router' to check for authentication when visitor attempts
* to access a secured URI.
*/
public function call()
{
$app = $this->app;
$req = $app->request();
$auth = $this->auth;
$config = $this->config;
$checkAuth = function () use ($app, $auth, $req, $config) {
// User restriction
$userSecuredUrls = isset($config['user.secured.urls']) ? $config['user.secured.urls'] : array();
foreach ($userSecuredUrls as $url) {
$urlPattern = '@^' . $url['path'] . '$@';
if (preg_match($urlPattern, $req->getPathInfo()) === 1 && $auth->hasIdentity() === false) {
$errorData = array('status' => 401,'error' => 'Permission Denied');
$app->render('error.php', $errorData, 401);
$app->stop();
}
}
};
$app->hook('slim.before.router', $checkAuth);
$this->next->call();
}
but if almost all your routes need authentification maybe not the best solution.
great example: http://www.slideshare.net/jeremykendall/keeping-it-small-slim-php
Maybe my implementation will work for you:
<?php
class CustomAuth extends \Slim\Middleware {
public function hasRoute() {
$dispatched = false;
// copied from Slim::call():1312
$matchedRoutes = $this->app->router->getMatchedRoutes($this->app->request->getMethod(), $this->app->request->getResourceUri());
foreach ($matchedRoutes as $route) {
try {
$this->app->applyHook('slim.before.dispatch');
$dispatched = $route->dispatch();
$this->app->applyHook('slim.after.dispatch');
if ($dispatched) {
break;
}
} catch (\Slim\Exception\Pass $e) {
continue;
}
}
return $dispatched;
}
public function call() {
if ($this->hasRoute()) {
if ($authorized) {
$this->next->call();
}
else {
$this->permissionDenied();
}
}
else {
$this->next->call();
}
}
}
I use a hook to do what you're trying to do, as MamaWalter suggested, but you want to use slim.before.dispatch
rather than an earlier hook. If the route your user is trying to visit doesn't exist, the hook will never be called and the 404
gets thrown.
I'm doing exactly that in my own Authorization Middleware. Works like a charm.