{"record":{"id":"5a23ae14816a1fee","repo":"passbolt/passbolt_api","slug":"invalid-response-invalid-token-endpoint","errorCode":null,"errorMessage":"Invalid response. Invalid token endpoint.","messagePattern":"Invalid response\\. Invalid token endpoint\\.","errorType":"exception","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php","lineNumber":190,"sourceCode":"            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     */\n    protected function getAuthorizationParameters(array $options)\n    {\n        $options = parent::getAuthorizationParameters($options);\n\n        /**\n         * The \"approval_prompt\" MUST be removed as it is not supported by Google, use \"prompt\" instead:\n         *\n         * @link https://developers.google.com/identity/protocols/oauth2/openid-connect#prompt\n         */\n        unset($options['approval_prompt']);\n\n        return $options;","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php#L172-L208","documentation":"validateOpenIdConfiguration() checks token_endpoint with Validation::url(). If present but not a valid absolute URL, the token exchange endpoint is unusable and an InternalErrorException 'Invalid response. Invalid token endpoint.' is thrown. This is the final check in the discovery validation chain.","triggerScenarios":"Decoded discovery JSON contains token_endpoint whose value fails Validation::url() during the token-exchange setup via getBaseAccessTokenUrl.","commonSituations":"IdP publishing relative or malformed token endpoint URLs; proxy rewriting the metadata; self-hosted IdP with a misconfigured external base URL.","solutions":["Inspect the discovery JSON; token_endpoint must be an absolute http(s) URL.","Correct the IdP's base URL / endpoint configuration and republish metadata.","Fix proxy/rewrite rules altering endpoint URLs.","Retest SSO; the error disappears once the token endpoint validates."],"exampleFix":"// before\n'{\"token_endpoint\":\"//auth.example.com/token\"}'\n// after\n'{\"token_endpoint\":\"https://auth.example.com/token\"}'","handlingStrategy":"validation","validationCode":"use Cake\\Validation\\Validation;\n$doc = json_decode(file_get_contents($wellKnownUrl), true);\nif (!isset($doc['token_endpoint']) || !Validation::url($doc['token_endpoint'])) { throw new UnexpectedValueException('token_endpoint missing or not a valid absolute URL.'); }","typeGuard":"function isValidTokenEndpoint(mixed $doc): bool { return is_array($doc) && isset($doc['token_endpoint']) && is_string($doc['token_endpoint']) && Validation::url($doc['token_endpoint']); }","tryCatchPattern":"try { $tokenUrl = $provider->getBaseAccessTokenUrl(); } catch (InternalErrorException $e) { if (str_contains($e->getMessage(), 'Invalid token endpoint')) { /* metadata emits malformed token_endpoint */ } throw $e; }","preventionTips":["Set the IdP external base URL correctly so token_endpoint is absolute","Re-check discovery metadata after network/proxy changes","Validate all three endpoints (jwks_uri, authorization_endpoint, token_endpoint) during setup","Log the discovery document on validation failure for quick diagnosis"],"tags":["openid-configuration","url-validation","oidc","response-validation"],"backgroundTag":"invalid-url-format","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"}