This guide is written by the team that builds Casdoor and describes the standards as published (listed under Sources), with notes on how Casdoor implements them as of November 3, 2026. Spotted a mistake? Tell us.
OIDC discovery is the document a client fetches before it knows anything else about an OpenID Provider. From one URL, the client learns where to send the user, where to exchange the code, where to get the signing keys, which algorithms and grant types are supported, and which optional features the server implements.
In most integrations, a single wrong value in this document produces an error that looks unrelated: "issuer mismatch", "invalid signature", "unsupported response type", or a login loop. Knowing what the document should contain makes those errors much faster to diagnose.
The URL
The standard location is:
{issuer}/.well-known/openid-configuration
For https://id.example.com, that is https://id.example.com/.well-known/openid-configuration.
Two details trip people up:
- A path-based issuer is not simple concatenation. OpenID Connect Discovery says to append the suffix to the issuer. RFC 8414, the OAuth metadata specification, says to insert
/.well-known/openid-configurationbetween the host and the path. A server athttps://example.com/tenantmay therefore answer at either/tenant/.well-known/openid-configurationor/.well-known/openid-configuration/tenant. If one form 404s, try the other, and check the server's documentation. - The document must be JSON, served directly. A redirect or an HTML page returned with status 200 is not a discovery document. SPAs and reverse proxies that rewrite unknown paths to
index.htmlare a common cause of "the client says the provider is not OIDC".
Required fields
OpenID Connect Discovery lists these as required:
issuer— the issuer identifier, an HTTPS URL with no query or fragment.authorization_endpoint— where the browser is sent to authenticate.token_endpoint— where the code or refresh token is exchanged.jwks_uri— where the signing keys are published.response_types_supported— for examplecode, orcode id_token.subject_types_supported— almost alwayspublic.id_token_signing_alg_values_supported— for exampleRS256,ES256.
A document missing any of these is invalid, even if one particular client happens to tolerate the gap.
Fields clients actually rely on
Beyond the required set, these decide whether a feature works:
| Field | What it controls |
|---|---|
userinfo_endpoint |
Where the client fetches profile claims |
scopes_supported |
Which scopes the client may request |
claims_supported |
Which claims the provider may return |
grant_types_supported |
Whether device code, client credentials, token exchange and refresh tokens are available |
token_endpoint_auth_methods_supported |
Whether the client may use client_secret_basic, client_secret_post, private_key_jwt or none |
code_challenge_methods_supported |
Whether PKCE is available, and whether S256 is supported |
end_session_endpoint |
Whether RP-initiated logout can work |
backchannel_logout_supported |
Whether the provider can push logout events to the client |
authorization_response_iss_parameter_supported |
Whether the authorization response carries iss (RFC 9207) |
registration_endpoint |
Whether dynamic client registration is available |
client_id_metadata_document_supported |
Whether URL-based client IDs (CIMD) are accepted |
The last few matter more than they used to. MCP clients and AI-agent connectors read discovery to decide whether they can register themselves, whether they can use PKCE, and how logout should be performed.
The issuer rule
The single most common discovery failure is an issuer mismatch. The rules:
- The
issuervalue must exactly match theissclaim inside the ID token. Not "same host", not "same after normalization" — the same string. - A trailing slash is a different issuer. So is
httpversushttps, a different port, or a hostname that resolves to the same server. - The issuer must not contain a query string or a fragment.
- The discovery response must not redirect. Clients generally refuse a 3xx here, because a redirect makes it easy to swap the metadata.
- HTTPS is required for OIDC. Development setups often use plain HTTP on localhost; production clients should not.
Behind a reverse proxy, the issuer is usually built from the request's host and scheme. If the proxy forwards http internally, or rewrites the Host header, the document can advertise an issuer that no client can reach. Check the document from the public internet, not from inside the cluster.
Common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| 404 on the discovery URL | Wrong path, or a path-based issuer built the other way | Try both documented forms |
| 200 with HTML | SPA fallback, proxy rewrite, or a catch-all route | Serve the JSON before the fallback |
| "Issuer mismatch" | Issuer differs by slash, scheme, port or host | Make the public issuer exact everywhere |
| Keys not found | jwks_uri points at an internal host, or the keys rotated |
Fetch jwks_uri from the same network as the client |
| "Unsupported response type" | Client asks for a flow the document does not list | Enable the grant, or change the client |
| Login loops after logout | end_session_endpoint missing, or the client ignores it |
Check the logout flow explicitly |
| PKCE rejected | code_challenge_methods_supported lacks S256, or the client sends plain |
Enable S256 and update the client |
Caching and migrations
Clients cache discovery metadata, sometimes for hours, sometimes for the life of the process. After a domain migration or an endpoint change:
- Serve a short
Cache-Controlduring the transition, then lengthen it once stable. - Keep the old issuer reachable long enough for cached clients to refresh.
- Check that the ID token's
issand the discoveryissuermoved together. A new domain with an old issuer inside the token is worse than no migration at all.
Security notes
- Do not let an arbitrary user-supplied URL drive server-side discovery fetches. That is an SSRF primitive. Allowlist the issuers you trust.
- Validate
issagainst the configured issuer, not against whatever the response says. - Fetch and pin the signing keys over TLS, and handle key rotation by refreshing
jwks_urion an unknownkid.
Discovery in Casdoor
Casdoor serves discovery at https://<your-casdoor-host>/.well-known/openid-configuration. The issuer is the deployment origin (or the configured origin), and the document includes:
- Authorization, token, userinfo, introspection, revocation and device authorization endpoints.
registration_endpointat/api/oauth/registerfor dynamic client registration.code_challenge_methods_supported: ["S256"]— noplain.end_session_endpoint,backchannel_logout_supported: trueandbackchannel_logout_session_supported: truefor logout.authorization_response_iss_parameter_supported: truefor RFC 9207.client_id_metadata_document_supported, which follows the organization's dynamic client registration setting.
You can fetch the live document from the demo at https://door.casdoor.com/.well-known/openid-configuration and compare it with your own deployment. If your Casdoor sits behind a proxy, make sure the document's issuer matches the URL your clients use. Casdoor is open source, and Casdoor Cloud starts at $6.67/month billed yearly for a dedicated instance.
FAQ
Do I need discovery if I already know the endpoints? No, but most clients and SDKs use it, and MCP and AI-agent connectors increasingly require it. Serving a correct document is cheaper than supporting every client's manual configuration.
Why does the client say the issuer is wrong when the login works?
The browser flow can succeed with a loosely configured endpoint while ID token validation still compares iss with the configured issuer. Both must be the same string.
Should discovery be public? Yes. It contains no secrets; it is meant to be readable by any client. Keep the endpoints behind TLS, but do not require authentication for the metadata.
What if my IdP supports both OIDC discovery and OAuth metadata?
They can coexist. OIDC clients read /.well-known/openid-configuration; pure OAuth clients may read /.well-known/oauth-authorization-server. Keep the shared values consistent.
Sources
- OpenID Connect Discovery 1.0
- RFC 8414: OAuth 2.0 Authorization Server Metadata
- RFC 9207: Authorization Server Issuer Identification
- OpenID Connect Core 1.0
- Casdoor OIDC documentation
Product names are trademarks of their respective owners.