Think about how an AI agent would access a protected API it has never seen before. It needs to know which authorization server issues tokens for that resource, what scopes to request, what token format the resource expects, and how to send the token. Today, in most implementations, that information is either hardcoded or buried in documentation someone has to read and configure manually.
That has worked for applications built by developers who can read a wiki. It does not work for autonomous agents that need to discover everything at runtime.
OAuth 2.0 had a piece missing and that piece finally arrived as a standard in early 2025. It’s called Protected Resource Metadata (PRM), defined in RFC 9728, and it completes a dynamic integration story that has been building for nearly a decade.
Let’s break down what was already there, what was missing, and why PRM matters now.
The dynamic integration story so far
Auth 2.0 defines three roles:
- The client (the application acting on behalf of the user)
- The authorization server (which issues access tokens)
- The resource server (which hosts the protected resource).

What makes modern OAuth 2.0 powerful is that much of the integration between these roles can be automated at runtime. Two specifications laid the groundwork for this.

Authorization Server Metadata (RFC 8414) allows a client to discover everything it needs to know about an authorization server by fetching a JSON document from a well-known URL. Supported grant types, token endpoints, authorization endpoints, PKCE support without hardcoding.
Dynamic Client Registration (RFC 7591) takes this further. A client that has never interacted with a particular authorization server can register itself programmatically, receive a client_id and credentials, and start requesting tokens all at runtime.
Together, these two specifications make the Client ↔ Authorization Server relationship fully automatable. A client can discover an authorization server, register with it, and obtain tokens without any manual configuration.
But here’s where it fell short.
The piece that was missing
Once a client has a token, it presents it to the resource server. The resource server validates it, either by calling the introspection endpoint (for opaque tokens) or verifying the signature using the JWKS endpoint (for JWTs). Both of these can be automated.

But there’s a question that neither of the above specifications answers: how does the client know which authorization server protects a given resource in the first place?
Traditionally, the answer has been: read the documentation. A developer looks up which identity provider an API uses, configures the authorization server URL, and hardcodes it. For an application a human developer builds once and ships, this is manageable. For an AI agent that needs to dynamically access dozens of third-party tools including MCP servers it’s never interacted with before, this is a fundamental blocker.
This is the gap that Protected Resource Metadata fills.
What Protected Resource Metadata does
PRM is a mechanism that allows a protected resource(typically an API) to publish a machine-readable JSON document describing its authorization requirements. This document tells clients:
- Which authorization servers the resource trusts
- What scopes clients need to request
- How tokens should be delivered (header, body, or query)
- Whether sender-constrained tokens (DPoP or certificate-bound) are required

The first draft of this specification appeared in 2016. It only recently became a priority because the use cases that requires fully automated, dynamic third-party integration has become urgent. AI agents and MCP are exactly why.
Together with Authorization Server Metadata and Dynamic Client Registration, PRM completes the full picture. A client can now discover everything it needs from resource requirements to authorization server details to registration entirely at runtime. No documentation, no hardcoded configuration.
How it works in practice
Let’s walk through the flow.
When a client accesses a protected resource without providing any security details, the resource server responds with an HTTP 401 Unauthorized as usual. In a PRM-compliant resource server, this response includes a WWW-Authenticate header with a resource_metadata field pointing to the resource metadata URL:

An actual HTTP response would look like this:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://resource.example.com/**.well-known/oauth-protected-resource"
The client then makes a simple HTTP GET request to that URL to retrieve the resource metadata. This is the Protected Resource Metadata Request, nothing more than a GET to a well-known endpoint.

The metadata response tells the client which authorization server issues tokens for this resource (authorization_servers), what scopes to request (scopes_supported), and how to send the token (bearer_methods_supported). The client uses the authorization server issuer identifier to construct the AS metadata URL from there, the existing Authorization Server Metadata flow takes over.

One important detail to highlight here: at any point, a resource server can return a fresh WWW-Authenticate challenge to signal that its metadata has changed. When a client receives this, it should re-fetch the resource metadata and update accordingly. This keeps the entire integration adaptive, if an authorization server changes or new security requirements are introduced, clients pick it up automatically without reconfiguration.
Key metadata parameters
Below are the core parameters defined by the PRM specification.
Mandatory:
resource— The unique identifier of the protected resource. Must use HTTPS, must not include a fragment, and ideally should not include a query string.
Strongly recommended:
authorization_servers— A list of authorization server issuer identifiers trusted by this resource. Technically optional per the spec, but without it the client has nowhere to go.scopes_supported— The OAuth 2.0 scopes clients must request to access this resource.bearer_methods_supported— How access tokens should be delivered:header,body, orquery. An empty array means no bearer methods are supported.jwks_uri— The HTTPS URL pointing to the resource’s JSON Web Key Set, used for verifying signed responses.
Additional security parameters:
resource_signing_alg_values_supported— JWS algorithms supported for signing resource responses. The value none is explicitly not permitted.authorization_details_types_supported— Supported authorization_details types when Rich Authorization Requests are in use.
For DPoP-bound tokens:
dpop_bound_access_tokens_required— Boolean. If true, the resource requires all tokens to be DPoP-bound.dpop_signing_alg_values_supported— Supported JWS algorithms for validating DPoP proofs.
For certificate-bound tokens:
tls_client_certificate_bound_access_tokens— Boolean. Indicates whether the resource supports mutual-TLS client certificate-bound tokens. Defaults to false if omitted.
Human-readable parameters (all optional):
resource_name— A display name for the resource, with internationalization support.resource_documentation— URL to developer documentation.resource_policy_uri— URL describing usage policy or restrictions.resource_tos_uri— URL to the resource’s terms of service.
All human-readable values support language tags (e.g. #en, #it) for localization. It’s recommended to also include a default version without a tag for broader compatibility.
Signed metadata
Beyond the standard JSON document, PRM supports delivering resource metadata as a signed JWT. This bundles the same metadata values into a cryptographically signed format that is useful in scenarios where metadata integrity needs to be verifiable.
The JWT must be signed or MACed using JSON Web Signature (JWS) and must include an iss (issuer) claim identifying who is asserting the metadata. Systems that support signed metadata must treat it as authoritative over the plain JSON values. The signed metadata is included using the signed_metadata parameter in the resource metadata response.
The protected_resources parameter for authorization servers
PRM also introduces a new metadata parameter for authorization servers: protected_resources. This allows an authorization server’s own metadata document to list the resources it protects enabling cross-checking between AS metadata and resource metadata.
In simple terms: the resource can say I trust this authorization server and the authorization server can say I protect this resource. Both sides can independently assert the relationship, which gives clients a way to verify the integrity of the integration.
Why this matters right now
The sequence diagram below illustrates the full end-to-end flow across all three specifications - Protected Resource Metadata, Authorization Server Metadata, and Dynamic Client Registration working together. While PRM highlights DCR as one possible approach for client registration, it doesn’t mandate it. DCR is included here to show what a fully automated, zero-hardcoding flow looks like.

The reason this became urgent is worth stating directly. For years, the gap in dynamic discovery was tolerable as developers could read documentation and configure things once. But AI agents change the equation. An agent that needs to access a set of third-party MCP servers it has never seen before cannot stop and ask a developer to configure each one. It needs to discover authorization requirements, register if necessary, obtain a token, and access the resource — entirely autonomously.
PRM is what makes that possible. Without it, every dynamic integration still requires a hardcoded authorization server URL somewhere. With it, the full OAuth 2.0 flow — from resource discovery to token acquisition can be driven by the client at runtime, based entirely on machine-readable metadata. This is the spec that completes the picture. It took nine years from the first draft to standard status. The reason it finally crossed the finish line is sitting right in front of us.
If you’re building MCP servers or designing AI agent authorization flows, PRM is worth reading directly, the spec is concise and the parameter reference is clear. You can find it at RFC 9728.
If you found this useful, I’d love to hear how you’re thinking about dynamic discovery in your own integrations, find me on LinkedIn.