AttestoPhoenix.DevTLS (AttestoPhoenix v1.2.0)

Copy Markdown View Source

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

https_opts(opts \\ [])

@spec https_opts(keyword()) :: keyword()

Returns the Phoenix endpoint https: keyword list for a locally-trusted mkcert certificate.

Options

  • :port - the TLS port to listen on. Defaults to 4443.
  • :certfile - path to the certificate. Defaults to the conventional priv/cert/localhost.pem resolved against the caller's app (see below).
  • :keyfile - path to the private key. Defaults to the conventional priv/cert/localhost-key.pem resolved against the caller's app.
  • :otp_app - when given, the default cert/key paths resolve via Application.app_dir/2 (release-safe). When omitted, they resolve relative to File.cwd!/0 — the app root when running mix phx.server, which is the idiomatic Phoenix-dev spelling (phx.gen.cert emits the same bare relative paths).
  • :max_header_length - the Bandit http_1_options max header length. Defaults to 65536.

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)