{"record":{"id":"210b669f5f0a3b0d","repo":"BookStackApp/BookStack","slug":"failed-to-load-key-from-jwk-parameters-with-error","errorCode":null,"errorMessage":"Failed to load key from JWK parameters with error: {$exception->getMessage()}","messagePattern":"Failed to load key from JWK parameters with error: (.+?)","errorType":"exception","errorClass":"OidcInvalidKeyException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcJwtSigningKey.php","lineNumber":88,"sourceCode":"        }\n\n        if (empty($jwk['e'])) {\n            throw new OidcInvalidKeyException('An \"e\" parameter on the provided key is expected');\n        }\n\n        if (empty($jwk['n'])) {\n            throw new OidcInvalidKeyException('A \"n\" parameter on the provided key is expected');\n        }\n\n        $n = strtr($jwk['n'], '-_', '+/');\n\n        try {\n            $key = PublicKeyLoader::load([\n                'e' => new BigInteger(base64_decode($jwk['e']), 256),\n                'n' => new BigInteger(base64_decode($n), 256),\n            ]);\n        } catch (\\Exception $exception) {\n            throw new OidcInvalidKeyException(\"Failed to load key from JWK parameters with error: {$exception->getMessage()}\");\n        }\n\n        if (!$key instanceof RSA) {\n            throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');\n        }\n\n        $this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);\n    }\n\n    /**\n     * Use this key to sign the given content and return the signature.\n     */\n    public function verify(string $content, string $signature): bool\n    {\n        return $this->key->verify($content, $signature);\n    }\n\n    /**","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcJwtSigningKey.php#L70-L106","documentation":"OidcJwtSigningKey::loadFromJwkArray builds an RSA public key from the JWK's 'e' and 'n' parameters via phpseclib's PublicKeyLoader. If phpseclib cannot construct a key from those parameters, it throws an OidcInvalidKeyException wrapping the underlying phpseclib message. This guards against malformed or unsupported JWK data rather than failing silently.","triggerScenarios":"Constructing OidcJwtSigningKey with a JWK array whose 'e' or 'n' is missing, empty, not valid base64, or does not decode into mathematically valid RSA modulus/exponent values.","commonSituations":"OIDC discovery/ JWKS endpoint returning truncated or corrupted keys; hand-copied JWK values; base64url vs standard base64 confusion; identity provider rotating keys and cache serving incomplete JWKS entries.","solutions":["Inspect the wrapped phpseclib message for the exact parameter failure","Verify the JWK contains non-empty 'e' and 'n' values and that they are valid base64url strings","Re-fetch the JWKS from the issuer's /.well-known/jwks.json or jwks_uri and clear any stale cached keys","Confirm the 'kty' of the JWK is RSA before passing it to OidcJwtSigningKey"],"exampleFix":"// before\n$key = new OidcJwtSigningKey($jwk); // $jwk missing 'n'\n\n// after\nif (empty($jwk['n']) || empty($jwk['e'])) {\n    throw new \\InvalidArgumentException('JWK is missing n/e parameters');\n}\n$key = new OidcJwtSigningKey($jwk);","handlingStrategy":"try-catch","validationCode":"function isValidRsaJwk(array $jwk): bool {\n    return ($jwk['kty'] ?? '') === 'RSA'\n        && !empty($jwk['n']) && !empty($jwk['e'])\n        && base64_decode($jwk['n'], true) !== false\n        && base64_decode($jwk['e'], true) !== false;\n}","typeGuard":"function isRsaKey($key): bool { return $key instanceof \\phpseclib3\\Crypt\\RSA; }","tryCatchPattern":"try {\n    $key = new \\BookStack\\Access\\Oidc\\OidcJwtSigningKey($jwk);\n} catch (\\BookStack\\Access\\Oidc\\OidcInvalidKeyException $e) {\n    logger()->warning('Invalid OIDC JWK: ' . $e->getMessage());\n    // skip key / refetch JWKS\n}","preventionTips":["Validate kty/e/n presence and base64url decodability before constructing the key","Refetch JWKS on key failure instead of relying on stale caches","Log the wrapped phpseclib message to diagnose parameter issues quickly"],"tags":["php","oidc","jwk","rsa","key-loading"],"backgroundTag":"invalid-jwk-key","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}