I am creating middleware for auth into REST API. My API is created using Slim PHP Framework, which in case provides great features to build APIs. One of these features is Middleware.
I need to check credentials in Middleware and respond with an error (HTTP code with JSON descriptions) to the user.
But unfortunately, Slim Framework gives me an exception whenever I try to halt and respond with the HTTP code.
<?php
require_once __DIR__.'/../Slim/Middleware.php';
class TokenAuth extends \Slim\Middleware {
private $auth;
const SECURED_URI_REGEX = "/^\/v\d\/store\/(orders|users|payment).*/";
const TOKEN_PARAMETER = "token";
const USER_EMAIL_PARAMETER = "user_email";
public static $credentialsArray = array(TokenAuth::TOKEN_PARAMETER,TokenAuth::USER_EMAIL_PARAMETER);
public function __construct() {
}
public function deny_access() {
print Response::respondWithHttpStatus($app,401,true);
}
public function call() {
$app = $this->app;
$uri = $app->request->getResourceUri();
if (preg_match(TokenAuth::SECURED_URI_REGEX, $uri)) {
$tokenAuth = $app->request->headers->get('Authorization');
if(isset($tokenAuth)) {
$parsedCredentials = TokenAuth::parseAndValidateCredentials($tokenAuth);
if (!$parsedCredentials) {
Response::respondWithHttpStatus($app,401,true);
}
else {
$auth = new Authenticator($parsedCredentials[TokenAuth::USER_EMAIL_PARAMETER],$app);
print $auth->userHasToken();
}
}
else {
Response::respondWithHttpStatus($app,400,true);
}
}
else {
$this->next->call();
}
}
respondWithHttpStatus method uses slim framework method $app->halt($code, $response);
In this case, when I try to execute this method I get an Exception from
Slim Framework
The application could not run because of the following error:
Details
Type: Slim\Exception\Stop
File: /var/www/api/Slim/Slim.php
Line: 1022
How to deal with this problem.
My goal is to control user credentials in middleware and if it is something wrong respond with the appropriate HTTP code and JSON message describing the reason of the error.
Maybe it is better to follow another way.
Please suggest.
ONE POSSIBLE WORKAROUND
$app->response->setStatus(400);
$app->response->headers->set('Content-Type', 'application/json');
print Response::respondWithHttpStatus($app,400,false);
And respond function
public static function basicRespond($app,$code,$message,$halt) {
if(!isset($message) || empty($message)) {
$message = Response::$RESPONSE_MAP[$code];
}
$response = json_encode($message);
if($halt===true) {
$app->halt($code, $response);
}
else {
return $response;
}
}
For my needs suits well, also throwing an exception can be another solution but in my case, I don't need to continue, just setting the header, code and don't call next - works for me.
You cannot use
halt
in middleware:https://stackoverflow.com/a/10201595/2970321
Instead, you could manually generate a
400
response using PHP'sheader
along withexit
:Alternatively,
you could define a new type of Exception:
Catch this in your
error
route:And throw an
AuthException
when authorization is to be denied:This is essentially how it is done in Slim-Auth.