# Host A Client ID Metadata Document (CIMD)

Publish a Client ID Metadata Document so your OAuth client can log in to FusionAuth without being registered ahead of time.

> For the index of this section of the site, see [llms.txt](https://fusionauth.io/docs/llms.txt)

> **PLAN:** This feature requires [an Enterprise plan](https://fusionauth.io/docs/get-started/core-concepts/plans-features.md#enterprise-features).

Available since `1.70.0`

This page shows how to publish a Client ID Metadata Document (CIMD) for an OAuth client you build, such as an MCP client or an AI agent. FusionAuth fetches the document the first time your client logs in and registers the client from it. For background, see [OAuth Client Registration](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/client-registration.md).

Before you start, the FusionAuth Tenant your client logs in to needs a [CIMD domain](https://fusionauth.io/docs/get-started/core-concepts/types/cimd-domains.md) that matches the origin of your document URL, or the `*` domain.

## Publish The Document

1.  Choose the URL for the document. This URL becomes your client's `client_id`. It must:
    
    *   use `https`
    *   have a path other than `/`, such as `/oauth/client.json`
    *   contain no fragment or query parameters
    *   be at most 2048 characters long
    *   resolve to a public IP address. FusionAuth won't fetch from private, loopback or link-local addresses.
2.  Write the document. FusionAuth reads these fields:
    
    | Field | Required | Description |
    | --- | --- | --- |
    | `client_id` | Yes | The document's own URL, exactly as your client sends it. |
    | `client_name` | Yes | The name users see on the consent screen. |
    | `redirect_uris` | Yes | At least one absolute redirect URI. Every entry must be valid, or FusionAuth rejects the whole document. Wildcards aren't allowed. Custom schemes, such as `com.example.app:/callback`, are allowed. For an `http` URI on a loopback IP address (`127.0.0.1` or `[::1]`), FusionAuth accepts any port at login, as described in [RFC 8252 Section 7.3](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3). A `localhost` URI only works when the CIMD domain enables **Allow localhost redirect URIs**. When it does, FusionAuth also accepts any port for an `http` `localhost` URI. |
    | `client_uri` | No | A URL for your client's home page, shown on the consent screen. |
    
    FusionAuth ignores every other field. Your client's scopes come from the MCP server's metadata, but must match the CIMD domain's allowed values. A `scope` value in the document has no effect: FusionAuth treats every CIMD client as a public client that uses PKCE, regardless of `token_endpoint_auth_method`.
    
    https://app.example.com/oauth/client.json
    
    ```json
    {
      "client_id": "https://app.example.com/oauth/client.json",
      "client_name": "Example Agent",
      "client_uri": "https://app.example.com",
      "redirect_uris": [
        "https://app.example.com/oauth/callback",
        "http://127.0.0.1:3334/callback"
      ]
    }
    ```
    
3.  Serve the document at the URL. FusionAuth needs a `2xx` response of at most 5KB. It waits up to 2 seconds to connect and 10 seconds for the response, and it doesn't follow redirects. FusionAuth doesn't check the content type, but `application/json` is a good choice. For more on how FusionAuth protects this fetch, see [CIMD Security](https://fusionauth.io/docs/operate/secure/cimd-security.md).
    
4.  Set a `Cache-Control: max-age` header to control how long FusionAuth caches the document. FusionAuth uses the smaller of your `max-age` and the domain's **Maximum cache duration**, and never caches for less than 15 minutes. Without a `max-age`, FusionAuth caches the document for 15 minutes. FusionAuth ignores the `Expires` header.
    
5.  Check the response:
    
    ```shell-session
    $ curl -i https://app.example.com/oauth/client.json
    ```
    
    You should get a `200` with no redirect, and the `client_id` in the body must match the URL you requested character for character. Even a trailing slash counts as a mismatch.
    

## Log In With The Document

Start the Authorization Code grant from your client with the document URL as the `client_id`:

*   Use the Tenant's endpoints, which end with the Tenant Id, such as `https://<host>/oauth2/authorize/<tenantId>` and `https://<host>/oauth2/token/<tenantId>`. You can find them in the Tenant's `https://<host>/.well-known/openid-configuration/<tenantId>` document, which reports `"client_id_metadata_document_supported": true` once CIMD is set up.
*   Send a PKCE `code_challenge` with the `S256` method.
*   Send exactly one `resource` parameter on both the authorization request and the token request. For an MCP client, this is the URL of the MCP server. The value must be one of the CIMD domain's **Authorized resource URIs**. A refresh grant request can omit `resource`, and FusionAuth uses the one from the original grant.
*   Use a `redirect_uri` that appears in your document's `redirect_uris` exactly.

## Update The Document

FusionAuth keeps using its cached copy until it expires. The next login after that fetches the document again, so a change, such as a new redirect URI, takes effect at the first login after the cached copy expires. See [CIMD Registration Caching And Lifecycle](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/cimd-registration-lifecycle.md) for how long that takes.

If that fetch fails, FusionAuth keeps using the old copy for the domain's **Grace period**. Refresh tokens your client already holds keep working even after the registration expires.

## Troubleshooting

When FusionAuth rejects a client, the user sees an `invalid_client` error page, and FusionAuth writes an Error entry to the Event Log under System -> Event Log . The entry includes the client's `client_id` URL, the requested `resource`, and a reason code: `metadataRetrievalFailed` when FusionAuth couldn't fetch or validate the document, `lambdaRejected` when the domain's registration lambda rejected the client, and `rateLimited` when the user registered too many new clients. A rate limited request also writes an Information entry. FusionAuth also sends a [CIMD Registration Failed](https://fusionauth.io/docs/extend/events-and-webhooks/events/cimd/cimd-registration-failed.md) event.

The entry doesn't say which requirement the document failed, so check the document and the request against the requirements on this page. The most common causes of a rejected client are:

*   The `client_id` in the document doesn't exactly match the URL.
*   The URL redirects, for example from a path without a trailing slash to one with it.
*   The document's origin doesn't match a CIMD domain in the Tenant.
*   The `redirect_uri` on the request isn't listed in the document.
*   The request has no `resource` parameter, or more than one.
*   The `resource` isn't one of the CIMD domain's **Authorized resource URIs**.

Related

[Lifecycle CIMD Registration Caching And Lifecycle Learn how long FusionAuth caches a Client ID Metadata Document, what happens when it expires, and how a CIMD client registration is refreshed or removed. cimdclient id metadata documentoauth client registration](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/cimd-registration-lifecycle.md)

[Operate CIMD Security Learn how FusionAuth protects itself when it fetches a Client ID Metadata Document from a URL a third party controls. cimdclient id metadata documentmcp client](https://fusionauth.io/docs/operate/secure/cimd-security.md)

[Extend CIMD Client Registration Lambda An overview of the CIMD client registration lambda. client id metadata documentcimdoauth client registration](https://fusionauth.io/docs/extend/code/lambdas/cimd-client-registration.md)

[Lifecycle OAuth Client Registration | Static and CIMD Learn how FusionAuth registers OAuth clients, either ahead of time as Applications or just-in-time from a Client ID Metadata Document. cimdclient id metadata document](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/client-registration.md)
---

## Other pages in OAuth

> For the full index of this section, see [Lifecycle](https://fusionauth.io/docs/llms-lifecycle.txt).

- [CIMD Registration Caching And Lifecycle](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/cimd-registration-lifecycle.md): Learn how long FusionAuth caches a Client ID Metadata Document, what happens when it expires, and how a CIMD client registration is refreshed or removed.
- [OAuth Client Registration | Static and CIMD](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/client-registration.md): Learn how FusionAuth registers OAuth clients, either ahead of time as Applications or just-in-time from a Client ID Metadata Document.
- [OAuth DPoP](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/dpop.md): Learn how to enable sender-constrained OAuth tokens DPoP (Demonstration of Proof-of-Possession) with FusionAuth and validate DPoP proofs in your APIs.
- [OAuth](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth.md): An overview of how FusionAuth provides an OAuth 2.0 and OpenID Connect SSO login system.
- [OAuth Issuer Validation](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/issuer-validation.md): Learn how to validate the authorization response issuer parameter (RFC 9207) to prevent mix-up attacks.
- [Modes](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/modes.md): An overview of OAuth modes and how OAuth is commonly used.
- [OIDC Prompt](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/prompt.md): Learn about OpenID Connect prompt and example use cases.
- [OAuth Response Modes](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/response-modes.md): Learn about OAuth 2.0 response modes (query, fragment, form_post) and when to use each one.
- [Access Control with OAuth Scopes](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/scopes.md): Learn about OAuth scope policy configuration, managing custom scopes, and using scopes in an OAuth2 workflow.
- [Delegate Access With Token Exchange](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/token-exchange-delegation.md): Configure FusionAuth so that one service can exchange a User's access token for a token that calls another service on that User's behalf.
- [OAuth Token Exchange](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/token-exchange.md): Learn how FusionAuth implements OAuth 2.0 Token Exchange (RFC 8693) so that a service can call another service on behalf of a user.
- [Manage Software Tokens](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/tokens.md): Learn about OAuth2 and OpenID Connect Tokens and how they are used.
- [URL Validation](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/url-validation.md): Learn about OAuth URL validation policies in FusionAuth.
