passbolt/passbolt_api · error · BadRequestException

The code is required in URL parameters.

Error message

The code is required in URL parameters.

What it means

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.

Solutions

  1. Inspect the callback URL for an 'error' query parameter — the provider refused the request (e.g. consent denied); have the user retry and approve.
  2. Verify the redirect URI registered with the provider exactly matches the passbolt SSO settings.
  3. Restart the SSO flow; authorization codes are single-use and short-lived.
  4. Check provider status/endpoint configuration if error redirects occur for all users.
Defensive patterns

Strategy: validation

Validate before calling

const params = new URL(callbackUrl).searchParams;
if (!params.get('error') && typeof params.get('code') !== 'string') { throw new Error('No authorization code and no error param — check provider redirect config'); }

Type guard

function hasCodeParam(url) { return typeof new URL(url).searchParams.get('code') === 'string'; }

Try / catch

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; } }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/c8838e3289d7d347. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Controller/AbstractSsoController.php:150

    public function getStateFromUrlQuery(): string
    {
        $state = $this->request->getQuery('state');
        if (!is_string($state) || !SsoState::isValidState($state)) {
            throw new BadRequestException(__('The state is required in URL parameters.'));
        }

        return $state;
    }

    /**
     * @throws \Cake\Http\Exception\BadRequestException if the code (access token) is not provided in URL query
     * @return string code
     */
    public function getCodeFromUrlQuery(): string
    {
        $code = $this->request->getQuery('code');
        if (!isset($code) || !is_string($code)) {
            throw new BadRequestException(__('The code is required in URL parameters.'));
        }

        return $code;
    }

    /**
     * @throws \Cake\Http\Exception\BadRequestException if the code (access token) is not provided in request data
     * @return string code
     */
    public function getCodeFromRequestData(): string
    {
        $code = $this->getRequest()->getData('code');
        if (!isset($code) || !is_string($code)) {
            throw new BadRequestException(__('The code is required in request data.'));
        }

        return $code;
    }

View on GitHub (pinned to 31c1bbc10f)