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

A Phoenix/Ecto OAuth 2.0 / OIDC authorization-server and
resource-server layer built on top of `Attesto`.

`Attesto` is transport-agnostic: it implements the pure, effect-free
protocol primitives - JWT mint/verify with per-key algorithm metadata
(RFC 7519), DPoP sender-constraint proofs (RFC 9449), mutual-TLS binding
(RFC 8705), PKCE (RFC 7636), the JWK Set (RFC 7517), authorization-server
metadata (RFC 8414), `private_key_jwt` client assertions (RFC 7523),
signed request objects (RFC 9101), and the scope grant-form algebra. It
deliberately carries no HTTP, no persistence, and no identity model.

`attesto_phoenix` adds exactly the two things a running server needs and
the core leaves out: a transport (HTTP endpoints and protected-resource
plugs) and persistence (Ecto-backed implementations of the core store
behaviours). Everything that is inherently application policy stays the
host's, supplied through a small set of neutral configuration callbacks.

## The split

The library keeps the same boundary `Attesto` draws - *protocol* versus
*policy* - and adds a third concern, *transport*:

  * **Protocol (core).** `Attesto.Token`, `Attesto.DPoP`,
    `Attesto.MTLS`, `Attesto.PKCE`, `Attesto.Scope`, `Attesto.JWKS`,
    `Attesto.ClientAssertion`, `Attesto.RequestObject`, and
    `Attesto.Discovery`. Pure functions over bytes and claims. This layer
    is reused verbatim; this package adds no crypto and forwards every
    protocol decision to it.

  * **Transport (here).** Controllers behind a router macro that mount
    authorization, token, pushed-authorization-request (RFC 9126),
    revocation (RFC 7009), discovery (RFC 8414), JWK Set (RFC 7517),
    UserInfo, and optional dynamic-registration (RFC 7591) endpoints, plus
    protected-resource plugs that verify a Bearer/DPoP access token and
    enforce its sender-constraint binding. The controllers and plugs use
    the core OAuth-error / `WWW-Authenticate` helpers so every failure is
    an RFC 6749 §5.2 / RFC 6750 §3 response, never a silent reject.

  * **Persistence (here).** Ecto schemas that implement the core store
    behaviours for authorization codes and refresh tokens, and - for
    clustered correctness - DPoP nonces and proof `jti` replay records.
    Migration scaffolding is a `mix` generator that writes the migration
    into the host application; this package owns no migration of its own.

  * **Policy (host application).** The client registry and its
    revocation rule, client-secret hashing, the subject/principal model,
    the scope catalog, signing keys, and the audit log. These are
    injected as the callbacks documented on `AttestoPhoenix.Config`, so
    the library never hardcodes one application's identity model.

## Configuration

All behaviour is centralized in `AttestoPhoenix.Config`. It is the single
source of truth read by every controller and plug: it validates the
required keys at build time (raising `ArgumentError` so misconfiguration
fails closed at boot), applies neutral defaults, and derives the
`Attesto.Config` the protocol layer runs against via
`AttestoPhoenix.Config.to_attesto_config/2`.

Anything that is application policy is a callback rather than a baked-in
assumption, named in OAuth terms:

  * client lookup -> `:load_client`
  * client-secret verification -> `:verify_client_secret`
  * client public keys -> `:client_jwks`
  * subject/principal resolution -> `:load_principal`
  * scope catalog / narrowing -> `:scopes_supported` and/or
    `:authorize_scope`
  * audit / telemetry -> `:on_event` (optional, no-op by default)
  * dynamic client persistence -> `:register_client` (only when
    registration is enabled)
  * mTLS certificate extraction -> `:cert_der` (only when mTLS is
    enabled)
  * HTTPS / proxy trust -> `:require_https` and `:trusted_proxies`

See `AttestoPhoenix.Config` for the full key reference and the default
for each value.

## Mounting the routes

`AttestoPhoenix.Router` provides the `attesto_routes/1` macro, which
mounts the authorization-server endpoints under a scope the host chooses.
Discovery and the JWK Set are public; the token and revocation endpoints
authenticate the client via the `:load_client` / `:verify_client_secret`
callbacks.

## Entry points

  * `AttestoPhoenix.Config` - the validated configuration every
    controller and plug reads, and the derivation of the protocol
    `Attesto.Config`.
  * `AttestoPhoenix.Router` - the `attesto_routes/1` macro that mounts
    the HTTP surface.

See the `README` for the supply/own breakdown, the router and plug usage,
and the migration generator.

---

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