OAuth Client Registration | Static and CIMD

On this page

Before an OAuth client can request tokens, the authorization server needs a record of it, including which redirect URLs the client may use. That record is the client's registration.

FusionAuth supports two ways to register a client:

  • Static registration, where you create an Application for the client ahead of time.
  • Client ID Metadata Documents (CIMD), where the client describes itself in a document it hosts, and FusionAuth registers it the first time it shows up.

Static Registration#

With static registration, you create an Application in FusionAuth for each client. The Application Id becomes the client's client_id. You configure everything else on the Application: redirect URLs, enabled grants, client authentication, roles, and scopes.

Use static registration when you know your clients in advance, such as your own apps and services.

Someone has to create the Application before the client can log in. That doesn't work for software you don't control and can't predict, like an AI chat app connecting to your MCP server on behalf of a user.

Client ID Metadata Documents#

Enterprise plan required

This feature requires an Enterprise plan.

Available since 1.70.0

With CIMD, the client_id is an HTTPS URL, such as https://chatgpt.com/oauth/client.json. The client hosts a JSON document at that URL describing itself, including its name and redirect URIs. CIMD is defined in draft-ietf-oauth-client-id-metadata-document, and the MCP authorization spec uses it for client registration.

You don't register CIMD clients one at a time. Instead, you tell FusionAuth which origins to trust by creating a CIMD domain for each one, for example https://chatgpt.com. You can configure scopes, consent, resource URIs, and lambdas for each domain.

How A CIMD Client Gets Registered#

  1. The client starts the Authorization Code grant, using its document URL as the client_id. The request must go to the Tenant's endpoints, which end with the Tenant Id, such as https://<host>/oauth2/authorize/<tenantId>, and include exactly one resource parameter, such as the URL of your MCP server.
  2. FusionAuth checks that the URL matches a CIMD domain in the Tenant. If nothing matches, the request fails.
  3. The user logs in.
  4. FusionAuth fetches the document, validates it, and registers the client. If the domain has a registration lambda, the lambda can reject the client or change its registration.
  5. The user consents to the requested scopes. CIMD clients are always treated as third-party clients, so FusionAuth always asks for consent at least once, even when the request includes no scopes. The consent page shows the client's client_name, its client_uri if provided, and the host where its document is hosted, so the user can tell which client they're connecting.
  6. FusionAuth redirects back to the client with an authorization code, and the client exchanges it for tokens.

The resource must be one of the domain's Authorized resource URIs, or FusionAuth rejects the request with invalid_target. The aud claim of both the access token and the Id token contains two values: the client's client_id URL and the resource.

FusionAuth caches the document. Until the cached copy expires, later logins from the same client reuse the registration without fetching the document again. The domain's cache settings control how long that is, as described in CIMD Registration Caching And Lifecycle. After the cached copy expires, the next login fetches the document again. Access and refresh tokens the client already holds keep working after the cached copy expires.

Removing A CIMD Client#

FusionAuth has no admin UI for removing a single CIMD client. There are three ways to remove access:

  • Delete the client's registration with the Delete a CIMD Client Registration API. FusionAuth deletes the registration and its refresh tokens immediately. To find the registration Id, search for the registration by its client_id URL.
  • Set decision to REVOKE in the domain's registration lambda. FusionAuth deletes the client's registration and refresh tokens the next time the lambda runs for that client. The lambda runs when a user logs in after the client's cached document expires, or when the client requests a resource it hasn't used before.
  • Delete the CIMD domain. This removes every client registered through the domain, along with their refresh tokens.

Deleting a registration doesn't block the client. The next time a user logs in with that client, FusionAuth registers it again. To keep a client out, also set decision to DENY for it in the registration lambda. A DENY decision on its own blocks new logins but leaves existing refresh tokens working.

Monitoring CIMD Clients#

To see which clients have registered, use the Search for CIMD Client Registrations API. Each registration shows the client's metadata, the scope decisions for each resource it has used, and whether its cached document is Active, in its Grace period, or Expired.

FusionAuth sends a CIMD Registration Success event when it registers a client or updates a registration, and a CIMD Registration Failed event when it can't. Every failure also writes an Error entry to the Event Log. A rate limited request also writes an Information entry. With Enable debug logging on the CIMD domain, FusionAuth writes a Debug entry when it creates a registration, refreshes one after its cache expires, or adds a new resource to an existing one.

Logins through a CIMD client appear in login records and login reports under the CIMD domain's Id as the applicationId, even though the user has no registration for an Application with that Id. FusionAuth records these logins against the domain's backing Application, whose Id matches the CIMD domain's Id. They roll up into the aggregated login data that the Report APIs use. The User Login Success and User Login Failed events work differently: they leave out applicationId and include the CIMD domain's Id as cimdDomainId.

What CIMD Clients Can't Do#

CIMD clients are public clients. They authenticate with PKCE instead of a client secret, and they can only use the authorization_code and refresh_token grants. See Fixed OAuth Behavior for the full list of restrictions.

FusionAuth reads only client_id, client_name, client_uri, and redirect_uris from the document, and ignores every other field. A scope value in the document has no effect, so a CIMD client can only request the scopes enabled on its domain. FusionAuth also doesn't fetch logo_uri.

A CIMD client's access token can't authenticate the FusionAuth APIs that accept a user's JWT in place of an API key, such as the Login API, the JWT issue and refresh APIs, the Change Password API, and the two-factor APIs. Use the token with your own resource server, the Userinfo endpoint, or the Introspect endpoint instead.

FusionAuth recognizes a CIMD client's token by its aud claim, which is always exactly ["<client_id URL>", "<resource>"]. Don't change aud in a JWT populate lambda for a CIMD domain, because FusionAuth won't recognize the token as a CIMD token.

Limitations#

  • CIMD works with every identity provider type except SAML v2 IdP-initiated login. IdP-initiated SAML login doesn't work with CIMD clients.
  • An identity provider can't create user registrations for a CIMD domain.
  • A CIMD domain's Id isn't a valid client_id. FusionAuth rejects it with an invalid_client error. A CIMD client must use the URL of its metadata document.

For more information, see Identity Providers and CIMD Domains: Fixed OAuth Behavior.

Dynamic Client Registration#

Dynamic Client Registration (DCR) is an older way to solve the same problem. Under DCR, the client calls a registration endpoint on the authorization server, and the server creates and stores a new client record for every caller. FusionAuth doesn't support DCR; you can follow GitHub issue #1125 for updates. CIMD covers the MCP use case with less stored state, since the client's metadata stays on the client's own server.

Choosing An Approach#

Static registration CIMD
Who registers the client You, before the client logs in FusionAuth, the first time the client logs in
client_id The Application Id The URL of the client's metadata document
Where the client's metadata lives The Application The client's document, cached by FusionAuth
What you configure One Application per client One CIMD domain per trusted origin
Client authentication Client secret or none, with or without PKCE None. PKCE is required
Grants Any grant FusionAuth supports authorization_code and refresh_token
Consent Configurable, including skipping it for first-party apps Always prompts at least once
Removing access Delete or deactivate the Application Delete the CIMD domain, or revoke the client with a registration lambda

Use static registration for clients you know about. Use CIMD when clients you don't know in advance need to log in, such as MCP clients like ChatGPT and claude.ai connecting to your MCP server.

Next Steps#