Contact Us 1-800-596-4880

OAuth 2.0 Protected Resource Metadata Policy

Policy Name

OAuth 2.0 Protected Resource Metadata

Summary

Serves OAuth 2.0 Protected Resource Metadata at the well-known endpoint

Category

Security

First Omni Gateway version available

v1.13.0

Returned Status Codes

404 - Request path does not match the well-known endpoint

405 - HTTP method is not GET

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

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:

Parameter Required or Optional Default Value Description

Resource Identifier

Required

The protected resource identifier (RFC 8707). Must be an https URL without a fragment. This value is returned as the resource field in the metadata response and is used by clients to validate the response matches the resource they intended to query.
Example: "https://api.example.com/v1"

Authorization Servers

Optional

(omitted from response)

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.
Example: ["https://auth.example.com"]

JWK Set URI

Optional

(omitted from response)

URL of the resource’s JWK Set document containing its public keys for signing resource responses. Must use https scheme.
Example: "https://api.example.com/.well-known/jwks.json"

Scopes Supported

Optional (recommended by RFC 9728)

(omitted from response)

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.
Example: ["read", "write", "admin"]

Resource Scopes Overrides

Optional

[] (no overrides)

Array of objects mapping per-resource-path overrides for scopes_supported. Each entry maps a path suffix to a specific set of scopes. When a client requests /.well-known/oauth-protected-resource/<suffix>, the policy looks for a matching entry; if found, the entry’s scopes replace the default Scopes Supported in the response.
Each object contains:

* path (string, required) - The path suffix to match. Matched case-sensitively against the portion of the request path after /.well-known/oauth-protected-resource/.
* scopesSupported (array of strings, required) - The scopes to return for this resource path.

Bearer Methods Supported

Optional

(omitted from response)

Array of methods supported for sending bearer access tokens. Defined values are "header", "body", and "query" (per RFC 6750 Sections 2.1-2.3). An empty array means no bearer token methods are supported.
Example: ["header"]

Resource Signing Algorithm Values

Optional

(omitted from response)

Array of JWS alg values the resource uses to sign responses.
Example: ["RS256", "ES256"]

Resource Name

Optional (recommended by RFC 9728)

(omitted from response)

Human-readable name of the protected resource, suitable for display to end users.
Example: "Example API"

Resource Documentation URL

Optional

(omitted from response)

URL of a page containing human-readable developer documentation for the resource.
Example: "https://docs.example.com/api"

Resource Policy URI

Optional

(omitted from response)

URL of a page describing the resource’s data-use policy for clients.
Example: "https://example.com/privacy"

Resource Terms of Service URI

Optional

(omitted from response)

URL of a page with the resource’s terms of service.
Example: "https://example.com/tos"

TLS Client Certificate Bound Access Tokens

Optional

false (omitted from response when false)

Boolean indicating whether the resource requires mutual-TLS certificate-bound access tokens (RFC 8705).

Authorization Details Types Supported

Optional

(omitted from response)

Array of authorization details type values the resource supports (RFC 9396).
Example: ["payment_initiation"]

DPoP Signing Algorithm Values

Optional

(omitted from response)

Array of JWS alg values the resource accepts for DPoP proof JWTs (RFC 9449).
Example: ["ES256"]

DPoP Bound Access Tokens Required

Optional

false (omitted from response when false)

Boolean indicating whether DPoP-bound access tokens are always required by this resource.

Resource Configuration Examples

Minimal Configuration

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

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

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

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

Property Mapping

The policy maps configuration parameters to JSON response fields using snake_case naming:

Configuration Parameter JSON Response Field

Resource Identifier

resource

Authorization Servers

authorization_servers

JWK Set URI

jwks_uri

Scopes Supported

scopes_supported

Bearer Methods Supported

bearer_methods_supported

Resource Signing Algorithm Values

resource_signing_alg_values_supported

Resource Name

resource_name

Resource Documentation URL

resource_documentation

Resource Policy URI

resource_policy_uri

Resource Terms of Service URI

resource_tos_uri

TLS Client Certificate Bound Access Tokens

tls_client_certificate_bound_access_tokens

Authorization Details Types Supported

authorization_details_types_supported

DPoP Signing Algorithm Values

dpop_signing_alg_values_supported

DPoP Bound Access Tokens Required

dpop_bound_access_tokens_required

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:

{
  "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:

{
  "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:

    {
      "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:

    {
      "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:

    {
      "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.