{"record":{"id":"c6f25c9930e4ebcd","repo":"passbolt/passbolt_api","slug":"only-administrators-are-allowed-to-create-update-mfa","errorCode":null,"errorMessage":"Only administrators are allowed to create/update MFA policies settings.","messagePattern":"Only administrators are allowed to create/update MFA policies settings\\.","errorType":"http","errorClass":"ForbiddenException","httpStatus":403,"severity":"error","filePath":"plugins/PassboltEe/MfaPolicies/src/Controller/MfaPoliciesSettingsSetController.php","lineNumber":37,"sourceCode":"\nuse App\\Controller\\AppController;\nuse App\\Error\\Exception\\FormValidationException;\nuse Cake\\Http\\Exception\\ForbiddenException;\nuse Passbolt\\MfaPolicies\\Form\\MfaPoliciesSettingsForm;\nuse Passbolt\\MfaPolicies\\Model\\Dto\\MfaPolicySettings;\nuse Passbolt\\MfaPolicies\\Service\\MfaPoliciesSetSettingsService;\n\nclass MfaPoliciesSettingsSetController extends AppController\n{\n    /**\n     * Create/update MFA policies settings.\n     *\n     * @return void\n     */\n    public function post()\n    {\n        if (!$this->User->isAdmin()) {\n            throw new ForbiddenException(\n                __('Only administrators are allowed to create/update MFA policies settings.')\n            );\n        }\n\n        $requestData = $this->getRequest()->getData();\n\n        $form = new MfaPoliciesSettingsForm();\n\n        if (!$form->execute($requestData)) {\n            throw new FormValidationException(__('Could not validate the MFA policies settings.'), $form);\n        }\n\n        $setSettingsService = new MfaPoliciesSetSettingsService();\n\n        $mfaPolicySettingsDto = MfaPolicySettings::createFromArray([\n            'policy' => $form->getData('policy'),\n            'remember_me_for_a_month' => $form->getData('remember_me_for_a_month'),\n        ]);","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/MfaPolicies/src/Controller/MfaPoliciesSettingsSetController.php#L19-L55","documentation":"The MfaPolicies settings POST endpoint is admin-only. MfaPoliciesSettingsSetController::post() checks $this->User->isAdmin() and throws ForbiddenException when the authenticated user lacks administrator privileges.","triggerScenarios":"A non-admin authenticated user (or anonymous user reaching the endpoint before auth) issues POST to /mfa/policies/settings.json.","commonSituations":"Automated scripts or CI using a regular user's API token to push MFA policy settings; testing the endpoint with a non-admin account.","solutions":["Authenticate as a passbolt administrator account before calling the endpoint","Grant administrator role to the intended service account if it legitimately must manage MFA policies","Verify the request actually carries valid authentication headers (X-CSRF-Token, session) and isn't degrading to a less-privileged identity"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if (!\\App\\Utility\\User::get()->role->is('admin')) {\n    // skip call to POST /mfa/policies/settings.json\n}","typeGuard":"$isAdmin = ($user['role']['name'] ?? null) === Role::ADMIN;","tryCatchPattern":"try {\n    $resp = $client->post('/mfa/policies/settings.json', $data);\n} catch (HttpException $e) {\n    if ($e->getCode() === 403) { /* not admin */ }\n}","preventionTips":["Use an admin service account for settings automation","Check role before invoking admin-only endpoints","Never reuse non-admin tokens for configuration tasks"],"tags":["authorization","mfa-policies","forbidden","permissions"],"backgroundTag":"permission-denied","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"}