{"record":{"id":"bd0d971ccdf597e1","repo":"passbolt/passbolt_api","slug":"the-authentication-token-should-be-a-valid-uuid-bd0d97","errorCode":null,"errorMessage":"The authentication token should be a valid UUID.","messagePattern":"The authentication token should be a valid UUID\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoCallbackAuthenticationTokenService.php","lineNumber":61,"sourceCode":"     * Consume and verify Duo callback authentication token.\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac User access control\n     * @param string $tokenType AuthenticationToken's token type\n     * @param string $token AuthenticationToken's token\n     * @param string $duoState The Duo state to verify the token state value against\n     * @return \\App\\Model\\Entity\\AuthenticationToken\n     * @throws \\InvalidArgumentException if token is not a valid UUID.\n     * @throws \\InvalidArgumentException if token type is not supported.\n     * @throws \\InvalidArgumentException if the Duo state token is not a valid UUID.\n     */\n    public function consumeAndVerifyAuthenticationToken(\n        UserAccessControl $uac,\n        string $tokenType,\n        string $token,\n        string $duoState\n    ): AuthenticationToken {\n        if (!Validation::uuid($token)) {\n            throw new InvalidArgumentException('The authentication token should be a valid UUID.');\n        }\n        if (!Validation::inList($tokenType, MfaDuoCallbackAuthenticationTokenService::$ALLOWED_TOKEN_TYPES)) {\n            $readableAllowedTokenTypes = implode(', ', MfaDuoCallbackAuthenticationTokenService::$ALLOWED_TOKEN_TYPES);\n            $msg = 'The authentication token type should be one of the following: ' . $readableAllowedTokenTypes . '.';\n            throw new InvalidArgumentException($msg);\n        }\n\n        $authToken = $this->consumeAuthenticationTokenOrFail($uac, $tokenType, $token);\n        $this->assertDuoStateMatchesAuthenticationTokenState($authToken, $duoState);\n\n        return $authToken;\n    }\n\n    /**\n     * Consume the duo callback authentication token or fail.\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac User access control\n     * @param string $tokenType AuthenticationToken's token type","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoCallbackAuthenticationTokenService.php#L43-L79","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","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"],"exampleFix":"// before\n$service->consumeAndVerifyAuthenticationToken($uac, $tokenType, $_GET['state'], $state);\n// after\n$token = $_GET['token'] ?? '';\nif (!Validation::uuid($token)) {\n    throw new BadRequestException('Missing or malformed MFA token.');\n}\n$service->consumeAndVerifyAuthenticationToken($uac, $tokenType, $token, $state);","handlingStrategy":"validation","validationCode":"if (!\\Cake\\Validation\\Validation::uuid($token)) {\n    throw new \\Cake\\Http\\Exception\\BadRequestException('A valid MFA token UUID is required.');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $authToken = $service->consumeAndVerifyAuthenticationToken($uac, $type, $token, $state);\n} catch (\\InvalidArgumentException $e) {\n    throw new \\Cake\\Http\\Exception\\BadRequestException($e->getMessage());\n}","preventionTips":["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"],"tags":["validation","uuid","mfa","duo"],"backgroundTag":"invalid-argument-format","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"}