Discovery document
GET /.well-known/openid-configuration returns the OpenID Connect discovery document, which client libraries use to find the endpoints and public keys. This page shows the observed output of v0.1.4, explains where each field comes from, and lists known issues you need to address yourself.
Observed output
Below is the actual response from the Quick start example (which registers only one API scope, orders.read, and one RS256 signing key, with everything else at defaults), with keys sorted alphabetically:
{
"authorization_endpoint": "http://localhost:5000/connect/authorize",
"authorization_response_iss_parameter_supported": true,
"backchannel_authentication_endpoint": "http://localhost:5000/connect/ciba",
"backchannel_logout_session_supported": true,
"backchannel_logout_supported": true,
"backchannel_token_delivery_modes_supported": ["poll"],
"backchannel_user_code_parameter_supported": true,
"check_session_iframe": "http://localhost:5000/connect/checksession",
"claims._supported": [],
"code_challenge_methods_supported": ["plain", "S256"],
"device_authorization_endpoint": "http://localhost:5000/connect/deviceauthorization",
"end_session_endpoint": "http://localhost:5000/connect/endsession",
"frontchannel_logout_session_supported": true,
"frontchannel_logout_supported": true,
"grant_types_supported": [
"authorization_code", "client_credentials", "refresh_token", "implicit",
"urn:ietf:params:oauth:grant-type:device_code", "urn:openid:params:grant-type:ciba"
],
"id_token_signing_alg_values_supported": ["RS256"],
"introspection_endpoint": "http://localhost:5000/connect/introspect",
"issuer": "http://localhost:5000",
"jwks_uri": "http://localhost:5000/.well-known/openid-configuration/jwks",
"request_object_signing_alg_values_supported": [
"RS256", "RS384", "RS512", "PS256", "PS384", "PS512",
"ES256", "ES384", "ES512", "HS256", "HS384", "HS512"
],
"request_parameter_supported": true,
"response_modes_supported": ["form_post", "query", "fragment"],
"response_types_supported": [
"code", "token", "id_token", "id_token token",
"code id_token", "code token", "code id_token token"
],
"revocation_endpoint": "http://localhost:5000/connect/revocation",
"scopes_supported": ["orders.read", "offline_access"],
"subject_types_supported": ["public"],
"token_endpoint": "http://localhost:5000/connect/token",
"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"],
"userinfo_endpoint": "http://localhost:5000/connect/userinfo"
}The corresponding JWKS (/.well-known/openid-configuration/jwks) looks like {"keys":[{"alg":"RS256","e":"AQAB","kid":"...","kty":"RSA","n":"..."}]}. Every public key carries a kid: when a validation key doesn't specify one, Wicket generates it automatically from the RFC 7638 thumbprint.
Known issues
1. Key name claims._supported
The standard field name is claims_supported, but v0.1.4 outputs claims._supported (the value of the DiscoveryClaimsSupported constant in constants.go has an extra dot; the claims._parameter_supported and claims._locales_supported constants in the same file have the same problem, though they aren't currently output). Clients that rely on claims_supported will conclude that the server declares no claims.
Until this is fixed, you can set opts.Discovery.ShowClaims = false to remove the incorrect key. If clients really need claims_supported, you can add it yourself through CustomEntries, but you must maintain the list by hand; it won't update automatically with your resource configuration.
2. Unregistered endpoints are advertised
revocation_endpoint and device_authorization_endpoint appear in the document by default, but v0.1.4 doesn't handle these two paths (requests fall through to the host handler; see Protocol endpoints). Turn them off:
opts.Endpoints.EnableTokenRevocationEndpoint = false
opts.Endpoints.EnableDeviceAuthorizationEndpoint = false // also removes the device_code grant type advertisement3. Endpoint URLs are taken from the request itself
Except for issuer, all URLs are built from the current request: the scheme depends on whether r.TLS is nil, and the host comes from the Host header. v0.1.4 doesn't read X-Forwarded-Proto / X-Forwarded-Host. Behind a TLS-terminating reverse proxy, the endpoints in the document become http://...; have the proxy pass through the original Host, and request the discovery document once before going live to confirm. issuer is unaffected as long as opts.IssuerUri is set.
Field reference
| Field | Source / controlling switch |
|---|---|
issuer | opts.IssuerUri (trailing / removed); when unset, the request's origin. Always set it explicitly in production |
jwks_uri | Present when Discovery.ShowKeySet is on and there's at least one validation key |
*_endpoint, check_session_iframe | The Discovery.ShowEndpoints master switch + the per-endpoint Endpoints.Enable*Endpoint switches |
mtls_endpoint_aliases | Only when MutualTls.Enabled=true; v0.1.4 doesn't implement mTLS, so don't turn it on |
frontchannel_logout_*, backchannel_logout_* | All four are true when Endpoints.EnableEndSessionEndpoint is true. Note that backchannel logout notification in v0.1.4 is a no-op implementation and doesn't actually send anything (see ServerConfig) |
scopes_supported | ShowIdentityScopes: identity resources with ShowInDiscoveryDocument=true; ShowApiScopes: API scopes meeting the same condition, with offline_access always appended |
claims._supported | ShowClaims: the deduplicated union of the UserClaims of the visible resources above (see known issue 1) |
grant_types_supported | ShowGrantTypes. Always includes authorization_code, client_credentials, refresh_token, implicit; password appears only when a custom ResourceOwnerPasswordValidator is injected; device authorization and CIBA appear according to their respective endpoint switches |
response_types_supported / response_modes_supported | ShowResponseTypes / ShowResponseModes; fixed contents |
token_endpoint_auth_methods_supported | ShowTokenEndpointAuthenticationMethods; taken from the registered secret parsers (basic, post) |
id_token_signing_alg_values_supported | Deduplicated algorithms of all current signing credentials; absent when there are no signing credentials |
subject_types_supported | Always ["public"] |
code_challenge_methods_supported | Always ["plain","S256"]; plain additionally requires the client to have AllowPlainTextPkce=true |
request_parameter_supported, request_object_signing_alg_values_supported | Always output when the authorization endpoint is enabled |
request_uri_parameter_supported | Present when Endpoints.EnableJwtRequestUri=true (default false) |
authorization_response_iss_parameter_supported | Always true |
backchannel_token_delivery_modes_supported, backchannel_user_code_parameter_supported | When the CIBA endpoint is enabled; taken from opts.BackchannelAuthentication |
DiscoveryOptions
All fields of opts.Discovery (config/options/discovery_options.go):
| Field | Default | Effect |
|---|---|---|
ShowEndpoints | true | Whether to output endpoint URLs |
ShowKeySet | true | Whether to output jwks_uri; when false, the JWKS endpoint itself also returns 404 |
ShowIdentityScopes | true | Whether scopes_supported includes identity resources |
ShowApiScopes | true | Whether scopes_supported includes API scopes (and offline_access) |
ShowClaims | true | Whether to output the claim list |
ShowResponseTypes | true | Whether to output response_types_supported |
ShowResponseModes | true | Whether to output response_modes_supported |
ShowGrantTypes | true | Whether to output grant_types_supported |
ShowExtensionGrantTypes | true | Whether to merge extension grant types into the previous item |
ShowTokenEndpointAuthenticationMethods | true | Whether to output client authentication methods |
CustomEntries | Empty map | Appends custom keys; a key that clashes with an existing one doesn't overwrite it, and only an error log entry is written |
ExpandRelativePathsInCustomEntries | true | Expands strings in CustomEntries that start with ~/ into absolute URLs |
ResponseCacheInterval | nil | When non-nil and ≥ 0, outputs Cache-Control: max-age=<seconds> and Vary: Origin; when nil, no cache headers are set |
To turn off the whole discovery endpoint, use opts.Endpoints.EnableDiscoveryEndpoint = false (both the discovery document and JWKS return 404).
Example
The configuration below has been compiled and tested on the Quick start example: it removes the two unregistered endpoints and the incorrect claims key, and adds cache headers and one custom entry.
opts := godi.GetRequired[*options.WicketOptions](root)
opts.IssuerUri = "https://id.example.com"
opts.Endpoints.EnableTokenRevocationEndpoint = false
opts.Endpoints.EnableDeviceAuthorizationEndpoint = false
opts.Discovery.ShowClaims = false
maxAge := 3600
opts.Discovery.ResponseCacheInterval = &maxAge
opts.Discovery.CustomEntries["service_documentation"] = "~/docs"Observed result: the response headers include Cache-Control: max-age=3600 and Vary: Origin; revocation_endpoint, device_authorization_endpoint, and claims._supported are gone; grant_types_supported no longer contains device_code; and "service_documentation": "http://<current host>/docs" is added.