Discovery
Clients learn the OP's endpoints, signing keys, and capabilities by fetching one JSON document. For an OIDC OP that document is defined by OIDC Discovery 1.0 and lives at /.well-known/openid-configuration. RFC 8414 (OAuth Authorization Server Metadata) defines the same idea for plain OAuth under /.well-known/oauth-authorization-server; this library serves only the openid-configuration document, and it carries the RFC 8414 members too. This page tours that document.
Specs referenced on this page
- OpenID Connect Discovery 1.0
- RFC 8414 — OAuth 2.0 Authorization Server Metadata
- RFC 9126 — Pushed Authorization Requests
- RFC 9449 — DPoP
- FAPI 2.0 Security Profile
Why this exists
Without a discovery document, every RP would hard-code the OP's endpoint URLs, signing algorithms and supported features, and every change on the OP would need a code change in every RP. With discovery, the RP only needs the issuer URL: https://op.example.com.
What's in the discovery document
Cache-Control: public, max-age=3600, so the RP asks again at most about once an hour.The table lists the fields a beginner will meet first. The library emits each one when the matching feature is configured. Endpoint URLs are absolute and sit under the mount prefix (/oidc by default), for example https://op.example.com/oidc/auth.
| Field | What it is |
|---|---|
issuer | The OP's canonical identifier. The same string appears as iss in every signed token. RPs compare it byte-for-byte. |
authorization_endpoint | URL of /auth — where the browser is redirected to log the user in. |
token_endpoint | URL of /token — where the RP exchanges a code or refresh token. |
userinfo_endpoint | URL of /userinfo — where the RP fetches fresh claims with an access token. |
jwks_uri | URL of the JWKS — the OP's public signing keys, published as a JWK Set. |
introspection_endpoint | URL of /introspect (RFC 7662) — present when the introspection feature is wired. |
revocation_endpoint | URL of /revoke (RFC 7009) — present when the revocation feature is wired. |
end_session_endpoint | URL of /end_session — where the RP redirects the browser for RP-Initiated Logout. Present only when the authorization endpoint is. |
backchannel_logout_supported | true whenever the authorization endpoint exists; the OP can send Back-Channel Logout tokens. |
registration_endpoint | URL of /register (RFC 7591) — present when op.WithDynamicRegistration(...) is wired. |
pushed_authorization_request_endpoint | URL of /par — present only when the PAR feature (RFC 9126) is enabled. |
device_authorization_endpoint | URL of /device_authorization — present only when the device-code grant is wired. |
backchannel_authentication_endpoint | URL of /bc-authorize — present only when the CIBA grant is wired. |
grant_types_supported | Grant types the OP accepts at /token: authorization_code, refresh_token, client_credentials, … |
response_types_supported | Response types the authorization endpoint accepts. Browser-capable configurations advertise only code (the OIDC Core "code flow"). A client-credentials-only OP emits an empty array because no authorization endpoint is mounted. |
response_modes_supported | How the authorization endpoint returns the result: query, form_post, plus query.jwt, fragment.jwt, form_post.jwt, jwt when JARM is enabled. |
authorization_response_iss_parameter_supported | Always true: every authorization response carries iss (RFC 9207). |
id_token_signing_alg_values_supported | JWS algorithms used to sign ID Tokens. The library publishes the one algorithm the OP signs with: ES256 by default, RS256 after op.WithSigningAlgorithm(op.AlgRS256). |
request_parameter_supported / request_uri_parameter_supported | true only when JAR is enabled; otherwise false. |
request_object_signing_alg_values_supported | JWS algorithms accepted on JAR request= parameters: RS256, PS256, ES256, EdDSA. FAPI profiles narrow it to PS256, ES256, EdDSA. Present only when JAR is enabled. |
token_endpoint_auth_methods_supported | How clients authenticate at /token. The default list includes client_secret_basic, client_secret_post, private_key_jwt, and none; FAPI profiles narrow it. The introspection and revocation auth-method lists intentionally omit none, because those endpoints require a confidential caller. With feature.MTLS enabled the lists also contain tls_client_auth and self_signed_tls_client_auth. mTLS endpoint metadata is advertised separately via mtls_endpoint_aliases. |
code_challenge_methods_supported | PKCE transformations. The library advertises only S256. |
subject_types_supported | public and (when op.WithPairwiseSubject(...) is wired) pairwise. |
claims_supported | Claims the OP can return. Omitted unless you pass op.WithClaimsSupported(...), because the library cannot know what your user store holds. |
scopes_supported | Public scopes: the standard OIDC scopes plus every scope registered with op.WithScope(...) as public. Private scopes are not listed. |
dpop_signing_alg_values_supported | Present only when the DPoP feature (RFC 9449) is enabled. |
require_pushed_authorization_requests | Present as true only under a profile that mandates PAR (the FAPI 2.0 profiles). |
acr_values_supported | The authentication context classes the OP accepts in acr_values. Present only when op.WithACRValuesSupported(...) is wired; op.New refuses an entry the ACR policy cannot resolve, so declare non-AAL values with op.WithACRPolicy. |
claims_parameter_supported | Defaults to true; pass op.WithClaimsParameterDisabled() to stop advertising and honoring OIDC §5.5 claims requests. |
authorization_details_types_supported | The RFC 9396 type values accepted in authorization_details. Present only when op.WithAuthorizationDetailTypes(...) is wired. |
grant_management_endpoint | The grant management endpoint URL. Present only when op.WithGrantManagement(...) is wired. |
grant_management_actions_supported | The grant management actions the OP accepts (create / replace / merge / query / revoke). Present with grant_management_endpoint. |
grant_management_action_required | Emitted as true only when WithGrantManagement(op.GrantManagement{..., ActionRequired: true}) — an authorization request must then carry grant_management_action. |
introspection_endpoint_auth_signing_alg_values_supported | JWS algorithms accepted on a client_assertion at /introspect. Present when the introspection feature is wired and the endpoint's auth-method list contains an assertion-based method (private_key_jwt). |
revocation_endpoint_auth_signing_alg_values_supported | JWS algorithms accepted on a client_assertion at /revoke. Present when the revocation feature is wired and the endpoint's auth-method list contains an assertion-based method (private_key_jwt). |
prompt_values_supported | The prompt values the authorization endpoint accepts: none, login, consent, select_account. create is added only when LoginFlow.Registration is set. |
authorization_grant_profiles_supported | urn:ietf:params:oauth:grant-profile:id-jag. Experimental: present only when at least one ID-JAG issuer is trusted (ID-JAG). The issuers themselves are never published. |
identity_chaining_requested_token_types_supported | urn:ietf:params:oauth:token-type:id-jag. Experimental: present only when op.WithIDJAGIssuance(...) is wired (ID-JAG). |
client_id_metadata_document_supported | true when op.WithClientIDMetadataDocuments(...) is wired, so an HTTPS client_id resolves to its metadata document. Experimental; omitted otherwise (MCP authorization server). |
When op.WithProtectedResources(...) is wired, the OP additionally serves RFC 9728 protected-resource metadata at /.well-known/oauth-protected-resource (one document per registered resource) — a separate well-known document, not a field on openid-configuration.
_supported fields are advertisements, not policy
A _supported list is what the OP will accept — not what every client must use. A client may use a subset. The OP rejects anything outside the list.
How clients use it
A typical RP SDK does the following on first start:
GET https://op.example.com/.well-known/openid-configuration- Cache the response, for at most the
max-agethe OP sends (3600 seconds). - Read endpoints, supported algorithms, and supported features from the cached document.
- Refetch when the cache expires, or when signature verification fails on an unknown
kid, which usually means the OP rotated its keys.
The library helps in two ways. The discovery document does not change between restarts of the same configuration, so RPs can cache it for a long time. During a key rotation, the embedder tells the library through op.WithJWKSRotationActive(predicate), and the JWKS endpoint switches from max-age=3600 to max-age=300, must-revalidate so RPs that refetch see the new key quickly.
The document is built once
The OP builds and marshals the document when the provider is created and serves the same JSON body for the provider's lifetime, so every instance with the same configuration returns identical bytes. Staleness is therefore an RP-side concern: see key rotation for how long an RP can keep using a cached JWKS.
How this library builds it
Discovery is constructed once at op.New from the wired feature set, so it cannot drift at runtime: if the embedder did not wire PAR, pushed_authorization_request_endpoint is absent and require_pushed_authorization_requests does not appear. If the embedder wired op.WithProfile(profile.FAPI2Baseline), the FAPI narrowing applies — token_endpoint_auth_methods_supported is filtered to the FAPI-permitted set, require_pushed_authorization_requests=true appears, and the introspection / revocation auth-method lists are copied from the same narrowed list with none removed. The authorization endpoint and its browser-only metadata are emitted only when a configured grant needs the browser authorization flow. A client_credentials-only OP therefore omits authorization_endpoint, end_session_endpoint, and backchannel_logout_supported, while retaining response_types_supported: [].
WithDiscoveryMetadata(DiscoveryMetadata{UILocalesSupported: ...}) is also a construction-time contract: every explicitly advertised locale must be served by the registered locale resolver. Advertising an unserved locale makes op.New fail instead of producing discovery metadata that the UI cannot honor.
Golden tests pin the document shape for each profile, so what discovery says and what the handlers do cannot diverge unnoticed. See design judgment #12 for the rationale.
The document is served at /.well-known/openid-configuration, outside the mount prefix. For an issuer with a path, the same document is also served at the issuer-relative path; see Issuer.
What the library does NOT advertise
The library narrows the discovery document deliberately:
- No
nonealg.id_token_signing_alg_values_supportedandrequest_object_signing_alg_values_supportednever containnone. This is separate from thenoneclient-authentication method listed for/token;noneis never a signing algorithm (see JOSE basics and design judgment #11). - No HMAC-family alg for ID Tokens.
HS256/HS384/HS512are not advertised. The alg-confusion attack class needs them to be reachable, so the library never makes them reachable. - No request-object support unless JAR is wired. Without JAR,
request_parameter_supportedandrequest_uri_parameter_supportedarefalseand the request-object algorithm lists are absent.pushed_authorization_request_endpointappears only when PAR is wired. claims_parameter_supporteddefaults totrue, but can be disabled. Passingop.WithClaimsParameterDisabled()makes the discovery document omit OIDC §5.5 support and makes authorize / PAR ignoreclaimspayloads after malformed JSON has been rejected.- No
frontchannel_logout_supportedorcheck_session_iframe. Front-Channel Logout 1.0 / Session Management 1.0 are not implemented; the discovery document is silent about them. Embedders use Back-Channel Logout 1.0 instead — see design judgment #5.
Discovery is a contract surface
Every _supported array is a commitment to accept those values. Adding a value widens the contract and removing one narrows it, and an RP may refuse to talk to an OP that stops advertising an algorithm it requires. Treat changes to the discovery document like changes to a public API.
Read next
- Operations: JWKS — what the JWK Set looks like and how the library serves it.
- Operations: key rotation — how the OP rotates signing keys without breaking RP caches.
- Reference: options — every
op.With...option that surfaces in the discovery document.