diff --git a/README.md b/README.md
index e4152cb..a12e7a4 100644
--- a/README.md
+++ b/README.md
@@ -127,17 +127,26 @@ $app->add(new Tuupola\Middleware\JwtAuthentication([
### Algorithm
-You can set supported algorithms via `algorithm` parameter. This can be either string or array of strings. Default value is `["HS256", "HS512", "HS384"]`. Supported algorithms are `HS256`, `HS384`, `HS512` and `RS256`. Note that enabling both `HS256` and `RS256` is a [security risk](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/).
+You can set supported algorithms via `algorithm` parameter. This can be either string or array of strings. Default value is `["HS256"]`. Supported algorithms are `HS256`, `HS384`, `HS512` and `RS256`. Note that enabling both `HS256` and `RS256` is a [security risk](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/).
+
+When passing multiple algorithm it be a key value array, with the key being the `KID` of the jwt.
``` php
$app = new Slim\App;
$app->add(new Tuupola\Middleware\JwtAuthentication([
"secret" => "supersecretkeyyoushouldnotcommittogithub",
- "algorithm" => ["HS256", "HS384"]
+ "algorithm" => [
+ "amce" => "HS256",
+ "beta" => "HS384"
+ ]
]));
```
+> :warning: **Warning**:
+Because of changes in `firebase/php-jwt` the `kid` is now checked when multiple algorithm are passed, failing to provide a key the algorithm will be used for the kid.
+this also means the `kid` will now need to be present in the JWT header as well.
+
### Attribute
When the token is decoded successfully and authentication succeeds the contents of the decoded token is saved as `token` attribute to the `$request` object. You can change this with. `attribute` parameter. Set to `null` or `false` to disable this behavour
diff --git a/src/JwtAuthentication.php b/src/JwtAuthentication.php
index 444ddcb..0faab67 100644
--- a/src/JwtAuthentication.php
+++ b/src/JwtAuthentication.php
@@ -79,7 +79,7 @@ final class JwtAuthentication implements MiddlewareInterface
* Stores all the options passed to the middleware.
*
* @var array{
- * secret?: string|array,
+ * secret?: string|array|array,
* secure: bool,
* relaxed: array,
* algorithm: array,
@@ -321,7 +321,8 @@ private function decodeToken(string $token): array
try {
$decoded = JWT::decode(
$token,
- $keys
+ $keys,
+ $this->options['algorithm']
);
return (array) $decoded;
} catch (Exception $exception) {
diff --git a/tests/JwtAuthenticationTest.php b/tests/JwtAuthenticationTest.php
index 3e0e925..9f232f6 100644
--- a/tests/JwtAuthenticationTest.php
+++ b/tests/JwtAuthenticationTest.php
@@ -220,6 +220,33 @@ public function testShouldReturn200WithSecretArray(): void
$this->assertEquals("Success", $response->getBody());
}
+ public function testShouldReturn200WithSecretArrayCheckKid(): void
+ {
+ $request = (new ServerRequestFactory)
+ ->createServerRequest("GET", "https://example.com/api")
+ ->withHeader("Authorization", "Bearer " . self::$betaToken);
+
+ $default = function (ServerRequestInterface $request) {
+ $response = (new ResponseFactory)->createResponse();
+ $response->getBody()->write("Success");
+ return $response;
+ };
+
+ $collection = new MiddlewareCollection([
+ new JwtAuthentication([
+ "algorithm" => ["acme" => "HS256", "beta" => "HS256"],
+ "secret" => [
+ "acme" =>"supersecretkeyyoushouldnotcommittogithub",
+ "beta" =>"anothersecretkeyfornevertocommittogithub"
+ ],
+ ])
+ ]);
+
+ $response = $collection->dispatch($request, $default);
+ $this->assertEquals(200, $response->getStatusCode());
+ $this->assertEquals("Success", $response->getBody());
+ }
+
public function testShouldReturn401WithSecretArray(): void
{
$request = (new ServerRequestFactory)