# `Attesto.ProtectedResourceMetadata`
[🔗](https://github.com/XukuLLC/attesto/blob/v0.13.0/lib/attesto/protected_resource_metadata.ex#L1)

RFC 9728 - OAuth 2.0 Protected Resource Metadata.

Build the JSON document a client (or an authorization server) fetches from a
protected resource's `/.well-known/oauth-protected-resource` to learn how to
obtain and present tokens for that resource: which authorization server(s)
issue tokens for it, where its JWKS lives, what scopes and bearer-token
presentation methods it accepts, and whether it requires sender-constrained
(DPoP / mTLS) tokens.

This is the resource-server analogue of `Attesto.Discovery` (RFC 8414, the
authorization server's metadata) and mirrors it exactly: a base map of the
fields Attesto can derive from the `Attesto.Config`, plus an `@host_fields`
allowlist reduce that merges in whatever the host supplies and drops `nil`
values so the document only advertises what the resource actually implements.

The only protocol-fixed field is `resource` (RFC 9728 §2, REQUIRED): the
resource identifier the metadata describes. It defaults to the config's
`audience` - the access-token audience a resource server validates is exactly
its resource identifier - and is overridable via the `:resource` opt for a
deployment whose canonical resource identifier differs from the default token
audience.

Everything else in RFC 9728 §2 is host-specific and supplied through `opts`:
the `authorization_servers` list, the resource's own `jwks_uri`,
`scopes_supported`, the `bearer_methods_supported` presentation methods, the
signing algorithms for signed responses, the human-facing
`resource_name`/documentation/policy/ToS URLs, the sender-constraint flags,
and a `signed_metadata` JWT. `nil` opt values are dropped.

The result is a string-keyed map ready to serialise as the endpoint's JSON
body. This module renders the document only; mounting a serving endpoint for
it is the host's concern.

# `metadata`

```elixir
@spec metadata(
  Attesto.Config.t(),
  keyword()
) :: %{required(String.t()) =&gt; term()}
```

Build the protected-resource metadata document for `config`.

The only field Attesto fixes is `resource` (RFC 9728 §2, REQUIRED): the
resource identifier this metadata describes.

Options:

  * `:resource` - the resource identifier. Defaults to `config.audience` (the
    access-token audience a resource server validates is its resource
    identifier); override for a deployment whose canonical resource
    identifier differs from the default token audience.
  * `:authorization_servers` - the list of issuer identifiers of the
    authorization servers that can issue tokens for this resource (RFC 9728
    §2). Included only if given.
  * `:jwks_uri` - the resource's own JWK Set URL (e.g. for verifying signed
    resource responses). Included only if given. Distinct from the
    authorization server's `jwks_uri`.
  * `:scopes_supported`, `:bearer_methods_supported`,
    `:resource_signing_alg_values_supported` - the scopes the resource
    recognises, the RFC 6750 token-presentation methods it accepts
    (`"header"`, `"body"`, `"query"`), and the JWS algorithms it signs
    responses with; included only if given.
  * `:resource_name`, `:resource_documentation`, `:resource_policy_uri`,
    `:resource_tos_uri` - human-facing display name and URLs; included only
    if given.
  * `:tls_client_certificate_bound_access_tokens` (RFC 8705),
    `:dpop_bound_access_tokens_required`,
    `:dpop_signing_alg_values_supported` (RFC 9449) - the sender-constraint
    flags and accepted DPoP algorithms; included only if given.
  * `:signed_metadata` - a JWT whose claims are the signed counterpart of
    this document (RFC 9728 §2); included only if given.

The accepted host fields are the RFC 9728 §2 allowlist in `@host_fields`; the
enumeration above is illustrative. Any other opt key is ignored.

---

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