{"record":{"id":"9f3ce563100d3200","repo":"passbolt/passbolt_api","slug":"invalid-response-missing-jwks-uri","errorCode":null,"errorMessage":"Invalid response. Missing JWKS URI","messagePattern":"Invalid response\\. Missing JWKS URI","errorType":"exception","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php","lineNumber":175,"sourceCode":"     * Check the endpoints info we expect to use later are present\n     *\n     * @param mixed $response from .well-known\n     * @return void\n     */\n    public function validateOpenIdConfiguration(mixed $response): void\n    {\n        if (!is_array($response)) {\n            $msg = sprintf('Invalid response. Expected array, got \"%s\".', gettype($response));\n            if (is_string($response)) {\n                // Cap excerpt to limit log volume on large/HTML responses; mb_strcut is UTF-8-safe.\n                $excerpt = mb_strcut($response, 0, 200, 'UTF-8');\n                // Escape newlines and control characters via JSON encoding so they don't corrupt log output.\n                $msg .= ' ' . sprintf('Response text (truncated): %s', json_encode($excerpt));\n            }\n            throw new InternalErrorException($msg);\n        }\n        if (!isset($response['jwks_uri'])) {\n            throw new InternalErrorException('Invalid response. Missing JWKS URI');\n        }\n        if (!isset($response['authorization_endpoint'])) {\n            throw new InternalErrorException('Invalid response. Missing authorization endpoint.');\n        }\n        if (!isset($response['token_endpoint'])) {\n            throw new InternalErrorException('Invalid response. Missing token endpoint.');\n        }\n        if (!Validation::url($response['jwks_uri'])) {\n            throw new InternalErrorException('Invalid response. Invalid JWKS URI');\n        }\n        if (!Validation::url($response['authorization_endpoint'])) {\n            throw new InternalErrorException('Invalid response. Invalid authorization endpoint.');\n        }\n        if (!Validation::url($response['token_endpoint'])) {\n            throw new InternalErrorException('Invalid response. Invalid token endpoint.');\n        }\n    }\n","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php#L157-L193","documentation":"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.","triggerScenarios":"The IdP's .well-known/openid-configuration JSON decodes to an array but lacks the jwks_uri field; discovered during getJwtVerificationKeys via getOpenIdConfiguration.","commonSituations":"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.","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."],"exampleFix":"// before (OAuth2-only endpoint without JWKS)\n'issuer' => 'https://oauth.example.com',\n// after (OIDC-compliant issuer)\n'issuer' => 'https://auth.example.com/oidc',","handlingStrategy":"validation","validationCode":"$doc = json_decode(file_get_contents($wellKnownUrl), true);\nif (!isset($doc['jwks_uri'])) { throw new UnexpectedValueException('Provider is not OIDC-compliant: jwks_uri missing from discovery document.'); }","typeGuard":"function hasJwksUri(mixed $doc): bool { return is_array($doc) && isset($doc['jwks_uri']) && is_string($doc['jwks_uri']); }","tryCatchPattern":"try { $keys = $provider->getJwtVerificationKeys(); } catch (InternalErrorException $e) { if ($e->getMessage() === 'Invalid response. Missing JWKS URI') { /* IdP is OAuth2-only or metadata incomplete */ } throw $e; }","preventionTips":["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"],"tags":["openid-configuration","jwks","oidc","response-validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}