passbolt/passbolt_api · error · InvalidArgumentException
The authentication token should be a valid UUID.
Error message
The authentication token should be a valid UUID.
What it means
MfaDuoCallbackAuthenticationTokenService::consumeAndVerifyAuthenticationToken validates the raw Duo callback authentication token string before touching the database. If Validation::uuid($token) fails, it throws this InvalidArgumentException immediately, because only UUID-format tokens can be looked up in the authentication_tokens table. It is a cheap pre-condition guard so callers never pass malformed identifiers downstream.
Solutions
- Check the token value passed in is a UUID generated by AuthenticationTokenService (e.g. from the /mfa/setup/duo endpoint response)
- Validate with \Cake\Validation\Validation::uuid($token) in the caller before invoking the service
- Fix the callback controller/route so the passbolt token UUID is extracted from the correct query parameter or path segment
- Regenerate the MFA setup token if the original was lost — it is always a UUID
Example fix
// before
$service->consumeAndVerifyAuthenticationToken($uac, $tokenType, $_GET['state'], $state);
// after
$token = $_GET['token'] ?? '';
if (!Validation::uuid($token)) {
throw new BadRequestException('Missing or malformed MFA token.');
}
$service->consumeAndVerifyAuthenticationToken($uac, $tokenType, $token, $state); Defensive patterns
Strategy: validation
Validate before calling
if (!\Cake\Validation\Validation::uuid($token)) {
throw new \Cake\Http\Exception\BadRequestException('A valid MFA token UUID is required.');
} Try / catch
try {
$authToken = $service->consumeAndVerifyAuthenticationToken($uac, $type, $token, $state);
} catch (\InvalidArgumentException $e) {
throw new \Cake\Http\Exception\BadRequestException($e->getMessage());
} Prevention
- Always pass token values straight from the authentication_tokens table, never user-authored strings
- Run Validation::uuid() at the controller boundary before calling the service
- Unit-test the callback handler with a malformed token to ensure a clean 400 response
When it happens
Trigger: Calling consumeAndVerifyAuthenticationToken() (or MfaDuoEnableService::enable() which forwards the token) with a $token argument that is not a valid UUID — e.g. a truncated token, a JWT, an empty string, or a value tampered with in the Duo callback query string.
Common situations: A developer wires up the Duo callback endpoint and passes the wrong query parameter (e.g. the Duo 'code' or 'state' instead of the passbolt token UUID); a client truncates the token URL; tests hand-craft token strings like 'invalid-token'.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The authentication token should be a valid UUID.
- The authentication token should be a valid UUID.
- The authentication token should be a valid UUID.
- The Duo state cookie should be a valid UUID.
- The Duo state cookie should be a valid UUID.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/bd0d971ccdf597e1.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoCallbackAuthenticationTokenService.php:61
* Consume and verify Duo callback authentication token.
*
* @param \App\Utility\UserAccessControl $uac User access control
* @param string $tokenType AuthenticationToken's token type
* @param string $token AuthenticationToken's token
* @param string $duoState The Duo state to verify the token state value against
* @return \App\Model\Entity\AuthenticationToken
* @throws \InvalidArgumentException if token is not a valid UUID.
* @throws \InvalidArgumentException if token type is not supported.
* @throws \InvalidArgumentException if the Duo state token is not a valid UUID.
*/
public function consumeAndVerifyAuthenticationToken(
UserAccessControl $uac,
string $tokenType,
string $token,
string $duoState
): AuthenticationToken {
if (!Validation::uuid($token)) {
throw new InvalidArgumentException('The authentication token should be a valid UUID.');
}
if (!Validation::inList($tokenType, MfaDuoCallbackAuthenticationTokenService::$ALLOWED_TOKEN_TYPES)) {
$readableAllowedTokenTypes = implode(', ', MfaDuoCallbackAuthenticationTokenService::$ALLOWED_TOKEN_TYPES);
$msg = 'The authentication token type should be one of the following: ' . $readableAllowedTokenTypes . '.';
throw new InvalidArgumentException($msg);
}
$authToken = $this->consumeAuthenticationTokenOrFail($uac, $tokenType, $token);
$this->assertDuoStateMatchesAuthenticationTokenState($authToken, $duoState);
return $authToken;
}
/**
* Consume the duo callback authentication token or fail.
*
* @param \App\Utility\UserAccessControl $uac User access control
* @param string $tokenType AuthenticationToken's token typeView on GitHub (pinned to 31c1bbc10f)