{"record":{"id":"299db82d569f63c8","repo":"passbolt/passbolt_api","slug":"the-token-is-required-in-url-parameters","errorCode":null,"errorMessage":"The token is required in URL parameters.","messagePattern":"The token is required in URL parameters\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Controller/AbstractSsoController.php","lineNumber":122,"sourceCode":"        $error = $this->getRequest()->getData('error');\n        $desc = $this->getRequest()->getData('error_description');\n\n        if (!is_string($error) || !is_string($desc)) {\n            return null;\n        } else {\n            return [$error => $desc];\n        }\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the token is not provided in URL query\n     * @return string state\n     */\n    public function getTokenFromUrlQuery(): string\n    {\n        $token = $this->request->getQuery('token');\n        if (!is_string($token) || !OAuthTokenValidation::token($token)) {\n            throw new BadRequestException(__('The token is required in URL parameters.'));\n        }\n\n        return $token;\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the state is not provided in URL query\n     * @return string state\n     */\n    public function getStateFromUrlQuery(): string\n    {\n        $state = $this->request->getQuery('state');\n        if (!is_string($state) || !SsoState::isValidState($state)) {\n            throw new BadRequestException(__('The state is required in URL parameters.'));\n        }\n\n        return $state;\n    }","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Controller/AbstractSsoController.php#L104-L140","documentation":"The SSO success/recover-success callbacks require a 'token' query parameter that must pass OAuthTokenValidation::token() (a UUID-format check). Missing or malformed tokens are rejected with this 400 because the token identifies the verification/authentication token created in an earlier step.","triggerScenarios":"GET to ssoSuccess or ssoRecoverSuccess without ?token=..., or with a value that is not a valid UUID/token string (truncated link, tampered URL).","commonSituations":"Email clients or messaging apps truncating the callback URL at the token parameter; users hand-typing the URL; replaying an old link after the token was consumed/expired; copy-paste losing query parameters.","solutions":["Re-open the original link (from email or the client) intact, including the full token query parameter.","Request a new SSO verification/recovery email or token — old tokens are single-use and may be expired.","Verify the token is a complete UUID (no truncation) by inspecting the URL.","If links keep breaking, check the email template / client that generates the URL for encoding issues (e.g. unescaped & splitting the query)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const token = new URL(callbackUrl).searchParams.get('token');\nconst uuidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nif (!uuidRe.test(token || '')) { throw new Error('Callback token missing or not a UUID'); }","typeGuard":"function isValidToken(t) { return typeof t === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(t); }","tryCatchPattern":"try { await ssoSuccess(token); } catch (e) { if (e.status === 400 && /token is required/.test(e.message)) { requestNewVerificationToken(); } else { throw e; } }","preventionTips":["Open links from passbolt emails in full, without truncation","Request fresh tokens — they are single-use and expire","Check email/URL generation for encoding issues that break the query string"],"tags":["sso","missing-parameter","token-validation","url"],"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-21T04:17:39.646Z"}