{"record":{"id":"c8838e3289d7d347","repo":"passbolt/passbolt_api","slug":"the-code-is-required-in-url-parameters","errorCode":null,"errorMessage":"The code is required in URL parameters.","messagePattern":"The code is required in URL parameters\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Controller/AbstractSsoController.php","lineNumber":150,"sourceCode":"    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    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the code (access token) is not provided in URL query\n     * @return string code\n     */\n    public function getCodeFromUrlQuery(): string\n    {\n        $code = $this->request->getQuery('code');\n        if (!isset($code) || !is_string($code)) {\n            throw new BadRequestException(__('The code is required in URL parameters.'));\n        }\n\n        return $code;\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the code (access token) is not provided in request data\n     * @return string code\n     */\n    public function getCodeFromRequestData(): string\n    {\n        $code = $this->getRequest()->getData('code');\n        if (!isset($code) || !is_string($code)) {\n            throw new BadRequestException(__('The code is required in request data.'));\n        }\n\n        return $code;\n    }","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Controller/AbstractSsoController.php#L132-L168","documentation":"The OAuth2 callback must carry the authorization 'code' query parameter issued by the identity provider. If it is unset or not a string, the controller cannot perform the token exchange and throws this 400.","triggerScenarios":"GET to the SSO stage2 callback without ?code=..., or with a non-string value — often because the provider redirected with an error parameter (error/error_description) instead of a code.","commonSituations":"User denied consent at the provider (redirect contains error=access_denied, no code); wrong callback URL configured at the provider; provider outage returning an error redirect; user bookmarking/replaying a URL after the code was consumed.","solutions":["Inspect the callback URL for an 'error' query parameter — the provider refused the request (e.g. consent denied); have the user retry and approve.","Verify the redirect URI registered with the provider exactly matches the passbolt SSO settings.","Restart the SSO flow; authorization codes are single-use and short-lived.","Check provider status/endpoint configuration if error redirects occur for all users."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const params = new URL(callbackUrl).searchParams;\nif (!params.get('error') && typeof params.get('code') !== 'string') { throw new Error('No authorization code and no error param — check provider redirect config'); }","typeGuard":"function hasCodeParam(url) { return typeof new URL(url).searchParams.get('code') === 'string'; }","tryCatchPattern":"try { await ssoStage2(url); } catch (e) { if (e.status === 400 && /code is required/.test(e.message)) { const err = new URL(url).searchParams.get('error'); handleProviderError(err || 'missing code'); restartFlow(); } else { throw e; } }","preventionTips":["Match the provider-registered redirect URI exactly","Handle provider error redirects (error=access_denied) explicitly","Use codes once, promptly — never replay callback URLs","Monitor provider status for outage-driven error redirects"],"tags":["sso","oauth2","missing-parameter","callback"],"backgroundTag":"missing-query-parameter","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"}