passbolt/passbolt_api · error · FormValidationException
Unable to validate the Duo callback data.
Error message
Unable to validate the Duo callback data.
What it means
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.
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side pre-check that expected callback query params exist
const required = ['state', 'code'];
const params = new URLSearchParams(callbackUrl.split('?')[1]);
const missing = required.filter(k => !params.get(k));
if (missing.length) { throw new Error('Duo callback missing params: ' + missing.join(',')); } Try / catch
try {
await duoVerifyCallback();
} catch (e) {
if (e.name === 'FormValidationException' || /Unable to validate the Duo callback data/.test(e.message)) {
logFormErrors(e.errors); restartDuoVerifyFlow();
} else { throw e; }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Unable to validate the Duo callback data.
- Unable to authenticate to Duo.
- Unable to authenticate to Duo.
- A Duo state cookie is required.
- A Duo state cookie is required.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/69ac404971356755.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Controller/Duo/DuoVerifyCallbackGetController.php:162
* @throws \Cake\Http\Exception\BadRequestException If Duo was not able to authenticate the user and provided error details
* @return \Passbolt\MultiFactorAuthentication\Model\Dto\MfaDuoCallbackDto
*/
private function getAndAssertMfaDuoCallbackData(): MfaDuoCallbackDto
{
$mfaDuoCallbackData = $this->getRequest()->getQueryParams();
$mfaDuoCallbackForm = new DuoCallbackForm();
$isValid = $mfaDuoCallbackForm->execute($mfaDuoCallbackData);
$mfaDuoCallbackDto = new MfaDuoCallbackDto($mfaDuoCallbackForm->getData());
if ($mfaDuoCallbackDto->hasError()) {
$msg = __('Unable to authenticate to Duo.');
$msg .= " {$mfaDuoCallbackDto->formatError()}";
throw new BadRequestException($msg);
}
if (!$isValid) {
$msg = __('Unable to validate the Duo callback data.');
throw new FormValidationException($msg, $mfaDuoCallbackForm);
}
return $mfaDuoCallbackDto;
}
/**
* Consume the duo state cookie containing the user authentication token id and assert the format this one.
*
* @return string The token id stored in the cookie
* @throws \Cake\Http\Exception\BadRequestException if the cookie is not defined
* @throws \Cake\Http\Exception\BadRequestException if the cookie value is not a string
* @throws \Cake\Http\Exception\BadRequestException if the cookie value is not a valid uuid
*/
private function consumeAndAssertCookieToken(): string
{
$cookieToken = (new MfaDuoStateCookieService())->readDuoStateCookieValue($this->getRequest());
if (is_null($cookieToken)) {
throw new BadRequestException(__('A Duo state cookie is required.'));View on GitHub (pinned to 31c1bbc10f)