---
schema_version: "1"
id: 14ec6e19b5aea7c3658b5a1025d8705a8b4c0551d575f5a9779b5b8c29b026e2
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/1.13/policies-included-oauth-protected-resource-metadata.md
canonical_url: https://docs.mulesoft.com/gateway/1.13/policies-included-oauth-protected-resource-metadata
source_site: docs.mulesoft.com
content_type: documentation
content_hash: 17bf353ba78c629033b99f6314206fa0ed9d26c28619e3d7fce2ce633e2a04f3
description: MuleSoft Documentation Site
release: "1.13"
latest: false
---
---
product: Omni Gateway
version: 1.13
keywords: oauth, protected resource, metadata, rfc 9728, api gateway, flex gateway, gateway, policy
---

# OAuth 2.0 Protected Resource Metadata Policy

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

<table><colgroup><col> <col></colgroup><tbody><tr><td><p><strong>Policy Name</strong></p></td><td><p>OAuth 2.0 Protected Resource Metadata</p></td></tr><tr><td><p><strong>Summary</strong></p></td><td><p>Serves OAuth 2.0 Protected Resource Metadata at the well-known endpoint</p></td></tr><tr><td><p><strong>Category</strong></p></td><td><p>Security</p></td></tr><tr><td><p><strong>First Omni Gateway version available</strong></p></td><td><p>v1.13.0</p></td></tr><tr><td><p><strong>Release Notes</strong></p></td><td><p><a href="https://docs.mulesoft.com/release-notes/gateway/policies/oauth-protected-resource-metadata-release-notes">OAuth 2.0 Protected Resource Metadata</a></p></td></tr><tr><td rowspan="2"><p><strong>Returned Status Codes</strong></p></td><td><p>404 - Request path does not match the well-known endpoint</p></td></tr><tr><td><p>405 - HTTP method is not GET</p></td></tr></tbody></table>

## 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). The metadata document is defined by the policy.
The policy doesn’t fetch metadata from an external source.

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

> [!IMPORTANT] This policy rejects all requests that aren’t made to the
> `/.well-known/oauth-protected-resource` route with a `404 Not Found` response.

## Configuring Policy Parameters

### Omni Gateway Local Mode

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

### Managed Omni Gateway and Omni Gateway Connected Mode

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

<table><colgroup><col> <col> <col> <col></colgroup><thead><tr><th>Parameter</th><th>Required or Optional</th><th>Default Value</th><th>Description</th></tr></thead><tbody><tr><td><div><div><p>Resource Identifier</p></div></div></td><td><div><div><p>Required</p></div></div></td><td><div></div></td><td><div><div><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><div><div><p>Authorization Servers</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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>Example: <code>["https://auth.example.com"]</code></p></div></div></td></tr><tr><td><div><div><p>JWK Set URI</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Scopes Supported</p></div></div></td><td><div><div><p>Optional (recommended by RFC 9728)</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Resource Scopes Overrides</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>[]</code> (no overrides)</p></div></div></td><td><div><div><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><div><div><p>Bearer Methods Supported</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Resource Signing Algorithm Values</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Resource Name</p></div></div></td><td><div><div><p>Optional (recommended by RFC 9728)</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Resource Documentation URL</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Resource Policy URI</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>Resource Terms of Service URI</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>TLS Client Certificate Bound Access Tokens</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code> (omitted from response when <code>false</code>)</p></div></div></td><td><div><div><p>Boolean indicating whether the resource requires mutual-TLS certificate-bound access tokens (RFC 8705).</p></div></div></td></tr><tr><td><div><div><p>Authorization Details Types Supported</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>DPoP Signing Algorithm Values</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p>(omitted from response)</p></div></div></td><td><div><div><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><div><div><p>DPoP Bound Access Tokens Required</p></div></div></td><td><div><div><p>Optional</p></div></div></td><td><div><div><p><code>false</code> (omitted from response when <code>false</code>)</p></div></div></td><td><div><div><p>Boolean indicating whether DPoP-bound access tokens are always required by this resource.</p></div></div></td></tr></tbody></table>

## Resource Configuration Examples

### 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

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

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"
```

## 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

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

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

## Example Responses

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

### 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

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 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

- **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.
