passbolt/passbolt_api · error · InternalErrorException
Invalid response. Missing JWKS URI
Error message
Invalid response. Missing JWKS URI
What it means
After confirming the discovery document is an array, validateOpenIdConfiguration() checks required OIDC metadata fields. A decoded JSON without a jwks_uri key means the provider did not advertise its JSON Web Key Set endpoint, which passbolt needs to verify ID token signatures, so it throws this InternalErrorException.
Solutions
- Curl the discovery URL and confirm jwks_uri is present in the JSON.
- Ensure the selected SSO provider is actually an OpenID Connect provider (OAuth2-only providers lack jwks_uri).
- Point passbolt at a compliant OIDC issuer for the same IdP.
- If the IdP genuinely omits jwks_uri, switch to a flow/algorithm setup not requiring JWKS or contact the IdP vendor.
Example fix
// before (OAuth2-only endpoint without JWKS) 'issuer' => 'https://oauth.example.com', // after (OIDC-compliant issuer) 'issuer' => 'https://auth.example.com/oidc',
Defensive patterns
Strategy: validation
Validate before calling
$doc = json_decode(file_get_contents($wellKnownUrl), true);
if (!isset($doc['jwks_uri'])) { throw new UnexpectedValueException('Provider is not OIDC-compliant: jwks_uri missing from discovery document.'); } Type guard
function hasJwksUri(mixed $doc): bool { return is_array($doc) && isset($doc['jwks_uri']) && is_string($doc['jwks_uri']); } Try / catch
try { $keys = $provider->getJwtVerificationKeys(); } catch (InternalErrorException $e) { if ($e->getMessage() === 'Invalid response. Missing JWKS URI') { /* IdP is OAuth2-only or metadata incomplete */ } throw $e; } Prevention
- Select an OpenID Connect provider, not a bare OAuth2 server
- Verify jwks_uri is present in the discovery JSON before configuring SSO
- Beware of caches/proxies truncating the metadata document
- Check for IdP version changes that alter published metadata
When it happens
Trigger: The IdP's .well-known/openid-configuration JSON decodes to an array but lacks the jwks_uri field; discovered during getJwtVerificationKeys via getOpenIdConfiguration.
Common situations: Provider is OAuth2-only (not OIDC) so it publishes no JWKS; partial/non-compliant discovery document; a proxy returning a trimmed/custom JSON body; wrong provider type selected in passbolt SSO settings.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Invalid response. Invalid authorization endpoint.
- Invalid response. Invalid JWKS URI
- Invalid response. Invalid token endpoint.
- Invalid response. Missing authorization endpoint.
- Invalid response. Missing token endpoint.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/9f3ce563100d3200.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php:175
* Check the endpoints info we expect to use later are present
*
* @param mixed $response from .well-known
* @return void
*/
public function validateOpenIdConfiguration(mixed $response): void
{
if (!is_array($response)) {
$msg = sprintf('Invalid response. Expected array, got "%s".', gettype($response));
if (is_string($response)) {
// Cap excerpt to limit log volume on large/HTML responses; mb_strcut is UTF-8-safe.
$excerpt = mb_strcut($response, 0, 200, 'UTF-8');
// Escape newlines and control characters via JSON encoding so they don't corrupt log output.
$msg .= ' ' . sprintf('Response text (truncated): %s', json_encode($excerpt));
}
throw new InternalErrorException($msg);
}
if (!isset($response['jwks_uri'])) {
throw new InternalErrorException('Invalid response. Missing JWKS URI');
}
if (!isset($response['authorization_endpoint'])) {
throw new InternalErrorException('Invalid response. Missing authorization endpoint.');
}
if (!isset($response['token_endpoint'])) {
throw new InternalErrorException('Invalid response. Missing token endpoint.');
}
if (!Validation::url($response['jwks_uri'])) {
throw new InternalErrorException('Invalid response. Invalid JWKS URI');
}
if (!Validation::url($response['authorization_endpoint'])) {
throw new InternalErrorException('Invalid response. Invalid authorization endpoint.');
}
if (!Validation::url($response['token_endpoint'])) {
throw new InternalErrorException('Invalid response. Invalid token endpoint.');
}
}
View on GitHub (pinned to 31c1bbc10f)