{"record":{"id":"69ac404971356755","repo":"passbolt/passbolt_api","slug":"unable-to-validate-the-duo-callback-data-69ac40","errorCode":null,"errorMessage":"Unable to validate the Duo callback data.","messagePattern":"Unable to validate the Duo callback data\\.","errorType":"validation","errorClass":"FormValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Controller/Duo/DuoVerifyCallbackGetController.php","lineNumber":162,"sourceCode":"     * @throws \\Cake\\Http\\Exception\\BadRequestException If Duo was not able to authenticate the user and provided error details\n     * @return \\Passbolt\\MultiFactorAuthentication\\Model\\Dto\\MfaDuoCallbackDto\n     */\n    private function getAndAssertMfaDuoCallbackData(): MfaDuoCallbackDto\n    {\n        $mfaDuoCallbackData = $this->getRequest()->getQueryParams();\n        $mfaDuoCallbackForm = new DuoCallbackForm();\n        $isValid = $mfaDuoCallbackForm->execute($mfaDuoCallbackData);\n        $mfaDuoCallbackDto = new MfaDuoCallbackDto($mfaDuoCallbackForm->getData());\n\n        if ($mfaDuoCallbackDto->hasError()) {\n            $msg = __('Unable to authenticate to Duo.');\n            $msg .= \" {$mfaDuoCallbackDto->formatError()}\";\n            throw new BadRequestException($msg);\n        }\n\n        if (!$isValid) {\n            $msg = __('Unable to validate the Duo callback data.');\n            throw new FormValidationException($msg, $mfaDuoCallbackForm);\n        }\n\n        return $mfaDuoCallbackDto;\n    }\n\n    /**\n     * Consume the duo state cookie containing the user authentication token id and assert the format this one.\n     *\n     * @return string The token id stored in the cookie\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the cookie is not defined\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the cookie value is not a string\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the cookie value is not a valid uuid\n     */\n    private function consumeAndAssertCookieToken(): string\n    {\n        $cookieToken = (new MfaDuoStateCookieService())->readDuoStateCookieValue($this->getRequest());\n        if (is_null($cookieToken)) {\n            throw new BadRequestException(__('A Duo state cookie is required.'));","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Controller/Duo/DuoVerifyCallbackGetController.php#L144-L180","documentation":"FormValidationException thrown by DuoVerifyCallbackGetController::getAndAssertMfaDuoCallbackData when MfaDuoCallbackForm->execute() returns false — the callback data failed server-side form validation. Unlike error 295, the DTO reported no formatted error; the form's validation errors are attached to the exception.","triggerScenarios":"GET /mfa/duo/verify/callback with missing or malformed query parameters required by MfaDuoCallbackForm (e.g. missing state, code, or duo fields), so the form cannot validate.","commonSituations":"Duo redirect truncated or manually edited callback URL; proxy stripping query parameters; wrong callback URL configured in the Duo application; mismatched state key between passbolt and Duo.","solutions":["Check the exception's form errors to see which callback fields failed validation.","Verify the Duo application's redirect/callback URL matches the passbolt route exactly.","Restart the Duo verification flow so Duo re-issues complete callback parameters.","Ensure no proxy or middleware strips query string parameters from the callback request.","Confirm MFA Duo settings (state request key) are consistent with the Duo application config."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// client-side pre-check that expected callback query params exist\nconst required = ['state', 'code'];\nconst params = new URLSearchParams(callbackUrl.split('?')[1]);\nconst missing = required.filter(k => !params.get(k));\nif (missing.length) { throw new Error('Duo callback missing params: ' + missing.join(',')); }","typeGuard":null,"tryCatchPattern":"try {\n  await duoVerifyCallback();\n} catch (e) {\n  if (e.name === 'FormValidationException' || /Unable to validate the Duo callback data/.test(e.message)) {\n    logFormErrors(e.errors); restartDuoVerifyFlow();\n  } else { throw e; }\n}","preventionTips":["Configure the Duo application callback URL to match the passbolt route exactly.","Ensure proxies preserve the full query string on redirects.","Restart the flow when callback parameters look truncated or missing.","Keep MFA Duo settings consistent with the Duo application configuration."],"tags":["duo","mfa","form-validation","callback"],"backgroundTag":"schema-validation-failed","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"}