Getting started Community Training Tutorials Documentation APIs, AI & Tools
Resource Identifier
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 |
Release Notes |
|
Returned Status Codes |
404 - Request path does not match the well-known endpoint |
405 - HTTP method is not GET |
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.
|
The OAuth 2.0 Protected Resource Metadata policy doesn’t support Omni Gateway running in Local 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 |
|
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. |
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 |
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. |
Resource Scopes Overrides |
Optional |
|
Array of objects mapping per-resource-path overrides for |
Bearer Methods Supported |
Optional |
(omitted from response) |
Array of methods supported for sending bearer access tokens. Defined values are |
Resource Signing Algorithm Values |
Optional |
(omitted from response) |
Array of JWS |
Resource Name |
Optional (recommended by RFC 9728) |
(omitted from response) |
Human-readable name of the protected resource, suitable for display to end users. |
Resource Documentation URL |
Optional |
(omitted from response) |
URL of a page containing human-readable developer documentation for the resource. |
Resource Policy URI |
Optional |
(omitted from response) |
URL of a page describing the resource’s data-use policy for clients. |
Resource Terms of Service URI |
Optional |
(omitted from response) |
URL of a page with the resource’s terms of service. |
TLS Client Certificate Bound Access Tokens |
Optional |
|
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 |
DPoP Signing Algorithm Values |
Optional |
(omitted from response) |
Array of JWS |
DPoP Bound Access Tokens Required |
Optional |
|
Boolean indicating whether DPoP-bound access tokens are always required by this resource. |
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"
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
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"
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.
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.
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.
Metadata Response: For matching GET requests, the policy constructs a JSON object from the configured properties. For response examples, see Example Responses.
The policy maps configuration parameters to JSON response fields using snake_case naming:
| Configuration Parameter | JSON Response Field |
|---|---|
Resource Identifier |
|
Authorization Servers |
|
JWK Set URI |
|
Scopes Supported |
|
Bearer Methods Supported |
|
Resource Signing Algorithm Values |
|
Resource Name |
|
Resource Documentation URL |
|
Resource Policy URI |
|
Resource Terms of Service URI |
|
TLS Client Certificate Bound Access Tokens |
|
Authorization Details Types Supported |
|
DPoP Signing Algorithm Values |
|
DPoP Bound Access Tokens Required |
|
These examples show the JSON metadata document the policy returns for a GET request to the well-known endpoint.
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"]
}
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
}
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"]
}
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.