# `AttestoPhoenix.Controller.ProtectedResourceController`
[🔗](https://github.com/XukuLLC/attesto_phoenix/blob/v0.19.0/lib/attesto_phoenix/controller/protected_resource_controller.ex#L1)

RFC 9728 - OAuth 2.0 Protected Resource Metadata endpoint.

Serves the protected-resource metadata document at
`/.well-known/oauth-protected-resource` (RFC 9728 §3) so that a client - or
an authorization server acting on its behalf - can discover, from the
resource identifier alone, which authorization server(s) issue tokens for
this resource, the scopes it recognises, and how it expects bearer tokens to
be presented. This is the resource-server analogue of the RFC 8414
authorization-server metadata `DiscoveryController` serves, and the discovery
half of the RFC 9728 §5.1 `WWW-Authenticate: Bearer ..., resource_metadata`
challenge `AttestoPhoenix.Plug.Authenticate` emits on a 401: the challenge
points a client here, and this endpoint answers.

The document is assembled by `Attesto.ProtectedResourceMetadata.metadata/2`;
this controller contributes transport concerns only and adds no policy of its
own. The members are derived from the protocol and host configuration the
rest of the server already carries:

  * `resource` (RFC 9728 §2, REQUIRED) - the resource identifier, the core
    builder's default: the access-token `audience` a resource server
    validates is exactly its resource identifier.
  * `authorization_servers` - this server's `issuer`. An OAuth deployment
    that is both the authorization server and the protected resource issues
    its own tokens, so the issuer is the authorization server for this
    resource; a client that reads this document then fetches that issuer's
    RFC 8414 metadata to run the flow.
  * `scopes_supported` - the host's `:scopes_supported`, the same list the
    RFC 8414 document advertises, so the two never drift.
  * `bearer_methods_supported` - the host's `:bearer_methods_supported`
    (`AttestoPhoenix.Config`), the RFC 6750 token-presentation methods the
    resource server accepts. Defaults to `["header"]`, matching
    `AttestoPhoenix.Plug.Authenticate`; add `"body"` only when the resource
    server intentionally accepts RFC 6750 §2.2 form-body `access_token`
    credentials.

The response carries no secrets and is identical for every caller, so it is
served unauthenticated, and RFC 9728 §3.1 permits caching, so a public,
cacheable `Cache-Control` header is set.

## Wiring

Like the other metadata endpoints, the host pipeline must place the
`AttestoPhoenix.Config` under `conn.private[:attesto_phoenix_config]` and the
derived `Attesto.Config` under `conn.private[:attesto_protocol_config]`. Both
are required; a missing value raises rather than serving a partial document,
because a document that omits `authorization_servers` or `resource` would
misdirect a client.

# `show`

```elixir
@spec show(Plug.Conn.t(), map()) :: Plug.Conn.t()
```

Render the RFC 9728 protected-resource metadata document as JSON.

Fails closed with `RuntimeError` when either required configuration value is
absent from `conn.private`, since serving a document that omits required
members would misdirect clients.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
