{"record":{"id":"e484a8b239bc08f7","repo":"BookStackApp/BookStack","slug":"oidc-discovery-error","errorCode":null,"errorMessage":"OIDC Discovery Error: ","messagePattern":"OIDC Discovery Error: ","errorType":"exception","errorClass":"OidcException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcService.php","lineNumber":117,"sourceCode":"            'clientId'              => $config['client_id'],\n            'clientSecret'          => $config['client_secret'],\n            'authorizationEndpoint' => $config['authorization_endpoint'],\n            'tokenEndpoint'         => $config['token_endpoint'],\n            'endSessionEndpoint'    => is_string($config['end_session_endpoint']) ? $config['end_session_endpoint'] : null,\n            'userinfoEndpoint'      => $config['userinfo_endpoint'],\n        ]);\n\n        // Use keys if configured\n        if (!empty($config['jwt_public_key'])) {\n            $settings->keys = [$config['jwt_public_key']];\n        }\n\n        // Run discovery\n        if ($config['discover'] ?? false) {\n            try {\n                $settings->discoverFromIssuer($this->http->buildClient(5), Cache::store(null), 15);\n            } catch (OidcIssuerDiscoveryException $exception) {\n                throw new OidcException('OIDC Discovery Error: ' . $exception->getMessage());\n            }\n        }\n\n        // Prevent use of RP-initiated logout if specifically disabled\n        // Or force use of a URL if specifically set.\n        if ($config['end_session_endpoint'] === false) {\n            $settings->endSessionEndpoint = null;\n        } else if (is_string($config['end_session_endpoint'])) {\n            $settings->endSessionEndpoint = $config['end_session_endpoint'];\n        }\n\n        $settings->validate();\n\n        return $settings;\n    }\n\n    /**\n     * Load the underlying OpenID Connect Provider.","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcService.php#L99-L135","documentation":"OidcService::getProviderSettings() catches OidcIssuerDiscoveryException from discoverFromIssuer() and rethrows it as a generic OidcException prefixed 'OIDC Discovery Error: '. This is the user-facing wrapper for any discovery failure: transport errors, non-JSON discovery documents, issuer mismatch, or unusable JWKS (the appended message carries the underlying cause).","triggerScenarios":"Thrown during login, processAuthorizeResponse or logout whenever config 'discover' is true and discoverFromIssuer() throws — i.e., the IdP's /.well-known/openid-configuration or jwks could not be fetched, parsed, or did not match the configured issuer.","commonSituations":"IdP outage or maintenance window; network/DNS/TLS issues from the BookStack host; wrong OIDC_ISSUER; stale cached bad discovery data; Keycloak realm renamed so the issuer no longer matches.","solutions":["Read the text after 'OIDC Discovery Error: ' — it contains the underlying OidcIssuerDiscoveryException cause; apply the matching fix (network, issuer mismatch, JSON, JWKS).","Verify OIDC_ISSUER matches the IdP's advertised issuer exactly and the discovery URL returns valid JSON from the BookStack host.","Clear the 'oidc-discovery::<issuer>' cache entry (php artisan cache:clear or targeted delete) and retry.","If the IdP is temporarily down, wait for recovery or temporarily disable OIDC login and use another auth method.","Confirm HTTPS reachability and CA trust from the server (curl the discovery URL)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight: issuer must be https and discovery doc fetchable\n$issuer = config('oidc.issuer');\nif (!str_starts_with($issuer ?? '', 'https://')) throw new RuntimeException('bad issuer');\n$resp = (new \\GuzzleHttp\\Client(['timeout' => 5]))->get(rtrim($issuer, '/') . '/.well-known/openid-configuration');\njson_decode($resp->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);","typeGuard":null,"tryCatchPattern":"try {\n    // login / processAuthorizeResponse / logout\n} catch (OidcException $e) {\n    if (str_starts_with($e->getMessage(), 'OIDC Discovery Error:')) {\n        Log::error($e->getMessage()); // suffix names the root cause: network, JSON, issuer mismatch or JWKS\n        abort(503, 'Identity provider discovery is currently unavailable.');\n    }\n    throw $e;\n}","preventionTips":["Always log the full message — everything after 'OIDC Discovery Error: ' identifies the root cause.","Pre-flight the discovery URL from the app host in deployment checks.","Keep a fallback auth path (e.g. local login) when the IdP is unreachable.","Clear oidc-discovery cache entries after IdP or issuer config changes."],"tags":["discovery","oidc","network","configuration"],"backgroundTag":"oidc-discovery-failed","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}