{"record":{"id":"7473e2b72495edbc","repo":"passbolt/passbolt_api","slug":"invalid-response-missing-authorization-endpoint","errorCode":null,"errorMessage":"Invalid response. Missing authorization endpoint.","messagePattern":"Invalid response\\. Missing authorization endpoint\\.","errorType":"exception","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php","lineNumber":178,"sourceCode":"     * @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\n    /**\n     * @inheritDoc\n     */","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php#L160-L196","documentation":"validateOpenIdConfiguration() requires authorization_endpoint to be present in the OIDC discovery document, since passbolt builds the browser redirect URL from it (getBaseAuthorizationUrl). A discovery payload missing this key is incomplete/non-compliant, so an InternalErrorException is thrown.","triggerScenarios":"getBaseAuthorizationUrl calls getOpenIdConfiguration -> validateOpenIdConfiguration; the decoded JSON lacks the authorization_endpoint key.","commonSituations":"Non-compliant or truncated discovery document; IdP misconfigured behind a proxy that strips fields; wrong discovery URL returning a partial metadata document; IdP software version change removing the field.","solutions":["Curl the .well-known/openid-configuration URL and verify authorization_endpoint exists.","Correct the issuer/WellKnownURI in passbolt SSO settings.","Check for proxies/caches serving a stale or partial discovery document and clear them.","Upgrade or reconfigure the IdP so it publishes full OIDC discovery metadata."],"exampleFix":"// before (wrong discovery doc)\n'{\"issuer\":\"https://auth.example.com\"}'\n// after (full OIDC metadata)\n'{\"issuer\":\"https://auth.example.com\",\"authorization_endpoint\":\"https://auth.example.com/authorize\",...}'","handlingStrategy":"validation","validationCode":"$doc = json_decode(file_get_contents($wellKnownUrl), true);\nif (!isset($doc['authorization_endpoint'])) { throw new UnexpectedValueException('Discovery document missing authorization_endpoint.'); }","typeGuard":"function hasAuthorizationEndpoint(mixed $doc): bool { return is_array($doc) && isset($doc['authorization_endpoint']) && is_string($doc['authorization_endpoint']); }","tryCatchPattern":"try { $authUrl = $provider->getBaseAuthorizationUrl(); } catch (InternalErrorException $e) { if (str_contains($e->getMessage(), 'authorization endpoint')) { /* incomplete discovery metadata */ } throw $e; }","preventionTips":["Validate full OIDC discovery metadata during setup, not just the issuer","Purge caches serving partial metadata","Test the discovery URL after any IdP upgrade","Pin the expected metadata fields in an SSO health check"],"tags":["openid-configuration","oidc","response-validation"],"backgroundTag":"unexpected-response-shape","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"}