]> BookStack Code Mirror - bookstack/blobdiff - app/Auth/Access/Oidc/OidcJwtSigningKey.php
Guest create page: name field autofocus
[bookstack] / app / Auth / Access / Oidc / OidcJwtSigningKey.php
index 3e77cf331732401afc902d06953275db5a60ca4f..f003ec93ca1c1df3f2c80ef9a3a940e2d90697fe 100644 (file)
@@ -18,15 +18,17 @@ class OidcJwtSigningKey
      * Can be created either from a JWK parameter array or local file path to load a certificate from.
      * Examples:
      * 'file:///var/www/cert.pem'
-     * ['kty' => 'RSA', 'alg' => 'RS256', 'n' => 'abc123...']
+     * ['kty' => 'RSA', 'alg' => 'RS256', 'n' => 'abc123...'].
+     *
      * @param array|string $jwkOrKeyPath
+     *
      * @throws OidcInvalidKeyException
      */
     public function __construct($jwkOrKeyPath)
     {
         if (is_array($jwkOrKeyPath)) {
             $this->loadFromJwkArray($jwkOrKeyPath);
-        } else if (is_string($jwkOrKeyPath) && strpos($jwkOrKeyPath, 'file://') === 0) {
+        } elseif (is_string($jwkOrKeyPath) && strpos($jwkOrKeyPath, 'file://') === 0) {
             $this->loadFromPath($jwkOrKeyPath);
         } else {
             throw new OidcInvalidKeyException('Unexpected type of key value provided');
@@ -39,16 +41,18 @@ class OidcJwtSigningKey
     protected function loadFromPath(string $path)
     {
         try {
-            $this->key = PublicKeyLoader::load(
+            $key = PublicKeyLoader::load(
                 file_get_contents($path)
-            )->withPadding(RSA::SIGNATURE_PKCS1);
+            );
         } catch (\Exception $exception) {
             throw new OidcInvalidKeyException("Failed to load key from file path with error: {$exception->getMessage()}");
         }
 
-        if (!($this->key instanceof RSA)) {
-            throw new OidcInvalidKeyException("Key loaded from file path is not an RSA key as expected");
+        if (!$key instanceof RSA) {
+            throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');
         }
+
+        $this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);
     }
 
     /**
@@ -56,15 +60,17 @@ class OidcJwtSigningKey
      */
     protected function loadFromJwkArray(array $jwk)
     {
-        if ($jwk['alg'] !== 'RS256') {
-            throw new OidcInvalidKeyException("Only RS256 keys are currently supported. Found key using {$jwk['alg']}");
-        }
-
-        if (empty($jwk['use'])) {
-            throw new OidcInvalidKeyException('A "use" parameter on the provided key is expected');
+        // 'alg' is optional for a JWK, but we will still attempt to validate if
+        // it exists otherwise presume it will be compatible.
+        $alg = $jwk['alg'] ?? null;
+        if ($jwk['kty'] !== 'RSA' || !(is_null($alg) || $alg === 'RS256')) {
+            throw new OidcInvalidKeyException("Only RS256 keys are currently supported. Found key using {$alg}");
         }
 
-        if ($jwk['use'] !== 'sig') {
+        // 'use' is optional for a JWK but we assume 'sig' where no value exists since that's what
+        // the OIDC discovery spec infers since 'sig' MUST be set if encryption keys come into play.
+        $use = $jwk['use'] ?? 'sig';
+        if ($use !== 'sig') {
             throw new OidcInvalidKeyException("Only signature keys are currently supported. Found key for use {$jwk['use']}");
         }
 
@@ -79,14 +85,19 @@ class OidcJwtSigningKey
         $n = strtr($jwk['n'] ?? '', '-_', '+/');
 
         try {
-            /** @var RSA $key */
-            $this->key = PublicKeyLoader::load([
+            $key = PublicKeyLoader::load([
                 'e' => new BigInteger(base64_decode($jwk['e']), 256),
                 'n' => new BigInteger(base64_decode($n), 256),
-            ])->withPadding(RSA::SIGNATURE_PKCS1);
+            ]);
         } catch (\Exception $exception) {
             throw new OidcInvalidKeyException("Failed to load key from JWK parameters with error: {$exception->getMessage()}");
         }
+
+        if (!$key instanceof RSA) {
+            throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');
+        }
+
+        $this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);
     }
 
     /**
@@ -104,5 +115,4 @@ class OidcJwtSigningKey
     {
         return $this->key->toString('PKCS8');
     }
-
-}
\ No newline at end of file
+}