BookStackApp/BookStack · error · OidcException

Userinfo endpoint response validation failed with error: {$e

Error message

Userinfo endpoint response validation failed with error: {$exception->getMessage()}

What it means

When the userinfo endpoint is used, BookStack validates the userinfo response against the ID token's 'sub' and the configured client_id via OidcUserinfoResponse::validate(). If that raises OidcInvalidTokenException, it is wrapped in this OidcException so the operator sees which userinfo validation failed.

Source

Thrown at app/Access/Oidc/OidcService.php:270

            $idToken,
            $this->config()['external_id_claim'],
            $this->config()['display_name_claims'] ?? '',
            $this->config()['groups_claim'] ?? ''
        );

        if (!$userDetails->isFullyPopulated($this->shouldSyncGroups()) && !empty($settings->userinfoEndpoint)) {
            $provider = $this->getProvider($settings);
            $request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken());
            $response = new OidcUserinfoResponse(
                $provider->getResponse($request),
                $settings->issuer,
                $settings->keys,
            );

            try {
                $response->validate($idToken->getClaim('sub'), $settings->clientId);
            } catch (OidcInvalidTokenException $exception) {
                throw new OidcException("Userinfo endpoint response validation failed with error: {$exception->getMessage()}");
            }

            $userDetails->populate(
                $response,
                $this->config()['external_id_claim'],
                $this->config()['display_name_claims'] ?? '',
                $this->config()['groups_claim'] ?? ''
            );
        }

        return $userDetails;
    }

    /**
     * Get the OIDC config from the application.
     */
    protected function config(): array
    {

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Check the wrapped message: it distinguishes 'No valid subject value' from 'Subject value ... does not match'
  2. Ensure the IdP returns the same 'sub' in userinfo and ID token (disable pairwise/subject-per-client settings if needed)
  3. Update the IdP or switch to a spec-compliant provider version
  4. Verify no reverse proxy is altering the userinfo response body
  5. If userinfo is unnecessary, disable it (remove userinfo endpoint config) so details come from the ID token only
Defensive patterns

Strategy: validation

Validate before calling

// Verify userinfo vs ID token sub before calling the API:
$ui = json_decode(file_get_contents($userinfoUrl, false, stream_context_create(['http' => ['header' => "Authorization: Bearer $at\r\n"]])), true);
$idTokenClaims = json_decode(base64_decode(explode('.', $idToken)[1]), true);
if (!isset($ui['sub']) || !is_string($ui['sub']) || $ui['sub'] !== $idTokenClaims['sub']) {
    // IdP is misbehaving — fix subject type / disable userinfo
}

Try / catch

try {
    auth()->attemptOidcLogin();
} catch (BookStack\Access\Oidc\OidcException $e) {
    if (str_contains($e->getMessage(), 'Userinfo endpoint response validation failed')) {
        abort(502, 'IdP userinfo response failed validation — check pairwise/public subject settings');
    }
    throw $e;
}

Prevention

When it happens

Trigger: getUserDetailsFromToken fetches the userinfo response, then $response->validate($idToken->getClaim('sub'), $settings->clientId) fails — typically subject mismatch between userinfo and ID token, or missing/invalid sub in the userinfo payload.

Common situations: Misbehaving or misconfigured IdP returning a different subject in userinfo vs ID token (e.g. pairwise subject identifiers or per-client sub values), a proxy/gateway rewriting responses, or an IdP not OIDC-spec compliant (missing sub).

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/7e278158253f3ff7. Report an issue: GitHub.