{"record":{"id":"7f793ee0a8e5fea1","repo":"BookStackApp/BookStack","slug":"only-rs256-keys-are-currently-supported-found-key","errorCode":null,"errorMessage":"Only RS256 keys are currently supported. Found key using {$alg}","messagePattern":"Only RS256 keys are currently supported\\. Found key using (.+?)","errorType":"exception","errorClass":"OidcInvalidKeyException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcJwtSigningKey.php","lineNumber":62,"sourceCode":"        }\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     * @throws OidcInvalidKeyException\n     */\n    protected function loadFromJwkArray(array $jwk): void\n    {\n        // 'alg' is optional for a JWK, but we will still attempt to validate if\n        // it exists otherwise presume it will be compatible.\n        $alg = $jwk['alg'] ?? null;\n        if ($jwk['kty'] !== 'RSA' || !(is_null($alg) || $alg === 'RS256')) {\n            throw new OidcInvalidKeyException(\"Only RS256 keys are currently supported. Found key using {$alg}\");\n        }\n\n        // 'use' is optional for a JWK but we assume 'sig' where no value exists since that's what\n        // the OIDC discovery spec infers since 'sig' MUST be set if encryption keys come into play.\n        $use = $jwk['use'] ?? 'sig';\n        if ($use !== 'sig') {\n            throw new OidcInvalidKeyException(\"Only signature keys are currently supported. Found key for use {$jwk['use']}\");\n        }\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'], '-_', '+/');","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcJwtSigningKey.php#L44-L80","documentation":"loadFromJwkArray validates that the JWK is an RSA signing key usable with RS256. It throws when kty is not 'RSA', or when an 'alg' is present and is anything other than 'RS256' (null alg is tolerated and presumed compatible).","triggerScenarios":"new OidcJwtSigningKey($jwkArray) where $jwkArray['kty'] !== 'RSA' (e.g. 'EC', 'OKP', 'oct') or $jwkArray['alg'] is 'ES256', 'RS384', 'RS512', etc.","commonSituations":"IdP configured for ES256/RS512 while the app only supports RS256; jwks_uri returns EC keys; picking the wrong key from a multi-key JWKS; missing 'kty' key in the JWK array.","solutions":["Select a JWK from the JWKS with kty=RSA (and alg RS256 or absent)","Reconfigure the IdP to sign with RS256","Filter discovery keys: only use entries where kty === 'RSA' and (alg is null or 'RS256')","If you control the JWK fixture for tests, add/set 'kty' => 'RSA'"],"exampleFix":"// before\n$jwk = $jwks['keys'][0]; // may be EC\n// after\n$jwk = current(array_filter($jwks['keys'], fn($k) => ($k['kty'] ?? null) === 'RSA' && in_array($k['alg'] ?? null, [null, 'RS256'], true)));","handlingStrategy":"validation","validationCode":"if (($jwk['kty'] ?? null) !== 'RSA' || !in_array($jwk['alg'] ?? null, [null, 'RS256'], true)) { throw new \\RuntimeException('JWK is not RS256/RSA'); }","typeGuard":"function isRs256Jwk(array $jwk): bool { return ($jwk['kty'] ?? null) === 'RSA' && in_array($jwk['alg'] ?? null, [null, 'RS256'], true); }","tryCatchPattern":"try { $key = new OidcJwtSigningKey($jwk); } catch (OidcInvalidKeyException $e) { if (str_contains($e->getMessage(), 'Only RS256')) { /* select another key or fix IdP alg */ } throw $e; }","preventionTips":["Filter jwks_uri keys by kty=RSA and alg RS256/absent before constructing","Confirm IdP signing algorithm is RS256 in discovery metadata (id_token_signing_alg_values_supported)","Match kid from the token header to the correct JWK instead of taking keys[0]"],"tags":["oidc","jwk","jwt","algorithm"],"backgroundTag":"unsupported-key-type","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}