{"record":{"id":"2a4853861f070b77","repo":"passbolt/passbolt_api","slug":"this-is-not-a-valid-ajax-json-request-2a4853","errorCode":null,"errorMessage":"This is not a valid Ajax/Json request.","messagePattern":"This is not a valid Ajax/Json request\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Controller/OrgSettings/MfaOrgSettingsPostController.php","lineNumber":41,"sourceCode":"use Passbolt\\MultiFactorAuthentication\\Utility\\MfaOrgSettingsDuoBackwardCompatible;\n\nclass MfaOrgSettingsPostController extends MfaController\n{\n    /**\n     * Handle Org Settings POST request\n     *\n     * @throws \\App\\Error\\Exception\\CustomValidationException if the user provided data do not validate\n     * @throws \\Cake\\Http\\Exception\\ForbiddenException if the user is not an admin\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the request is not made using Ajax/Json\n     * @param \\Duo\\DuoUniversal\\Client|null $duoSdkClient Duo SDK Client\n     * @return void\n     */\n    public function post(?Client $duoSdkClient = null): void\n    {\n        $this->User->assertIsAdmin();\n\n        if (!$this->request->is('json')) {\n            throw new BadRequestException(__('This is not a valid Ajax/Json request.'));\n        }\n\n        /** TODO: Remove this line and its class once the frontend has been updated to use the new format/names */\n        $data = MfaOrgSettingsDuoBackwardCompatible::remapSetDuoSettings((array)$this->getRequest()->getData());\n\n        $config = (new MfaOrgSettingsSetService())->setOrgSettings(\n            $data,\n            $this->User->getAccessControl(),\n            $duoSdkClient\n        );\n        $this->success(__('The multi factor authentication settings for the organization were updated.'), $config);\n    }\n}\n","sourceCodeStart":23,"sourceCodeEnd":55,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Controller/OrgSettings/MfaOrgSettingsPostController.php#L23-L55","documentation":"The MFA organization settings POST endpoint only accepts JSON (Ajax) requests. When the incoming request does not declare an Accept/Content-Type of JSON, CakePHP's `$this->request->is('json')` check fails and the controller throws a BadRequestException. It exists to prevent HTML form posts from silently being treated as API calls.","triggerScenarios":"POSTing to /mfa/policies/settings.json (or /mfa/policies/settings without .json) with Accept: text/html or missing Content-Type: application/json headers; submitting the MFA org-settings form via a plain HTML form post; a proxy or frontend client stripping the JSON Accept header.","commonSituations":"Calling the endpoint with curl without `-H 'Content-Type: application/json'`; older frontend code posting the legacy Duo settings format without the JSON content type; integration tests using `$this->post()` without `enableCsrfToken`/JSON headers.","solutions":["Send the request with `Content-Type: application/json` and `Accept: application/json` headers","Append `.json` to the URL so CakePHP routes it through the JSON extension","In tests, use `$this->postJson()` or set the request headers before dispatch"],"exampleFix":"// before\ncurl -X POST -d '{\"providers\":[\"totp\"]}' https://passbolt/mfa/policies/settings.json\n// after\ncurl -X POST -H 'Content-Type: application/json' -H 'X-CSRF-Token: <token>' \\\n  -d '{\"providers\":[\"totp\"]}' https://passbolt/mfa/policies/settings.json","handlingStrategy":"validation","validationCode":"const isJson = (opts) => (opts.headers['Content-Type'] || '').includes('application/json') && (opts.headers['Accept'] || '').includes('application/json');\nif (!isJson(requestOptions)) throw new Error('MFA org settings endpoint requires JSON headers');","typeGuard":"function isJsonRequest(headers) {\n  return typeof headers['Content-Type'] === 'string' && headers['Content-Type'].includes('application/json');\n}","tryCatchPattern":"null","preventionTips":["Always send Content-Type: application/json and Accept: application/json to passbolt API endpoints","Use the .json URL extension on API routes","In integration tests, use the JSON-aware test helpers"],"tags":["http","api","bad-request","json"],"backgroundTag":"invalid-argument-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"}