{"record":{"id":"221a72f385bd32b9","repo":"passbolt/passbolt_api","slug":"the-authentication-token-id-is-invalid","errorCode":null,"errorMessage":"The authentication token id is invalid.","messagePattern":"The authentication token id is invalid\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Controller/AccountRecoveryContinue/AccountRecoveryContinueController.php","lineNumber":66,"sourceCode":"    /**\n     * Render a page to continue the account recovery process\n     *\n     * @param string|null $userId User ID\n     * @param string|null $tokenId Token ID\n     * @param \\Passbolt\\Ee\\Service\\AccountRecoveryContinue\\AccountRecoveryContinueAggregatorService $accountRecoveryContinueService Service instance.\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the data provided is not valid\n     */\n    public function get(\n        ?string $userId,\n        ?string $tokenId,\n        AccountRecoveryContinueAggregatorService $accountRecoveryContinueService\n    ): void {\n        if (!isset($userId) || !Validation::uuid($userId)) {\n            throw new BadRequestException(__('The user id is invalid.'));\n        }\n        if (!isset($tokenId) || !Validation::uuid($tokenId)) {\n            throw new BadRequestException(__('The authentication token id is invalid.'));\n        }\n\n        if ($this->getRequest()->is('json')) {\n            // Do not allow logged in user to recover\n            if ($this->User->role() !== Role::GUEST) {\n                throw new ForbiddenException(__('Only guests are allowed to proceed with account recovery.'));\n            }\n\n            (new AccountRecoveryRequestGetService())->getOrFail($userId, $tokenId);\n\n            $data = $accountRecoveryContinueService->get();\n\n            $this->success(__('The operation was successful.'), $data);\n        } else {\n            $this->renderHtml();\n        }\n    }\n","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Controller/AccountRecoveryContinue/AccountRecoveryContinueController.php#L48-L84","documentation":"BadRequestException thrown by AccountRecoveryContinueController::get() when the tokenId route parameter is missing or not a valid UUID. It follows the userId check and guards the authentication-token identifier format.","triggerScenarios":"GET request to the account recovery continue endpoint with a missing, empty, or non-UUID token id, e.g. /account-recovery/continue/<user-uuid>.json or with 'null'/'0' as token id.","commonSituations":"Recovery email link missing the token segment; client stripping the token when redirecting; expired/rotated token id replaced with a placeholder in tests.","solutions":["Regenerate the recovery link including the full authentication token UUID","Validate the token id with Cake\\Validation::uuid() client-side before navigating","Confirm the email template renders the token id into the URL","Check the route template accepts the token parameter and the client preserves it"],"exampleFix":"// before\n$url = \"/account-recovery/continue/{$userId}.json\"; // token omitted\n// after\n$url = \"/account-recovery/continue/{$userId}/{$accountRecoveryToken->id}.json\";","handlingStrategy":"validation","validationCode":"if (!isValidUuid(tokenId)) {\n  throw new Error('authentication token id must be a UUID');\n}","typeGuard":"function isValidUuid(value: unknown): value is string {\n  return typeof value === 'string'\n    && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}","tryCatchPattern":"try {\n  await accountRecoveryContinueService.get(userId, tokenId);\n} catch (ApiError e) {\n  if (e.message.includes('token id is invalid')) {\n    showTokenLinkCorruptedScreen();\n  }\n}","preventionTips":["Include the complete token UUID in recovery links generated by email templates","Validate token ids client-side before calling the endpoint","Never hardcode placeholder token ids in tests or docs","Keep route templates and link builders in sync"],"tags":["php","cakephp","validation","uuid"],"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"}