{"record":{"id":"30cf21b1c6000cfc","repo":"passbolt/passbolt_api","slug":"ajax-json-request-not-supported-30cf21","errorCode":null,"errorMessage":"Ajax/Json request not supported.","messagePattern":"Ajax/Json request not supported\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/SsoRecover/src/Controller/PingOne/PingOneRecoverSuccessController.php","lineNumber":45,"sourceCode":"\nclass PingOneRecoverSuccessController extends AbstractSsoController\n{\n    /**\n     * @inheritDoc\n     */\n    public function beforeFilter(EventInterface $event)\n    {\n        parent::beforeFilter($event);\n        $this->Authentication->allowUnauthenticated(['ssoRecoverSuccess']);\n    }\n\n    /**\n     * @return void\n     */\n    public function ssoRecoverSuccess(): void\n    {\n        if ($this->request->is('json')) {\n            throw new BadRequestException(__('Ajax/Json request not supported.'));\n        }\n\n        $this->User->assertNotLoggedIn();\n        $token = $this->getTokenFromUrlQuery();\n\n        try {\n            (new SsoAuthenticationTokenGetService())->getActiveNotExpiredOrFail($token, SsoState::TYPE_SSO_RECOVER);\n        } catch (RecordNotFoundException $e) {\n            throw new BadRequestException(\n                __('The authentication token does not exist or has been deleted.'),\n                null,\n                $e\n            );\n        } catch (CustomValidationException $e) {\n            throw new BadRequestException(\n                __('The authentication token has been expired.'),\n                null,\n                $e","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/SsoRecover/src/Controller/PingOne/PingOneRecoverSuccessController.php#L27-L63","documentation":"Thrown by PingOneRecoverSuccessController::ssoRecoverSuccess when the incoming request has the JSON/Ajax content type. This endpoint is a browser redirect target from the SSO provider and must render an HTML page, so JSON requests are explicitly rejected with a 400.","triggerScenarios":"Calling the success endpoint with Accept/Content-Type indicating JSON (e.g. fetch/XHR, curl with Accept: application/json, or passbolt JS API style request headers) instead of a normal browser navigation.","commonSituations":"Developer tests the provider callback URL with curl or Postman using JSON headers; frontend code incorrectly routes the callback through XHR; browser extension or proxy alters Accept headers.","solutions":["Open the callback URL via normal browser navigation (full page redirect), not fetch/XHR","Remove JSON Accept/Content-Type headers when testing with curl/Postman","Ensure the SSO provider is configured to redirect the browser directly to this endpoint","Use the JSON SSO endpoints (e.g. RecoverStartController) for programmatic flows instead"],"exampleFix":"// before\ncurl -H 'Accept: application/json' https://host/sso/recover/success/pingone?token=...\n// after\ncurl -H 'Accept: text/html' https://host/sso/recover/success/pingone?token=...  # or open in browser","handlingStrategy":"validation","validationCode":"const isJsonRequest = (init) =>\n  (init?.headers?.Accept || '').includes('application/json') ||\n  (init?.headers?.['Content-Type'] || '').includes('application/json');\nif (isJsonRequest(myInit)) throw new Error('Callback must be a browser navigation, not JSON.');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call redirect-target endpoints via fetch/XHR","Configure the SSO provider to redirect the browser directly","Exclude SSO callback URLs from JSON-forcing middleware","Test callbacks with a real browser, not curl with JSON headers"],"tags":["sso","http","content-negotiation","json"],"backgroundTag":"operation-not-supported","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"}