Packages
attesto_phoenix
2.0.1
2.1.0
2.0.2
2.0.1
2.0.0
1.4.0
1.3.0
1.2.0
1.1.0
1.0.0
0.20.0
0.19.1
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.2
0.14.1
0.14.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
Phoenix/Ecto OAuth 2.0 / OIDC authorization server layer over attesto: authorization, token, PAR, revocation, discovery, JWKS, UserInfo, protected-resource plugs, and Ecto-backed token stores.
Current section
Files
Jump to
Current section
Files
lib/attesto_phoenix.ex
defmodule AttestoPhoenix do
@moduledoc """
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).** Standards controllers behind a router macro that
owns the maintained route catalog for 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. Hosts select endpoint
capabilities and metadata/interactive/protocol pipeline classes instead
of restating those routes. Protected-resource plugs verify Bearer/DPoP
access tokens and enforce 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.
Hosts declaratively select optional route mounts and route pipeline classes;
application authentication and consent remain callbacks. The same
routing and controller plumbing supports public-client OAuth and strict FAPI
profiles through different policy configuration rather than controller
forks. 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.
"""
end