BookStackApp/BookStack · error · OidcIssuerDiscoveryException

Error discovering provider settings from issuer at URL {$iss

Error message

Error discovering provider settings from issuer at URL {$issuerUrl}

What it means

loadSettingsFromIssuerDiscovery() throws this when the response from {issuer}/.well-known/openid-configuration is empty, is not valid JSON, or does not decode to an array. The library therefore received *a* HTTP response but it wasn't a usable discovery document.

Source

Thrown at app/Access/Oidc/OidcProviderSettings.php:122

            $this->applySettingsFromArray($discoveredSettings);
        } catch (ClientExceptionInterface $exception) {
            throw new OidcIssuerDiscoveryException("HTTP request failed during discovery with error: {$exception->getMessage()}");
        }
    }

    /**
     * @throws OidcIssuerDiscoveryException
     * @throws ClientExceptionInterface
     */
    protected function loadSettingsFromIssuerDiscovery(ClientInterface $httpClient): array
    {
        $issuerUrl = rtrim($this->issuer, '/') . '/.well-known/openid-configuration';
        $request = new Request('GET', $issuerUrl);
        $response = $httpClient->sendRequest($request);
        $result = json_decode($response->getBody()->getContents(), true);

        if (empty($result) || !is_array($result)) {
            throw new OidcIssuerDiscoveryException("Error discovering provider settings from issuer at URL {$issuerUrl}");
        }

        if ($result['issuer'] !== $this->issuer) {
            throw new OidcIssuerDiscoveryException('Unexpected issuer value found on discovery response');
        }

        $discoveredSettings = [];

        if (!empty($result['authorization_endpoint'])) {
            $discoveredSettings['authorizationEndpoint'] = $result['authorization_endpoint'];
        }

        if (!empty($result['token_endpoint'])) {
            $discoveredSettings['tokenEndpoint'] = $result['token_endpoint'];
        }

        if (!empty($result['userinfo_endpoint'])) {
            $discoveredSettings['userinfoEndpoint'] = $result['userinfo_endpoint'];

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. curl the discovery URL from the server and inspect the raw body — it must be JSON with issuer, endpoints and jwks_uri.
  2. Correct OIDC_ISSUER so it points to the actual OIDC issuer (e.g. include the realm path in Keycloak: https://host/realms/<realm>).
  3. Bypass or authenticate the proxy/WAF intercepting server-to-server requests, or allowlist the BookStack host.
  4. Verify no redirect to an SSO login page occurs (curl -L and check content-type is application/json).

Example fix

# before
OIDC_ISSUER=https://keycloak.example.com  # hits portal HTML
# after
OIDC_ISSUER=https://keycloak.example.com/realms/main  # serves JSON discovery
Defensive patterns

Strategy: type-guard

Validate before calling

$raw = file_get_contents(rtrim(config('oidc.issuer'), '/') . '/.well-known/openid-configuration');
$doc = json_decode($raw ?? '', true);
if (!is_array($doc) || empty($doc['issuer'])) {
    throw new RuntimeException('Discovery endpoint did not return a JSON document');
}

Type guard

function isValidDiscoveryDoc(?array $decoded): bool {
    return is_array($decoded)
        && isset($decoded['issuer'], $decoded['authorization_endpoint'], $decoded['token_endpoint']);
}

Try / catch

try {
    $settings->discoverFromIssuer($client, $cache, 15);
} catch (OidcIssuerDiscoveryException $e) {
    if (str_contains($e->getMessage(), 'Error discovering provider settings')) {
        Log::error('Discovery response was not JSON — check issuer URL / auth walls: ' . $e->getMessage());
    }
}

Prevention

When it happens

Trigger: The discovery URL returns 200 with non-JSON content (HTML login/error page, empty body, proxy interstitial), or the request was redirected to an SSO sign-in page that returns HTML with status 200.

Common situations: Issuer URL wrong so a web server's default page/404 HTML is returned; an auth wall or WAF intercepting the request; gzip/misconfigured proxy returning garbage; hitting a human-facing portal path instead of the real OIDC issuer.

Related errors


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