{"record":{"id":"3ce2b6accd6b7494","repo":"passbolt/passbolt_api","slug":"invalid-user-id-format","errorCode":null,"errorMessage":"Invalid user ID format.","messagePattern":"Invalid user ID format\\.","errorType":"http","errorClass":"InvalidVerifyTokenException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/JwtAuthentication/src/Service/VerifyToken/VerifyTokenValidationService.php","lineNumber":106,"sourceCode":"            !is_string($verifyToken) ||\n            !Validation::uuid($verifyToken)\n        ) {\n            throw new InvalidVerifyTokenException(__('Invalid verify token format.'));\n        }\n    }\n\n    /**\n     * Assert verify token is a UUID\n     *\n     * @param string $userId User ID\n     * @return void\n     * @throws \\Passbolt\\JwtAuthentication\\Error\\Exception\\VerifyToken\\InvalidVerifyTokenException if the user ID is not a UUID.\n     * @throws \\Cake\\ORM\\Exception\\PersistenceFailedException\n     */\n    protected function validateUserId(string $userId): void\n    {\n        if (!Validation::uuid($userId)) {\n            throw new InvalidVerifyTokenException(__('Invalid user ID format.'));\n        }\n    }\n\n    /**\n     * Check that this token - userId pair does not exist.\n     *\n     * @param string $verifyToken Verify Token\n     * @param string $userId User ID\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the token has already been used.\n     */\n    protected function validateNonce(string $verifyToken, string $userId): void\n    {\n        $AuthenticationTokens = TableRegistry::getTableLocator()->get('AuthenticationTokens');\n        $existingTokenWithSameValue = $AuthenticationTokens\n            ->find()\n            ->where([\n                $AuthenticationTokens->aliasField('token') => $verifyToken,","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Service/VerifyToken/VerifyTokenValidationService.php#L88-L124","documentation":"Alongside the verify token, the JWT verify-token request must carry the UUID of the user the token belongs to. validateUserId checks the user ID with Cake's Validation::uuid and throws InvalidVerifyTokenException ('Invalid user ID format.') when it is not a well-formed UUID.","triggerScenarios":"Calling the verify-token endpoint (or validateToken()) with a user id that is missing from the UUID format: empty string, numeric ID from another system, email address, or a truncated/corrupted UUID.","commonSituations":"Client confuses username/email with user ID; a migration or import produced non-UUID identifiers; test fixtures use ids like '1' or 'user-id'; copy-paste dropped characters from the UUID.","solutions":["Send the actual passbolt user UUID (36-char, hyphenated) in the user_id field","Fetch the correct user ID from the API (e.g. /users.json) instead of constructing one","Regenerate the test fixture with a UUID via Text::uuid() or a UUID generator","Verify the client is not URL-encoding or trimming the UUID before sending"],"exampleFix":"// before\nconst body = {user_id: '42', verify_token: token};\n// after\nif (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(userId)) {\n  throw new Error('user_id must be a UUID');\n}\nconst body = {user_id: userId, verify_token: token};","handlingStrategy":"validation","validationCode":"const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nif (!UUID_RE.test(userId ?? '')) throw new Error('user_id must be a UUID');","typeGuard":"function isUuid(v: unknown): v is string {\n  return typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);\n}","tryCatchPattern":"try { await api.verifyToken(token, userId); } catch (e) { if (e.response?.status === 400 && /user ID/.test(e.message)) await refetchUserId(); else throw e; }","preventionTips":["Always source user IDs from the API, not from usernames or emails","Keep UUIDs intact through URL/storage handling","Add client-side UUID validation in forms and SDKs","Use consistent 36-char hyphenated UUID representation"],"tags":["jwt","uuid","user-id","validation"],"backgroundTag":"invalid-identifier-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"}