Client ID Metadata Documents
CAS can accept OAuth and OpenID Connect clients that it has never seen before and that identify themselves with
a client ID metadata document: the
client_id is an HTTPS URL, and the JSON document published at that URL describes the client. This is how
MCP clients connect to servers they have no prior
relationship with, and the MCP authorization specification recommends it over dynamic client registration.
Support is turned off by default and is enabled and tuned through CAS settings. When it is enabled, the discovery document
advertises client_id_metadata_document_supported.
The following settings and properties are available from the CAS configuration catalog:
cas.authn.oidc.registration.client-id-metadata-document.enabled
falsecas.authn.oidc.registration.client-id-metadata-document.maximum-cache-duration
PT24Hcas.authn.oidc.registration.client-id-metadata-document.maximum-clients
1000cas.authn.oidc.registration.client-id-metadata-document.minimum-cache-duration
PT5Mcas.authn.oidc.registration.client-id-metadata-document.retention
P30Dcas.authn.oidc.registration.client-id-metadata-document.timeout
PT5SRequired settings may be needed to activate or affect the feature; review them even when they have a default. Optional settings only need to be set to change a default or to turn on the behavior they control. Third party settings belong to libraries such as Spring Boot that CAS builds on; their own documentation may have more detail.
Notes on configuration
Configuration Metadata
The collection of configuration properties listed in this section are automatically generated from the CAS source and components that contain the actual field definitions, types, descriptions, modules, etc. This metadata may not always be 100% accurate, or could be lacking details and sufficient explanations.
Be Selective
This section is meant as a guide only. Do NOT copy/paste the entire collection of settings into your CAS configuration; rather pick only the properties that you need. Do NOT enable settings unless you are certain of their purpose and do NOT copy settings into your configuration only to keep them as reference. All these ideas lead to upgrade headaches, maintenance nightmares and premature aging.
YAGNI
Note that for nearly ALL use cases, declaring and configuring properties listed here is sufficient. You should NOT have to explicitly massage a CAS XML/Java/etc configuration file to design an authentication handler, create attribute release policies, etc. CAS at runtime will auto-configure all required changes for you. If you are unsure about the meaning of a given CAS setting, do NOT turn it on without hesitation. Review the codebase or better yet, ask questions to clarify the intended behavior.
Naming Convention
Property names can be specified in very relaxed terms. For instance cas.someProperty, cas.some-property, cas.some_property are all valid names. While all
forms are accepted by CAS, there are certain components (in CAS and other frameworks used) whose activation at runtime is conditional on a property value, where
this property is required to have been specified in CAS configuration using kebab case. This is both true for properties that are owned by CAS as well as those
that might be presented to the system via an external library or framework such as Spring Boot, etc.
When possible, properties should be stored in lower-case kebab format, such as cas.property-name=value.
The only possible exception to this rule is when naming actuator endpoints; The name of the
actuator endpoints (i.e. ssoSessions) MUST remain in camelCase mode.
Settings and properties that are controlled by the CAS platform directly always begin with the prefix cas. All other settings are controlled and provided
to CAS via other underlying frameworks and may have their own schemas and syntax. BE CAREFUL with
the distinction. Unrecognized properties are rejected by CAS and/or frameworks upon which CAS depends. This means if you somehow misspell a property definition
or fail to adhere to the dot-notation syntax and such, your setting is entirely refused by CAS and likely the feature it controls will never be activated in the
way you intend.
Validation
Configuration properties are automatically validated on CAS startup to report issues with configuration binding, especially if defined CAS settings cannot be recognized or validated by the configuration schema. Additional validation processes are also handled via Configuration Metadata and property migrations applied automatically on startup by Spring Boot and family.
Indexed Settings
CAS settings able to accept multiple values are typically documented with an index, such as cas.some.setting[0]=value. The index [0] is meant to be
incremented by the adopter to allow for distinct multiple configuration blocks.
An example document, published at https://app.example.org/oauth/client.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"client_id": "https://app.example.org/oauth/client.json",
"client_name": "Example MCP Client",
"client_uri": "https://app.example.org",
"logo_uri": "https://app.example.org/logo.png",
"redirect_uris": [
"http://127.0.0.1:3000/callback",
"https://app.example.org/callback"
],
"grant_types": [
"authorization_code",
"refresh_token"
],
"response_types": [
"code"
],
"token_endpoint_auth_method": "none"
}
How CAS Uses The Document
When a request to an OpenID Connect endpoint names a client_id that is an HTTPS URL, CAS fetches the document,
checks it and registers the client in the service registry, the same way a dynamically registered client is registered.
The client is then an ordinary public client of CAS: it must use PKCE, and its redirect URIs are matched exactly.
- The client id must use
https, contain a path, and carry no user information, query, fragment or dot segments. - The document’s
client_idmust be identical to the URL, and it must carryclient_nameandredirect_uris. - Redirect URIs must use
https, orhttponlocalhost,127.0.0.1or[::1], and have no fragment. - The client may not use a shared secret:
token_endpoint_auth_methodisnone, its default, orprivate_key_jwtwith keys published inline injwks.client_secretandclient_secret_expires_atare refused. - Only the
authorization_codeandrefresh_tokengrants and thecoderesponse type are accepted. - Metadata that would make CAS call URLs chosen by the client from the server side is refused:
jwks_uri,sector_identifier_uri,backchannel_logout_uri,frontchannel_logout_uri,initiate_login_uri,request_urisand the CIBA notification endpoint. Post-logout redirect URIs are ignored.
These clients are evaluated after every other registered service, so they never take precedence over an application an administrator defined. A registered client whose client id happens to be a URL, but that was not registered from a document, is left alone.
Fetching Documents
Documents are fetched with the following protections:
- The host is resolved once, and every address it resolves to must be public. Loopback, private, link-local, carrier-grade NAT, unique local, multicast, documentation and reserved addresses are always refused, and the connection is made to the addresses that were checked.
- Redirects are not followed, only
200responses with a JSON body are accepted, and documents larger than 5 KB are refused. - The request has a timeout, and TLS follows the CAS HTTP client settings, such as its trust store.
An outbound HTTP proxy configured for the CAS server resolves the host itself, so the address checks no longer apply to the connection it makes. Do not route these requests through such a proxy.
Refresh And Cleanup
CAS uses a fetched document for as long as its Cache-Control header allows, within the bounds defined in CAS settings,
and fetches it again on the next request after that. If the document cannot be fetched again, CAS keeps using the last
valid one. Each successful fetch moves the expiration of the client to the retention period from then; clients that are
not used for that long expire and are removed from the service registry. The number of clients registered from
documents is capped, and new ones are refused once the cap is reached.
Consent
Nobody has reviewed these clients, so CAS always asks for consent, even when consent would otherwise be bypassed for the application or globally. The consent screen shows the host of the client id and the host the person is sent back to, next to the name the client chose for itself, and warns when that host is on the person’s own computer, since any program running there could claim such an address.