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:
<?php
class SecurityMiddleware extends \Slim\Middleware
{
protected $resource;
public function __construct($resource)
{
$this->resource = $resource;
}
public function call()
{
//get a reference to application
$app = $this->app;
//skip routes that are exceptionally allowed without an access token:
$publicRoutes = ["/","/login","/about"];
if (in_array($app->request()->getPathInfo(),publicRoutes)){
$this->next->call(); //let go
} else {
//Validate:
if ($this->resource->isValid()){
$this->next->call(); //validation passed, let go
} else {
$app->response->setStatus('403'); //validation failed
$app->response->body(json_encode(array("Error"=>"Access token problem")));
return;
}
}
}
}
This works, but the undesired side effect is the middleware does not make a distinction between existing routes and non-existing routes. For example, if a the user attempts to request a route like /dfghdfgh
which does not exist, instead of getting an HTTP status code of 404 he'll get a 403 saying there is no access token. I would like to add an implementation similar to the following check on the middleware class:
if ($app->hasRoute($app->request->getPathInfo()){
$this->next->call(); //let go so user gets 404 from the app.
}
Any ideas how this can be achieved?
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With