]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
API: expect JWT in the Authorization header
authorVirtualTam <virtualtam@flibidi.net>
Sat, 7 Jan 2017 21:23:47 +0000 (22:23 +0100)
committerVirtualTam <virtualtam+github@flibidi.net>
Sun, 15 Jan 2017 12:41:04 +0000 (13:41 +0100)
Relates to https://github.com/shaarli/Shaarli/pull/731

Added:
- require the presence of the 'Authorization' header

Changed:
- use the HTTP Bearer Token authorization schema

See:
- https://jwt.io/introduction/#how-do-json-web-tokens-work-
- https://tools.ietf.org/html/rfc6750
- http://security.stackexchange.com/q/108662

Signed-off-by: VirtualTam <virtualtam@flibidi.net>
application/api/ApiMiddleware.php
tests/api/ApiMiddlewareTest.php

index 162e88e0bc06ea50a43e6cc1cc289212962b1edf..522091cac39328222d790b441f29195e2d64fe78 100644 (file)
@@ -98,8 +98,7 @@ class ApiMiddleware
      * @throws ApiAuthorizationException The token couldn't be validated.
      */
     protected function checkToken($request) {
-        $jwt = $request->getHeaderLine('jwt');
-        if (empty($jwt)) {
+        if (! $request->hasHeader('Authorization')) {
             throw new ApiAuthorizationException('JWT token not provided');
         }
 
@@ -107,7 +106,13 @@ class ApiMiddleware
             throw new ApiAuthorizationException('Token secret must be set in Shaarli\'s administration');
         }
 
-        ApiUtils::validateJwtToken($jwt, $this->conf->get('api.secret'));
+        $authorization = $request->getHeaderLine('Authorization');
+
+        if (! preg_match('/^Bearer (.*)/i', $authorization, $matches)) {
+            throw new ApiAuthorizationException('Invalid JWT header');
+        }
+
+        ApiUtils::validateJwtToken($matches[1], $this->conf->get('api.secret'));
     }
 
     /**
index 4d4dd9b979c8180b3ffd05c816ba4e6c1600287e..d9753b1d6bdafc6b92aa8771e3e748ae7e605d66 100644 (file)
@@ -143,7 +143,7 @@ class ApiMiddlewareTest extends \PHPUnit_Framework_TestCase
         $env = Environment::mock([
             'REQUEST_METHOD' => 'GET',
             'REQUEST_URI' => '/echo',
-            'HTTP_JWT'=> 'jwt',
+            'HTTP_AUTHORIZATION'=> 'Bearer jwt',
         ]);
         $request = Request::createFromEnvironment($env);
         $response = new Response();
@@ -157,7 +157,30 @@ class ApiMiddlewareTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * Invoke the middleware without an invalid JWT token (debug):
+     * Invoke the middleware with an invalid JWT token header
+     */
+    public function testInvalidJwtAuthHeaderDebug()
+    {
+        $this->conf->set('dev.debug', true);
+        $mw = new ApiMiddleware($this->container);
+        $env = Environment::mock([
+            'REQUEST_METHOD' => 'GET',
+            'REQUEST_URI' => '/echo',
+            'HTTP_AUTHORIZATION'=> 'PolarBearer jwt',
+        ]);
+        $request = Request::createFromEnvironment($env);
+        $response = new Response();
+        /** @var Response $response */
+        $response = $mw($request, $response, null);
+
+        $this->assertEquals(401, $response->getStatusCode());
+        $body = json_decode((string) $response->getBody());
+        $this->assertEquals('Not authorized: Invalid JWT header', $body->message);
+        $this->assertContains('ApiAuthorizationException', $body->stacktrace);
+    }
+
+    /**
+     * Invoke the middleware with an invalid JWT token (debug):
      * should return a 401 error Unauthorized - with a specific message and a stacktrace.
      *
      * Note: specific JWT errors tests are handled in ApiUtilsTest.
@@ -169,7 +192,7 @@ class ApiMiddlewareTest extends \PHPUnit_Framework_TestCase
         $env = Environment::mock([
             'REQUEST_METHOD' => 'GET',
             'REQUEST_URI' => '/echo',
-            'HTTP_JWT'=> 'bad jwt',
+            'HTTP_AUTHORIZATION'=> 'Bearer jwt',
         ]);
         $request = Request::createFromEnvironment($env);
         $response = new Response();