Commit 38db59d9 authored by François Agneray's avatar François Agneray

Authorization can be fully disabled

parent c47ecc89
......@@ -47,7 +47,7 @@ $app->group('', function (RouteCollectorProxy $group) {
'/dataset/{name}/attribute/{id}/distinct',
App\Action\AttributeDistinctAction::class
);
})->add(new App\Middleware\AdminMiddleware());
})->add(new App\Middleware\AdminMiddleware($container->get(SETTINGS)['token']));
$app->get('/search/{dname}', App\Action\SearchAction::class);
$app->get('/download-file/{dname}/[{fpath:.*}]', App\Action\DownloadFileAction::class);
......@@ -31,7 +31,9 @@ return [
'level' => getenv('LOGGER_LEVEL')
],
'token' => [
'issuer' => getenv('TOKEN_ISSUER'),
'public_key_file' => getenv('TOKEN_PUBLIC_KEY_FILE')
//'issuer' => getenv('TOKEN_ISSUER'),
'enabled' => getenv('TOKEN_ENABLED'),
'public_key_file' => getenv('TOKEN_PUBLIC_KEY_FILE'),
'admin_role' => getenv('TOKEN_ADMIN_ROLE')
]
];
......@@ -17,8 +17,9 @@ services:
LOGGER_NAME: "anis-metamodel"
LOGGER_PATH: "php://stderr"
LOGGER_LEVEL: "debug"
TOKEN_ISSUER: http://localhost:8180/auth/realms/anis
TOKEN_ENABLED: 1
TOKEN_PUBLIC_KEY_FILE: /data/public_key
TOKEN_ADMIN_ROLE: anis_admin
ports:
- 8080:80
volumes:
......
......@@ -20,20 +20,50 @@ use Nyholm\Psr7\Response as NyholmResponse;
final class AdminMiddleware implements MiddlewareInterface
{
/**
* Contains settings to handle Json Web Token
*
* @var array
*/
private $settings;
/**
* Create the classe before call process to execute this middleware
*
* @param array $settings Settings about token
*/
public function __construct(array $settings)
{
$this->settings = $settings;
}
public function process(Request $request, RequestHandler $handler): Response
{
if ($request->getMethod() === OPTIONS || $request->getMethod() === GET) {
if (
$request->getMethod() === OPTIONS
|| $request->getMethod() === GET
|| $this->settings['enabled'] === 0
) {
return $handler->handle($request);
}
$token = $request->getAttribute('token');
if (!$token) {
return (new NyholmResponse())->withStatus(401);
return $this->getResponse('HTTP 401: This url need a valid token', 401);
}
if (!in_array('anis_admin', $token->getClaim('realm_access')->roles)) {
return (new NyholmResponse())->withStatus(403);
if (!in_array($this->settings['admin_role'], $token->getClaim('realm_access')->roles)) {
return $this->getResponse('HTTP 403: This url need a higher level of permission', 403);
}
return $handler->handle($request);
}
private function getResponse(string $message, int $code)
{
$resonse = new NyholmResponse();
$resonse->getBody()->write(json_encode(array(
'message' => $message
)));
return $resonse->withStatus($code);
}
}
......@@ -15,6 +15,7 @@ namespace App\Middleware;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Exception\HttpUnauthorizedException;
use Nyholm\Psr7\Response as NyholmResponse;
use Psr\Http\Server\MiddlewareInterface;
use Lcobucci\JWT\Parser;
......@@ -58,7 +59,11 @@ final class AuthorizationMiddleware implements MiddlewareInterface
*/
public function process(Request $request, RequestHandler $handler): Response
{
if ($request->getMethod() === OPTIONS || !$request->hasHeader('Authorization')) {
if (
$request->getMethod() === OPTIONS
|| !$request->hasHeader('Authorization')
|| $this->settings['enabled'] === 0
) {
return $handler->handle($request);
}
......@@ -66,7 +71,9 @@ final class AuthorizationMiddleware implements MiddlewareInterface
$bearer = $request->getHeader('Authorization');
$data = explode(' ', $bearer[0]);
if ($data[0] !== 'Bearer') {
return (new NyholmResponse())->withStatus(401);
return $this->getUnauthorizedResponse(
'HTTP 401: Authorization must contain a string with the following format -> Bearer JWT'
);
}
// Parse the JWT Token
......@@ -74,18 +81,38 @@ final class AuthorizationMiddleware implements MiddlewareInterface
// Validating token (verifying expiration date and issuer)
$data = new ValidationData();
// TODO: Ajouter une config pour vérifier ou non le issuer
// $data->setIssuer($this->settings['issuer']);
if (!$token->validate($data)) {
return (new NyholmResponse())->withStatus(401);
return $this->getUnauthorizedResponse('HTTP 401: Access Token is not valid or has expired');
}
// Test token signature with the public key
$publicKey = new Key('file://' . $this->settings['public_key_file']);
if (!$token->verify(new Sha256(), $publicKey)) {
return (new NyholmResponse())->withStatus(401);
return $this->getUnauthorizedResponse('HTTP 401: Access Token signature is not valid');
}
return $handler->handle($request->withAttribute('token', $token));
}
// private function getPublicKey(string $issuer, string $kid): string
// {
// $urlOpenIdConfiguration = $issuer . '/.well-known/openid-configuration';
// $openIdConfiguration = json_decode(file_get_contents($urlOpenIdConfiguration), true);
// $jwksUri = $openIdConfiguration['jwks_uri'];
// $jwks = json_decode(file_get_contents($jwksUri), true);
// foreach ($jwks['keys'] as $jwk) {
// if ($jwk['kid'] === $kid) {
// return $jwk['x5c'];
// }
// }
// }
private function getUnauthorizedResponse(string $message)
{
$resonse = new NyholmResponse();
$resonse->getBody()->write(json_encode(array(
'message' => $message
)));
return $resonse->withStatus(401);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment