{"record":{"id":"d092bb945c1fc403","repo":"passbolt/passbolt_api","slug":"an-authentication-token-should-be-provided","errorCode":null,"errorMessage":"An authentication token should be provided.","messagePattern":"An authentication token should be provided\\.","errorType":"http","errorClass":"Cake\\Http\\Exception\\BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryRequests/AccountRecoveryRequestCreateService.php","lineNumber":166,"sourceCode":"            $msg = __('Recovery request cannot be created when user is not enrolled.');\n            throw new BadRequestException($msg);\n        }\n    }\n\n    /**\n     * Return the authentication from data if any\n     *\n     * @param string $userId the user uuid the token belongs to\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if no authentication token was provided\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the authentication token is not a uuid\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the authentication token is expired or invalid\n     * @return \\App\\Model\\Entity\\AuthenticationToken\n     */\n    protected function getAndAssertToken(string $userId): AuthenticationToken\n    {\n        $token = $this->getData('authentication_token.token');\n        if (!isset($token)) {\n            throw new BadRequestException(__('An authentication token should be provided.'));\n        }\n\n        try {\n            $tokenEntity = (new AuthenticationTokenGetService())\n                ->getActiveNotExpiredOrFail($token, $userId, AuthenticationToken::TYPE_RECOVER);\n        } catch (NotFoundException $exception) {\n            throw new BadRequestException(__('The authentication token is not valid or has expired.'));\n        }\n\n        // Deactivate all previous active tokens\n        $this->AuthenticationTokens->updateQuery()\n            ->set(['active' => false])\n            ->where([\n                'id <>' => $tokenEntity->id,\n                'active' => true,\n                'type' => AuthenticationToken::TYPE_RECOVER,\n                'user_id' => $userId,\n            ])","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryRequests/AccountRecoveryRequestCreateService.php#L148-L184","documentation":"BadRequestException from getAndAssertToken when no `authentication_token.token` is present in the request data. A recover-type authentication token is mandatory to correlate the recovery request with the user's session.","triggerScenarios":"POST /account-recovery/requests with the `authentication_token.token` key missing or null.","commonSituations":"Client forgot to include the token obtained from the recover start endpoint; payload nesting flattened incorrectly (`token` at top level instead of under `authentication_token`); an old client version using a different field name.","solutions":["Include `authentication_token.token` in the request payload","Obtain the token first from the recovery start flow (verify step) and pass it through","Fix payload nesting so the token sits under the `authentication_token` key"],"exampleFix":"// before\n{\"user_id\": \"54c3...\", \"token\": \"...\"}\n// after\n{\"user_id\": \"54c3...\", \"authentication_token\": {\"token\": \"...\"}}","handlingStrategy":"validation","validationCode":"if (empty($data['authentication_token']['token'])) { throw new \\InvalidArgumentException('authentication_token.token is required'); }","typeGuard":"null","tryCatchPattern":"try { $service->create($data); } catch (BadRequestException $e) { if (str_contains($e->getMessage(), 'token should be provided')) { requestNewToken(); } }","preventionTips":["Always obtain the token from the recovery start step before creating the request","Serialize the token under the `authentication_token.token` key","Add a client-side contract test for the request payload shape"],"tags":["authentication","missing-field","account-recovery","bad-request"],"backgroundTag":"missing-required-argument","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}