passbolt/passbolt_api · error · BadRequestException
The Duo state cookie should be a valid UUID.
Error message
The Duo state cookie should be a valid UUID.
What it means
Format guard on the Duo state cookie during MFA callback verification: the cookie value, while a string, does not pass Validation::uuid(), so it cannot be the authentication token id the flow expects and a 400 is raised.
Solutions
- Clear MFA cookies and restart the Duo verification flow to mint a fresh UUID state cookie.
- Ensure no intermediary truncates or re-encodes the Cookie header.
- Avoid manual cookie manipulation; rely on server-generated values.
- Reproduce by comparing the cookie value against the UUID format (8-4-4-4-12 hex).
Defensive patterns
Strategy: validation
Validate before calling
const uuidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!uuidRe.test(cookies.passbolt_mfa_duo_state ?? '')) { throw new Error('Duo state cookie is not a valid UUID; restart flow.'); } Type guard
function isValidUuid(value: unknown): value is string {
return typeof value === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
} Try / catch
try {
await duoVerifyCallback();
} catch (e) {
if (e.status === 400 && /valid UUID/.test(e.message)) {
clearMfaCookies(); restartDuoVerifyFlow();
} else { throw e; }
} Prevention
- Restart the flow rather than reusing altered state cookie values.
- Guard against header truncation in proxies/load balancers.
- Validate cookie integrity (UUID shape) when instrumenting MFA debugging.
- Avoid URL re-encoding layers on the passbolt domain.
When it happens
Trigger: GET /mfa/duo/verify/callback with a corrupted, truncated, or forged state cookie value that fails UUID validation.
Common situations: Proxy header truncation; URL encoding mangling the cookie; user-crafted cookies in security testing; leftover cookies from a differently formatted flow.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- The authentication token should be a valid UUID.
- The Duo state cookie should be a valid UUID.
- The authentication token should be a valid UUID.
- The authentication token should be a valid UUID.
- The authentication token should be a valid UUID.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/ca160b796157f07a.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Controller/Duo/DuoVerifyCallbackGetController.php:188
*
* @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.'));
}
$cookieToExpire = new Cookie(MfaDuoStateCookieService::MFA_COOKIE_DUO_STATE);
$this->setResponse($this->getResponse()->withExpiredCookie($cookieToExpire));
if (!is_string($cookieToken)) {
throw new BadRequestException(__('The Duo state cookie value should be a string.'));
} elseif (!Validation::uuid($cookieToken)) {
throw new BadRequestException(__('The Duo state cookie should be a valid UUID.'));
}
return $cookieToken;
}
/**
* Add to the response the MFA verified cookie.
*
* @param \App\Utility\UserAccessControl $uac User access control
* @param \App\Authenticator\SessionIdentificationServiceInterface $sessionIdentificationService session ID service
* @return void
* @throws \Cake\Http\Exception\InternalErrorException if it cannot create MFA cookie
*/
private function addMfaVerifiedCookieToResponse(
UserAccessControl $uac,
SessionIdentificationServiceInterface $sessionIdentificationService
): void {
try {View on GitHub (pinned to 31c1bbc10f)