passbolt/passbolt_api · error · InternalErrorException

Invalid response. Invalid token endpoint.

Error message

Invalid response. Invalid token endpoint.

What it means

validateOpenIdConfiguration() checks token_endpoint with Validation::url(). If present but not a valid absolute URL, the token exchange endpoint is unusable and an InternalErrorException 'Invalid response. Invalid token endpoint.' is thrown. This is the final check in the discovery validation chain.

Solutions

  1. Inspect the discovery JSON; token_endpoint must be an absolute http(s) URL.
  2. Correct the IdP's base URL / endpoint configuration and republish metadata.
  3. Fix proxy/rewrite rules altering endpoint URLs.
  4. Retest SSO; the error disappears once the token endpoint validates.

Example fix

// before
'{"token_endpoint":"//auth.example.com/token"}'
// after
'{"token_endpoint":"https://auth.example.com/token"}'
Defensive patterns

Strategy: validation

Validate before calling

use Cake\Validation\Validation;
$doc = json_decode(file_get_contents($wellKnownUrl), true);
if (!isset($doc['token_endpoint']) || !Validation::url($doc['token_endpoint'])) { throw new UnexpectedValueException('token_endpoint missing or not a valid absolute URL.'); }

Type guard

function isValidTokenEndpoint(mixed $doc): bool { return is_array($doc) && isset($doc['token_endpoint']) && is_string($doc['token_endpoint']) && Validation::url($doc['token_endpoint']); }

Try / catch

try { $tokenUrl = $provider->getBaseAccessTokenUrl(); } catch (InternalErrorException $e) { if (str_contains($e->getMessage(), 'Invalid token endpoint')) { /* metadata emits malformed token_endpoint */ } throw $e; }

Prevention

When it happens

Trigger: Decoded discovery JSON contains token_endpoint whose value fails Validation::url() during the token-exchange setup via getBaseAccessTokenUrl.

Common situations: IdP publishing relative or malformed token endpoint URLs; proxy rewriting the metadata; self-hosted IdP with a misconfigured external base URL.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

            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
     */
    protected function getAuthorizationParameters(array $options)
    {
        $options = parent::getAuthorizationParameters($options);

        /**
         * The "approval_prompt" MUST be removed as it is not supported by Google, use "prompt" instead:
         *
         * @link https://developers.google.com/identity/protocols/oauth2/openid-connect#prompt
         */
        unset($options['approval_prompt']);

        return $options;

View on GitHub (pinned to 31c1bbc10f)