---
schema_version: "1"
id: 2bbd35bf95fba662c8a0cc465701082072464f38876c081a3edeaef520f3d7cb
title: OAuth 2.0 Protected Resource Metadata Policy
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/gateway/latest/policies-included-oauth-protected-resource-metadata.md
canonical_url: https://docs.mulesoft.com/gateway/latest/policies-included-oauth-protected-resource-metadata
source_site: docs.mulesoft.com
content_type: documentation
content_hash: c4463bbb5e5b2169b28a3baffd8be22fbb4a8f235d7747bf0b1c1fe7bac41e64
description: MuleSoft Documentation Site
release: "1.14"
latest: true
---
# OAuth 2.0 Protected Resource Metadata Policy

<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 75%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-right valign-top"><p class="tableblock"><strong>Policy Name</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">OAuth 2.0 Protected Resource Metadata</p></td>
</tr>
<tr>
<td class="tableblock halign-right valign-top"><p class="tableblock"><strong>Summary</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Serves OAuth 2.0 Protected Resource Metadata at the well-known endpoint</p></td>
</tr>
<tr>
<td class="tableblock halign-right valign-top"><p class="tableblock"><strong>Category</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Security</p></td>
</tr>
<tr>
<td class="tableblock halign-right valign-top"><p class="tableblock"><strong>First Omni Gateway version available</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">v1.13.0</p></td>
</tr>
<tr>
<td class="tableblock halign-right valign-top"><p class="tableblock"><strong>Release Notes</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://docs.mulesoft.com/release-notes/gateway/policies/oauth-protected-resource-metadata-release-notes" class="xref page">OAuth 2.0 Protected Resource Metadata</a></p></td>
</tr>
<tr>
<td class="tableblock halign-right valign-middle" rowspan="4"><p class="tableblock"><strong>Returned Status Codes</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">404 - Request path does not match the well-known endpoint</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">405 - HTTP method is not GET</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">400 - Registration request matches no configured client (<a href="#static-dynamic-client-registration">Static Dynamic Client Registration</a> only)</p></td>
</tr>
</tbody>
</table>

## [](#summary)Summary

The OAuth Protected Resource Metadata policy serves a JSON document describing the protected resource’s OAuth 2.0 metadata at `/.well-known/oauth-protected-resource` as defined by [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728).

This policy enables authorization servers and client applications to discover important OAuth 2.0 configuration details about your protected resource, such as:

- Which authorization server tokens are accepted
- What scopes are available for authorization
- How to send bearer tokens (header, body, or query)
- Whether DPoP or mTLS token binding is required
- What URLs are available for resource documentation, policy, and terms of service

For identity providers (IdP) that don’t support support Dynamic Client Registration (DCR), the policy provides [Static DCR configuration](#static-dynamic-client-registration). Use it when your MCP clients require a `registration_endpoint`, but your IdP doesn’t support DCR. If your IdP supports DCR, or clients only need to discover your authorization server and scopes, static DCR configuration isn’t required.

<table><tbody><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content">This policy rejects all requests that aren’t made to the <code>/.well-known/oauth-protected-resource</code> route with a <code>404 Not Found</code> response.</td></tr></tbody></table>

## [](#configuring-policy-parameters)Configuring Policy Parameters

### [](#omni-gateway-local-mode)Omni Gateway Local Mode

The OAuth 2.0 Protected Resource Metadata policy doesn’t support Omni Gateway running in Local Mode.

### [](#connected-mode)Managed Omni Gateway and Omni Gateway Connected Mode

When you apply the policy from the UI, the following parameters are displayed:

<table class="tableblock frame-all grid-all fit-content spread">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter</th>
<th class="tableblock halign-left valign-top">Required or Optional</th>
<th class="tableblock halign-left valign-top">Default Value</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Identifier</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Required</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>The protected resource identifier (RFC 8707). Must be an <code>https</code> URL without a fragment. This value is returned as the <code>resource</code> field in the metadata response and is used by clients to validate the response matches the resource they intended to query.<br>
Example: <code>"https://api.example.com/v1"</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Authorization Servers</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Required</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of OAuth 2.0 authorization server issuer identifier URLs (per RFC 8414) whose tokens are accepted by this protected resource. Enter multiple values separated by commas or on separate lines.<br>
If you enable Static Dynamic Client Registration, these are the upstream servers whose metadata the policy fetches, and the response advertises the Consumer URL instead.<br>
Example: <code>["https://auth.example.com"]</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>JWK Set URI</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>URL of the resource’s JWK Set document containing its public keys for signing resource responses. Must use <code>https</code> scheme.<br>
Example: <code>"https://api.example.com/.well-known/jwks.json"</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Scopes Supported</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional (recommended by RFC 9728)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of default OAuth 2.0 scope values that can be used to request access to this resource. This value is returned when the well-known path has no suffix or when the suffix doesn’t match any entry in Resource Scopes Overrides. Enter multiple values separated by commas or on separate lines.<br>
Example: <code>["read", "write", "admin"]</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Scopes Overrides</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>[]</code> (no overrides)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of objects mapping per-resource-path overrides for <code>scopes_supported</code>. Each entry maps a path suffix to a specific set of scopes. When a client requests <code>/.well-known/oauth-protected-resource/&lt;suffix&gt;</code>, the policy looks for a matching entry; if found, the entry’s scopes replace the default Scopes Supported in the response.<br>
Each object contains:<br>
<br>
* <code>path</code> (string, required) - The path suffix to match. Matched case-sensitively against the portion of the request path after <code>/.well-known/oauth-protected-resource/</code>.<br>
* <code>scopesSupported</code> (array of strings, required) - The scopes to return for this resource path.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Bearer Methods Supported</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of methods supported for sending bearer access tokens. Defined values are <code>"header"</code>, <code>"body"</code>, and <code>"query"</code> (per RFC 6750 Sections 2.1-2.3). An empty array means no bearer token methods are supported.<br>
Example: <code>["header"]</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Signing Algorithm Values</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of JWS <code>alg</code> values the resource uses to sign responses.<br>
Example: <code>["RS256", "ES256"]</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Name</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional (recommended by RFC 9728)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Human-readable name of the protected resource, suitable for display to end users.<br>
Example: <code>"Example API"</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Documentation URL</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>URL of a page containing human-readable developer documentation for the resource.<br>
Example: <code>"https://docs.example.com/api"</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Policy URI</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>URL of a page describing the resource’s data-use policy for clients.<br>
Example: <code>"https://example.com/privacy"</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Terms of Service URI</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>URL of a page with the resource’s terms of service.<br>
Example: <code>"https://example.com/tos"</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>TLS Client Certificate Bound Access Tokens</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>false</code> (omitted from response when <code>false</code>)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Boolean indicating whether the resource requires mutual-TLS certificate-bound access tokens (RFC 8705).</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Authorization Details Types Supported</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of authorization details <code>type</code> values the resource supports (RFC 9396).<br>
Example: <code>["payment_initiation"]</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>DPoP Signing Algorithm Values</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(omitted from response)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Array of JWS <code>alg</code> values the resource accepts for DPoP proof JWTs (RFC 9449).<br>
Example: <code>["ES256"]</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>DPoP Bound Access Tokens Required</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>false</code> (omitted from response when <code>false</code>)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Boolean indicating whether DPoP-bound access tokens are always required by this resource.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Static Dynamic Client Registration</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>(disabled)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Object that makes an identity provider without Dynamic Client Registration (DCR) support appear DCR-capable to MCP clients. For the fields and behavior, see <a href="#static-dynamic-client-registration">Static Dynamic Client Registration</a>.</p>
</div></div></td>
</tr>
</tbody>
</table>

## [](#resource-configuration-examples)Resource Configuration Examples

### [](#minimal-configuration)Minimal Configuration

This example shows the minimum required configuration with basic scope and authorization server information:

```yaml
- policyRef:
    name: oauth-protected-resource-metadata-policy-flex
  config:
    resource: "https://api.example.com"
    scopesSupported:
      - "read"
      - "write"
    authorizationServers:
      - "https://auth.example.com"
```

### [](#full-configuration)Full Configuration

This example demonstrates all available configuration parameters:

```yaml
- policyRef:
    name: oauth-protected-resource-metadata-policy-flex
  config:
    resource: "https://api.example.com/v1"
    authorizationServers:
      - "https://auth.example.com"
      - "https://backup-auth.example.com"
    jwksUri: "https://api.example.com/.well-known/jwks.json"
    scopesSupported:
      - "read"
      - "write"
      - "admin"
    bearerMethodsSupported:
      - "header"
    resourceSigningAlgValuesSupported:
      - "RS256"
      - "ES256"
    resourceName: "Example API"
    resourceDocumentation: "https://docs.example.com/api"
    resourcePolicyUri: "https://example.com/privacy"
    resourceTosUri: "https://example.com/tos"
    tlsClientCertificateBoundAccessTokens: true
    authorizationDetailsTypesSupported:
      - "payment_initiation"
    dpopSigningAlgValuesSupported:
      - "ES256"
    dpopBoundAccessTokensRequired: true
```

### [](#per-resource-scope-overrides)Per-Resource Scope Overrides

This example shows how to configure different scopes for different resource paths:

```yaml
- policyRef:
    name: oauth-protected-resource-metadata-policy-flex
  config:
    resource: "https://api.example.com"
    authorizationServers:
      - "https://auth.example.com"
    scopesSupported:
      - "read"
      - "write"
    resourceScopesOverrides:
      - path: "users"
        scopesSupported:
          - "users:read"
          - "users:write"
          - "users:delete"
      - path: "orders"
        scopesSupported:
          - "orders:read"
          - "orders:create"
```

## [](#static-dynamic-client-registration)Static Dynamic Client Registration

MCP clients register with an authorization server through its `registration_endpoint` ([RFC 7591](https://www.rfc-editor.org/rfc/rfc7591)). If your IdP doesn’t support DCR, there is no `registration_endpoint`, and MCP clients can’t complete the OAuth flow.

When you enable Static Dynamic Client Registration, the policy:

- Advertises the gateway’s public URL (the Consumer URL) as the authorization server.
- Serves the IdP’s authorization server metadata with a `registration_endpoint` that points at the gateway.
- Serves that endpoint at `/.well-known/idp/register`. It returns the credentials of a client you already created in the IdP, chosen by matching the request’s `client_name`.

The IdP still authorizes users and issues tokens.

<table><tbody><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content">All MCP clients that match the same entry receive the same <code>client_id</code> and <code>client_secret</code>. Use public clients without a secret, or trusted MCP clients, and limit what the client can access in the IdP.</td></tr></tbody></table>

### [](#static-dcr-parameters)Parameters

Configure these parameters under **Static Dynamic Client Registration** (`staticDcr`). You must also set Authorization Servers.

<table class="tableblock frame-all grid-all fit-content spread">
<colgroup>
<col>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter</th>
<th class="tableblock halign-left valign-top">Required or Optional</th>
<th class="tableblock halign-left valign-top">Default Value</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Enable (<code>enabled</code>)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>false</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Turns the feature on.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Authorization Server Metadata Path (<code>authorizationServerMetadataPath</code>)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>/.well-known/oauth-authorization-server</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Path of the authorization server metadata. For OpenID Connect IdPs, use <code>/.well-known/openid-configuration</code>.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Consumer URL (<code>consumerUrl</code>)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Optional</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Taken from API Manager</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Public URL clients use to reach this API.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Static DCR Clients (<code>clients</code>)</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Required</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>List of preconfigured clients. The policy uses the first entry whose <code>name</code> matches the request’s <code>client_name</code>. If none match, the request is rejected. Each entry contains:<br>
<br>
* <code>name</code> (required) - Case-insensitive match on <code>client_name</code>. Use <code><strong></strong></code><strong> as a wildcard at the start or end, such as <code>claude</code></strong>. Use <code>*</code> alone to match any name.<br>
* <code>clientId</code> (required) - The client ID to return.<br>
* <code>clientSecret</code> (optional) - The client secret to return. Omit it for public clients.</p>
</div></div></td>
</tr>
</tbody>
</table>

### [](#static-dcr-configuration-example)Static DCR Configuration Example

```yaml
- policyRef:
    name: oauth-protected-resource-metadata-policy-flex
  config:
    resource: "https://api.example.com"
    authorizationServers:
      - "https://idp.example.com"
    staticDcr:
      enabled: true
      consumerUrl: "https://api.example.com"
      clients:
        - name: "claude*"
          clientId: "claude-mcp-client"
          clientSecret: "<CLAUDE_CLIENT_SECRET>"
        - name: "*"
          clientId: "shared-mcp-client"
```

### [](#static-dcr-walkthrough)Static DCR MCP Client Flow

First, create the OAuth clients in your IdP and apply the policy as shown in the example. Then an MCP client does the following:

1. Requests `/.well-known/oauth-protected-resource`. The policy returns the gateway as the authorization server:
    
    ```json
    {
      "resource": "https://api.example.com",
      "authorization_servers": ["https://api.example.com/"]
    }
    ```
2. Requests `/.well-known/oauth-authorization-server`. The policy returns the IdP’s metadata with the gateway’s `registration_endpoint`:
    
    ```json
    {
      "issuer": "https://idp.example.com",
      "authorization_endpoint": "https://idp.example.com/authorize",
      "token_endpoint": "https://idp.example.com/token",
      "registration_endpoint": "https://api.example.com/.well-known/idp/register"
    }
    ```
3. Sends a registration request to `/.well-known/idp/register`:
    
    ```json
    {
      "client_name": "Claude Desktop",
      "redirect_uris": ["https://client.example.com/callback"]
    }
    ```
    
    The name matches `claude*`, so the policy returns `201 Created` with that client’s credentials:
    
    ```json
    {
      "client_id": "claude-mcp-client",
      "client_secret": "<CLAUDE_CLIENT_SECRET>",
      "client_secret_expires_at": 0,
      "client_id_issued_at": 1719360000,
      "client_name": "Claude Desktop",
      "redirect_uris": ["https://client.example.com/callback"]
    }
    ```
4. Signs the user in directly with the IdP using the returned `client_id`, then calls the API with the access token.

If no entry matches the `client_name`, the policy returns `400 Bad Request` with the error `invalid_client_metadata`.

The policy fetches the IdP’s metadata on every authorization server metadata request and doesn’t cache it. If the policy can’t reach any IdP, the request returns `502 Bad Gateway`. The registration endpoint doesn’t depend on the IdP.

## [](#request-processing)Request Processing

1. **Path Matching:** The policy checks whether the request path ends with `/.well-known/oauth-protected-resource` or contains `/.well-known/oauth-protected-resource/` followed by a suffix. If the path doesn’t match, the policy returns `404 Not Found`.
2. **Method Validation:** If the path matches but the HTTP method is not `GET`, the policy returns `405 Method Not Allowed` with an `Allow: GET` header.
3. **Scope Resolution:** If the request path has a suffix after `/.well-known/oauth-protected-resource/`, the policy searches `resourceScopesOverrides` for an entry whose `path` matches the suffix exactly. If found, the entry’s `scopesSupported` replaces the top-level default in the response. If no override matches, the top-level `scopesSupported` is used.
4. **Metadata Response:** For matching `GET` requests, the policy constructs a JSON object from the configured properties. For response examples, see [Example Responses](#example-responses).

## [](#property-mapping)Property Mapping

The policy maps configuration parameters to JSON response fields using snake\_case naming:

<table class="tableblock frame-all grid-all fit-content spread">
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Configuration Parameter</th>
<th class="tableblock halign-left valign-top">JSON Response Field</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Identifier</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>resource</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Authorization Servers</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>authorization_servers</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>JWK Set URI</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>jwks_uri</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Scopes Supported</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>scopes_supported</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Bearer Methods Supported</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>bearer_methods_supported</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Signing Algorithm Values</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>resource_signing_alg_values_supported</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Name</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>resource_name</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Documentation URL</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>resource_documentation</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Policy URI</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>resource_policy_uri</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Resource Terms of Service URI</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>resource_tos_uri</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>TLS Client Certificate Bound Access Tokens</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>tls_client_certificate_bound_access_tokens</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Authorization Details Types Supported</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>authorization_details_types_supported</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>DPoP Signing Algorithm Values</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>dpop_signing_alg_values_supported</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>DPoP Bound Access Tokens Required</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>dpop_bound_access_tokens_required</code></p>
</div></div></td>
</tr>
</tbody>
</table>

## [](#example-responses)Example Responses

These examples show the JSON metadata document the policy returns for a `GET` request to the well-known endpoint.

### [](#minimal-configuration-response)Minimal Configuration Response

When only `resource`, `authorizationServers`, and `scopesSupported` are configured, a `GET` request to `/.well-known/oauth-protected-resource` returns:

```json
{
  "resource": "https://api.example.com",
  "authorization_servers": ["https://auth.example.com"],
  "scopes_supported": ["read", "write"]
}
```

### [](#full-configuration-response)Full Configuration Response

When all parameters are configured, a `GET` request to `/.well-known/oauth-protected-resource` returns all configured fields:

```json
{
  "resource": "https://api.example.com/v1",
  "authorization_servers": ["https://auth.example.com", "https://backup-auth.example.com"],
  "jwks_uri": "https://api.example.com/.well-known/jwks.json",
  "scopes_supported": ["read", "write", "admin"],
  "bearer_methods_supported": ["header"],
  "resource_signing_alg_values_supported": ["RS256", "ES256"],
  "resource_name": "Example API",
  "resource_documentation": "https://docs.example.com/api",
  "resource_policy_uri": "https://example.com/privacy",
  "resource_tos_uri": "https://example.com/tos",
  "tls_client_certificate_bound_access_tokens": true,
  "authorization_details_types_supported": ["payment_initiation"],
  "dpop_signing_alg_values_supported": ["ES256"],
  "dpop_bound_access_tokens_required": true
}
```

### [](#per-resource-scope-overrides-response)Per-Resource Scope Overrides Responses

When `resourceScopesOverrides` maps the `users` path suffix to `["users:read", "users:write", "users:delete"]` over a top-level default of `["read", "write"]`:

- A `GET` request to the default endpoint, `/.well-known/oauth-protected-resource`, returns the top-level scopes:
    
    ```json
    {
      "resource": "https://api.example.com",
      "authorization_servers": ["https://auth.example.com"],
      "scopes_supported": ["read", "write"]
    }
    ```
- A `GET` request to `/.well-known/oauth-protected-resource/users` matches the `users` override and returns its scopes:
    
    ```json
    {
      "resource": "https://api.example.com",
      "authorization_servers": ["https://auth.example.com"],
      "scopes_supported": ["users:read", "users:write", "users:delete"]
    }
    ```
- A `GET` request to an unconfigured suffix, such as `/.well-known/oauth-protected-resource/billing`, falls back to the top-level scopes:
    
    ```json
    {
      "resource": "https://api.example.com",
      "authorization_servers": ["https://auth.example.com"],
      "scopes_supported": ["read", "write"]
    }
    ```

## [](#edge-cases)Edge Cases

- **Non-matching paths:** Any request whose path doesn’t contain `/.well-known/oauth-protected-resource` receives `404 Not Found`. The policy is intended to be route-scoped to the well-known path.
- **Trailing slash:** `/.well-known/oauth-protected-resource/` (with trailing slash) is treated as a match with an empty suffix. Since an empty string won’t match any `resourceScopesOverrides` entries, the top-level `scopesSupported` is returned.
- **Case sensitivity:** Path matching is case-sensitive per RFC 9728 and RFC 8615.
- **Query parameters:** Query strings on the well-known URL are ignored (the path is matched without query or fragment).
- **Empty `bearerMethodsSupported`:** An explicitly configured empty array `[]` is serialized in the response (it signals "no bearer methods supported"), distinct from omitting the field entirely.