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.
Summary
Functions
Build the protected-resource metadata document for config.
Functions
@spec metadata( Attesto.Config.t(), keyword() ) :: %{required(String.t()) => 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 toconfig.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'sjwks_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.