BookStackApp/BookStack · error · OidcIssuerDiscoveryException
Error reading keys from issuer jwks_uri
Error message
Error reading keys from issuer jwks_uri
What it means
loadKeysFromUri() fetches the JWKS from the IdP's jwks_uri and throws OidcIssuerDiscoveryException if the body is empty, invalid JSON, or lacks a 'keys' array. Without signing keys, incoming ID tokens cannot be verified, so the library refuses to continue.
Source
Thrown at app/Access/Oidc/OidcProviderSettings.php:181
return $key['kty'] === 'RSA' && $use === 'sig' && $alg === 'RS256';
});
}
/**
* Return an array of jwks as PHP key=>value arrays.
*
* @throws ClientExceptionInterface
* @throws OidcIssuerDiscoveryException
*/
protected function loadKeysFromUri(string $uri, ClientInterface $httpClient): array
{
$request = new Request('GET', $uri);
$response = $httpClient->sendRequest($request);
$result = json_decode($response->getBody()->getContents(), true);
if (empty($result) || !is_array($result) || !isset($result['keys'])) {
throw new OidcIssuerDiscoveryException('Error reading keys from issuer jwks_uri');
}
return $result['keys'];
}
/**
* Get the settings needed by an OAuth provider, as a key=>value array.
*/
public function arrayForOAuthProvider(): array
{
$settingKeys = ['clientId', 'clientSecret', 'authorizationEndpoint', 'tokenEndpoint', 'userinfoEndpoint'];
$settings = [];
foreach ($settingKeys as $setting) {
$settings[$setting] = $this->$setting;
}
return $settings;
}View on GitHub (pinned to 18f8469a1c)
Solutions
- curl the jwks_uri from the BookStack host and confirm it returns {"keys":[...]}.
- Fix DNS/firewall/proxy so the JWKS host is reachable from the BookStack container.
- Clear the discovery cache ('oidc-discovery::<issuer>') after restoring access, since a cached discovery doc holds the jwks_uri.
- Check IdP health/logs; rotate to a known-good realm if keys were removed from the JWKS.
Defensive patterns
Strategy: try-catch
Validate before calling
$jwksUri = json_decode(file_get_contents($discoveryUrl), true)['jwks_uri'] ?? null;
$jwks = json_decode(@file_get_contents($jwksUri) ?? '', true);
if (!is_array($jwks) || !isset($jwks['keys'])) {
throw new RuntimeException('JWKS endpoint did not return a keys array');
} Type guard
function isValidJwks(?array $decoded): bool {
return is_array($decoded) && isset($decoded['keys']) && is_array($decoded['keys']) && $decoded['keys'] !== [];
} Try / catch
try {
$settings->discoverFromIssuer($client, $cache, 15);
} catch (OidcIssuerDiscoveryException $e) {
if (str_contains($e->getMessage(), 'jwks_uri')) {
Log::error('JWKS fetch failed: check jwks_uri reachability from app host');
}
} Prevention
- Ensure the jwks_uri host is resolvable and reachable from the BookStack container.
- Verify with curl that the JWKS URL returns {"keys":[...]} before enabling OIDC.
- Purge cached discovery data after JWKS endpoint changes.
- Monitor IdP health; JWKS outages break token validation on every login.
When it happens
Trigger: GET jwks_uri returns non-JSON (HTML error page, empty 200), a proxy/WAF interstitial, or a document without the 'keys' member; also raised if the JWKS endpoint errors with a body that still parses as empty/non-array.
Common situations: JWKS URL unreachable through internal DNS while the main discovery doc is cached and reachable; IdP returning 5xx HTML pages; jwks_uri pointing to an internal hostname BookStack can't resolve; intermediate proxy stripping/altering the response.
Related errors
- HTTP request failed during discovery with error: {$exception
- Error discovering provider settings from issuer at URL {$iss
- OIDC Discovery Error:
- Unexpected issuer value found on discovery response
- errors.ldap_cannot_connect
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/b7c3b948e25c23dd.
Report an issue: GitHub.