{"record":{"id":"831683d469d188b8","repo":"passbolt/passbolt_api","slug":"this-functionality-is-not-available-using-ajax-json","errorCode":null,"errorMessage":"This functionality is not available using AJAX/JSON.","messagePattern":"This functionality is not available using AJAX/JSON\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Controller/MfaController.php","lineNumber":83,"sourceCode":"     * Clear any dubious cookie if mfa check is required\n     *\n     * @return void\n     */\n    protected function _invalidateMfaCookie(): void\n    {\n        (new ClearMfaCookieInResponseService($this))->clearMfaCookie();\n    }\n\n    /**\n     * Assert the request is not of json type.\n     *\n     * @return void\n     * @throw BadRequestException if the request is of json type.\n     */\n    protected function _assertRequestNotJson(): void\n    {\n        if ($this->getRequest()->is('json')) {\n            throw new BadRequestException(__('This functionality is not available using AJAX/JSON.'));\n        }\n    }\n\n    /**\n     * Assert the request is of json type.\n     *\n     * @return void\n     * @throw BadRequestException if the request is not of json type.\n     */\n    protected function _assertRequestIsJson(): void\n    {\n        if (!$this->getRequest()->is('json')) {\n            throw new BadRequestException(__('This functionality is only available using AJAX/JSON.'));\n        }\n    }\n}\n","sourceCodeStart":65,"sourceCodeEnd":100,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Controller/MfaController.php#L65-L100","documentation":"Certain MFA flows (browser redirects to providers, Duo callbacks) cannot be consumed by AJAX/JSON clients because they return full HTML redirects. _assertRequestNotJson rejects JSON-type requests with a BadRequestException before any MFA logic runs.","triggerScenarios":"Requesting a non-JSON MFA endpoint (e.g. MFA verify GET/POST or Duo callback) with the .json extension or an Accept/Content-Type that marks the request as JSON.","commonSituations":"Calling the browser-oriented MFA verify page from a script or API client; frontend sending JSON headers to an endpoint designed for full-page redirects.","solutions":["Remove the .json extension and JSON headers from the request","Use the JSON-specific endpoints guarded by _assertRequestIsJson instead","Perform this flow in a browser context rather than via AJAX"],"exampleFix":"// before\nawait fetch('/mfa/verify/totp.json');\n// after (non-json browser flow)\nwindow.location.href = '/mfa/verify/totp';","handlingStrategy":"type-guard","validationCode":"const isJsonRequest = url.endsWith('.json') || headers.Accept?.includes('application/json');\nif (isJsonRequest) throw new Error('Use non-JSON browser flow for this endpoint');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Separate browser-flow and JSON API endpoints in client code","Never send JSON headers to redirect-based MFA endpoints","Document per-endpoint request format requirements"],"tags":["mfa","http-400","ajax","request-format"],"backgroundTag":"invalid-argument-value","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}