JWT middleware is executing in wrong order of middlewares
agostinhodev opened this issue · 2 comments
I have a API that allow many companies to connect to them and use my services.
I have two files:
index.php
<?php
require_once "config/env.php";
require_once "../vendor/autoload.php";
$app = new Slim\App(
[
'settings' =>[
'displayErrorDetails' => true,
],
]
);
use src\middlewares\Empresa;
$app->group('/v1', function () use ($app){
require_once "./routes/usuario.php";
require_once "./routes/pessoa.php";
});
$app->add( new Empresa ); // First middleware. Need to be executed in first time to check company HEADER and set enviroment variable
$app->run();
?>
and one file called routes/pessoa.php
<?php
use src\controllers\Pessoa;
use src\middlewares\JwtAuth;
$app->group('/pessoa', function () use ($app){
$app->post('', Pessoa::class . ":nova")->add(JwtAuth::validateToken()); // Second middleware. Need to be executed after first middleware and need to get access to the enviroment variable
});
Note that i put a middleware called Empresa wich need to be executed before that JwtAuth middleware because it receive a HEADER from my request wich i send my client company's name to get a enviroment variable base on this HEADER name.
However, the JwtAuth is returning before that my Empresa middleware can be executed.
This is executing in wrong sequence in my perception.
What would be the problem?
src/middlewares.php
<?php
namespace src\middlewares;
use src\database\Database;
final class Empresa {
private $empresas = [
"businness1",
"businness2"
];
public function __invoke($request, $response, $next)
{
$empresa = isset($request->getHeaders()['HTTP_EMPRESA'][0]) ? $request->getHeaders()['HTTP_EMPRESA'][0] : NULL ;
if(is_null($empresa)){
$response = $response->withJson([
"message" => "Informe a empresa corretamente"
])->withStatus(400);
} else {
if(!in_array($empresa, $this->empresas)){
$response = $response->withJson([
"message" => "A empresa informada não existe"
])->withStatus(404);
} else {
$request = $request->withAttribute('empresa', $empresa);
putenv("APP_NOME_EMPRESA=$empresa");
$response = $next($request, $response);
}
}
return $response;
}
}
src/middlewares/JwtAuth
<?php
namespace src\middlewares;
use Tuupola\Middleware\JwtAuthentication;
final class JwtAuth{
public function validateToken() : JwtAuthentication
{
$jwtkey = getenv('APP_NOME_EMPRESA');
//Here's the wrong. According with the Slim doc, the first middleware added it's the last to be executed.
// But in here i can't access the enviroment variable...
// I need to know how company is requesting to generate a JWT verification. But this don't happen.
switch($type){
default:
case 'login':
$jwtkey .= getenv('API_JWT_TOKEN_SUFIX');
break;
}
return new JwtAuthentication([
'secure' => false,
'secret' => $jwtkey,
'attribute' => 'jwt',
'error' => function ($response, $arguments) {
$data["message"] = $arguments["message"];
return $response
->withHeader("Content-Type", "application/json")
->getBody()->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]);
}
}
Middleware cannot affect the order it is executed. Both Slim 3 and 4 use LIFO. Meaning if you add middlewares as the following:
$app->add('middleware3');
$app->add('middleware2');
$app->add('middleware1');
The execution order will be:
- middleware1
- middleware2
- middleware3
Ie. If you want Empresa
middleware to be executed first you need to add it last.
$app->add($jwtAuthentication);
$app->add($empresa);
If you are looking to use multiple keys, you can also pass them as anything which implements ArrayAccess.
new JwtAuthentication([
"secret" => [
"xxxx" =>"supersecretkeyyoushouldnotcommittogithub",
"yyyy" =>"anothersecretkeyfornevertocommittogithub"
]
]);
No feedback.