passbolt/passbolt_api · error · InternalErrorException

Invalid response. Missing authorization endpoint.

Error message

Invalid response. Missing authorization endpoint.

What it means

validateOpenIdConfiguration() requires authorization_endpoint to be present in the OIDC discovery document, since passbolt builds the browser redirect URL from it (getBaseAuthorizationUrl). A discovery payload missing this key is incomplete/non-compliant, so an InternalErrorException is thrown.

Solutions

  1. Curl the .well-known/openid-configuration URL and verify authorization_endpoint exists.
  2. Correct the issuer/WellKnownURI in passbolt SSO settings.
  3. Check for proxies/caches serving a stale or partial discovery document and clear them.
  4. Upgrade or reconfigure the IdP so it publishes full OIDC discovery metadata.

Example fix

// before (wrong discovery doc)
'{"issuer":"https://auth.example.com"}'
// after (full OIDC metadata)
'{"issuer":"https://auth.example.com","authorization_endpoint":"https://auth.example.com/authorize",...}'
Defensive patterns

Strategy: validation

Validate before calling

$doc = json_decode(file_get_contents($wellKnownUrl), true);
if (!isset($doc['authorization_endpoint'])) { throw new UnexpectedValueException('Discovery document missing authorization_endpoint.'); }

Type guard

function hasAuthorizationEndpoint(mixed $doc): bool { return is_array($doc) && isset($doc['authorization_endpoint']) && is_string($doc['authorization_endpoint']); }

Try / catch

try { $authUrl = $provider->getBaseAuthorizationUrl(); } catch (InternalErrorException $e) { if (str_contains($e->getMessage(), 'authorization endpoint')) { /* incomplete discovery metadata */ } throw $e; }

Prevention

When it happens

Trigger: getBaseAuthorizationUrl calls getOpenIdConfiguration -> validateOpenIdConfiguration; the decoded JSON lacks the authorization_endpoint key.

Common situations: Non-compliant or truncated discovery document; IdP misconfigured behind a proxy that strips fields; wrong discovery URL returning a partial metadata document; IdP software version change removing the field.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/Provider/AbstractOauth2Provider.php:178

     * @return void
     */
    public function validateOpenIdConfiguration(mixed $response): void
    {
        if (!is_array($response)) {
            $msg = sprintf('Invalid response. Expected array, got "%s".', gettype($response));
            if (is_string($response)) {
                // Cap excerpt to limit log volume on large/HTML responses; mb_strcut is UTF-8-safe.
                $excerpt = mb_strcut($response, 0, 200, 'UTF-8');
                // Escape newlines and control characters via JSON encoding so they don't corrupt log output.
                $msg .= ' ' . sprintf('Response text (truncated): %s', json_encode($excerpt));
            }
            throw new InternalErrorException($msg);
        }
        if (!isset($response['jwks_uri'])) {
            throw new InternalErrorException('Invalid response. Missing JWKS URI');
        }
        if (!isset($response['authorization_endpoint'])) {
            throw new InternalErrorException('Invalid response. Missing authorization endpoint.');
        }
        if (!isset($response['token_endpoint'])) {
            throw new InternalErrorException('Invalid response. Missing token endpoint.');
        }
        if (!Validation::url($response['jwks_uri'])) {
            throw new InternalErrorException('Invalid response. Invalid JWKS URI');
        }
        if (!Validation::url($response['authorization_endpoint'])) {
            throw new InternalErrorException('Invalid response. Invalid authorization endpoint.');
        }
        if (!Validation::url($response['token_endpoint'])) {
            throw new InternalErrorException('Invalid response. Invalid token endpoint.');
        }
    }

    /**
     * @inheritDoc
     */

View on GitHub (pinned to 31c1bbc10f)