A one-line, dev-only helper that wires a locally-trusted TLS certificate into a
Phoenix endpoint's https: listener.
attesto requires an https issuer (RFC 8414 §2: the issuer identifier MUST be
an https URL) — the discovery documents, DPoP htu, and RFC 9728 resource
identifiers are all https by spec, and attesto enforces that at config-build
time. So a plain http://localhost dev server can't drive the OAuth / MCP flow.
Rather than adding an https-disable switch (there is deliberately none in a
security library), this helper makes the RIGHT path frictionless: serve a
certificate from a local certificate authority — mkcert —
so https://localhost is trusted with no tunnel and no downgrade.
Generate the certificate once with mix attesto_phoenix.gen.dev_https, then in
config/dev.exs:
config :my_app, MyAppWeb.Endpoint, https: AttestoPhoenix.DevTLS.https_opts(port: 4443)The MCP / OAuth issuer then becomes https://localhost:4443, so discovery,
DPoP, and the RFC 8707 resource identifiers all line up automatically.
This is a dev-only convenience
It does not weaken any https requirement and it is not for production. In
production, TLS is terminated at the load balancer / ingress with a real CA
certificate, and the endpoint's https: listener (if any) uses that
certificate — never an mkcert one. mix mkcert -install trusts a CA on the
local machine only; never run it on a server or in CI.
This helper only wires a locally-trusted certificate into the dev endpoint. It never touches the issuer/audience validation, and attesto's https-only guarantee stays fully intact.
Summary
Functions
Returns the Phoenix endpoint https: keyword list for a locally-trusted
mkcert certificate.
Functions
Returns the Phoenix endpoint https: keyword list for a locally-trusted
mkcert certificate.
Options
:port- the TLS port to listen on. Defaults to4443.:certfile- path to the certificate. Defaults to the conventionalpriv/cert/localhost.pemresolved against the caller's app (see below).:keyfile- path to the private key. Defaults to the conventionalpriv/cert/localhost-key.pemresolved against the caller's app.:otp_app- when given, the default cert/key paths resolve viaApplication.app_dir/2(release-safe). When omitted, they resolve relative toFile.cwd!/0— the app root when runningmix phx.server, which is the idiomatic Phoenix-dev spelling (phx.gen.certemits the same bare relative paths).:max_header_length- the Bandithttp_1_optionsmax header length. Defaults to65536.
Returns:
[
port: 4443,
cipher_suite: :strong,
certfile: "…/priv/cert/localhost.pem",
keyfile: "…/priv/cert/localhost-key.pem",
http_1_options: [max_header_length: 65_536]
]Raises ArgumentError if the certificate or key is missing, pointing you at
mix attesto_phoenix.gen.dev_https. It NEVER silently falls back to http.
Examples
# config/dev.exs
config :my_app, MyAppWeb.Endpoint,
https: AttestoPhoenix.DevTLS.https_opts(port: 4443)
# release-safe path resolution
config :my_app, MyAppWeb.Endpoint,
https: AttestoPhoenix.DevTLS.https_opts(port: 4443, otp_app: :my_app)