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

MfaDuoLoginService::login() requires the mfa_verify authentication token id passed as $token to be a valid UUID. Validation::uuid() rejects anything else, and an InvalidArgumentException is thrown before the token is consumed.

Solutions

  1. Pass the full authentication token UUID generated during the Duo start flow (AuthenticationToken.id)
  2. Validate with Validation::uuid($token) (or a regex) before calling login()
  3. Check that the callback route/query parameter name matches what passbolt emits so the token is not truncated

Example fix

// before
$service->login($uac, $dto, $this->request->getQuery('token'));
// after
$token = $this->request->getQuery('token') ?? '';
if (!Validation::uuid($token)) { throw new BadRequestException('Missing mfa token'); }
$service->login($uac, $dto, $token);
Defensive patterns

Strategy: validation

Validate before calling

use Cake\Validation\Validation;
if (!is_string($token) || !Validation::uuid($token)) { throw new \InvalidArgumentException('token must be a UUID'); }

Type guard

function isUuid(mixed $v): bool { return is_string($v) && (bool)preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $v); }

Try / catch

try { $service->login($uac, $dto, $token); } catch (\InvalidArgumentException $e) { /* return 400 invalid token */ }

Prevention

When it happens

Trigger: Calling login($uac, $duoCallbackDto, $token) where $token is empty, truncated, url-mangled, or any non-UUID string — commonly a malformed callback query parameter.

Common situations: User bookmarks/pastes a partially truncated callback URL; a reverse proxy or client code mangles the query string; a custom frontend passes a session id instead of the token UUID.

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


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/5940f529be3b452b. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoLoginService.php:80

    /**
     * Login using Duo for the operator.
     *
     * @param \App\Utility\UserAccessControl $uac The user access control
     * @param \Passbolt\MultiFactorAuthentication\Model\Dto\MfaDuoCallbackDto $duoCallbackDto The Duo callback data
     * @param string $token The authentication token.
     * @return \App\Model\Entity\AuthenticationToken
     * @throws \InvalidArgumentException if the provided token is not a UUID
     * @throws \Cake\Http\Exception\UnauthorizedException If no active Duo callback authentication can be found.
     * @throws \Cake\Http\Exception\UnauthorizedException If the duo state cannot be verified.
     * @throws \Cake\Http\Exception\UnauthorizedException If the Duo code cannot be verified.
     */
    public function login(
        UserAccessControl $uac,
        MfaDuoCallbackDto $duoCallbackDto,
        string $token
    ): AuthenticationToken {
        if (!Validation::uuid($token)) {
            throw new InvalidArgumentException('The authentication token should be a valid UUID.');
        }
        $authenticationTokenType = AuthenticationToken::TYPE_MFA_VERIFY;
        $authenticationToken = (new MfaDuoCallbackAuthenticationTokenService())
            ->consumeAndVerifyAuthenticationToken(
                $uac,
                $authenticationTokenType,
                $token,
                $duoCallbackDto->state
            );
        try {
            (new MfaDuoVerifyDuoCodeService($authenticationTokenType, $this->duoClient))
                ->verify($uac, $duoCallbackDto->duoCode);
        } catch (Throwable $th) {
            throw new BadRequestException(__('Unable to verify Duo authentication.'), null, $th);
        }

        return $authenticationToken;
    }

View on GitHub (pinned to 31c1bbc10f)