{"record":{"id":"df35075fb6366ee4","repo":"passbolt/passbolt_api","slug":"the-multi-factor-authentication-is-not-required","errorCode":null,"errorMessage":"The multi-factor authentication is not required.","messagePattern":"The multi-factor authentication is not required\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Controller/MfaVerifyController.php","lineNumber":81,"sourceCode":"     * @return void\n     */\n    protected function _handleVerifiedNotRequired(\n        SessionIdentificationServiceInterface $sessionIdentificationService,\n        ?RememberAMonthSettingInterface $rememberMeForAMonthSetting = null\n    ) {\n        // Mfa cookie is set and a valid token\n        $uac = $this->User->getAccessControl();\n        $mfaVerifiedToken = $this->request->getCookie(MfaVerifiedCookie::MFA_COOKIE_ALIAS);\n        if (isset($mfaVerifiedToken)) {\n            $isValid = MfaVerifiedToken::check(\n                $uac,\n                $mfaVerifiedToken,\n                $sessionIdentificationService,\n                $this->getRequest(),\n                $rememberMeForAMonthSetting\n            );\n            if ($isValid) {\n                throw new BadRequestException(__('The multi-factor authentication is not required.'));\n            }\n        }\n    }\n\n    /**\n     * Trigger an error if current MFA settings do not allow verify for the given provider.\n     *\n     * Callers MUST return the response when a non-null value is returned; otherwise the request\n     * will continue to execute past a disabled provider and can mint an MFA cookie.\n     *\n     * @param string $provider name of the provider\n     * @return \\Cake\\Http\\Response|null redirect response for non-JSON requests, null when settings are valid\n     * @throws \\Cake\\Http\\Exception\\BadRequestException on JSON requests with invalid settings\n     */\n    protected function _handleInvalidSettings(string $provider): ?Response\n    {\n        if ($this->mfaSettings->getAccountSettings() === null) {\n            if ($this->getRequest()->is('json')) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Controller/MfaVerifyController.php#L63-L99","documentation":"During MFA verification the controller checks whether MFA is actually required for the current request; if an existing MFA verified token is still valid, verification is unnecessary and a BadRequestException is thrown instead of issuing a redundant verification.","triggerScenarios":"GET/POST to /mfa/verify when the user's MFA verified cookie/token is already valid for this session (isValid === true in _handleVerifiedNotRequired) and MFA is not pending.","commonSituations":"Client repeating verify after a successful verification; double-submitting the verify form; cached token still present while the frontend forces the verify screen.","solutions":["Skip the verify call — the session is already MFA verified","Clear the stale MFA verified cookie/token if a fresh verification is truly needed","Fix client logic to track verification state and avoid redundant verify requests"],"exampleFix":"// before: always calling verify\nawait http.post('/mfa/verify/totp.json', {totp});\n// after: check state first\nif (!mfaIsVerified) await http.post('/mfa/verify/totp.json', {totp});","handlingStrategy":"validation","validationCode":"const verified = await isMfaVerified();\nif (verified) return; // skip verify call","typeGuard":null,"tryCatchPattern":"try { await mfaVerify(provider, token); } catch (e) { if (/not required/.test(e.message)) return; throw e; }","preventionTips":["Track MFA verification state client-side","Treat 'not required' as success in verification flows","Avoid retry loops on verify endpoints"],"tags":["mfa","verify","redundant-request","http-400"],"backgroundTag":"invalid-state-transition","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"}