AttestoMCP.Plug.Authenticate (AttestoMCP v1.0.0)

Copy Markdown View Source

Authenticate a protected MCP endpoint with Attesto.

This plug delegates token, DPoP, and mTLS verification to Attesto.Plug.Authenticate, then assigns MCP-friendly auth context for the host server.

Defaults:

  • :claims_key - :attesto_mcp_claims
  • :scopes_key - :attesto_mcp_scopes
  • :sender_key - :attesto_mcp_sender
  • :principal_key - :attesto_mcp_principal
  • :context_key - :attesto_context

Alongside the MCP-specific assigns above, the plug also assigns a single protocol-shaped context map under :context_key (default :attesto_context), identical in shape to the one AttestoPhoenix.Plug.Authenticate assigns: %{subject, client_id, scope (list), claims, cnf, principal}. This is the canonical cross-plug auth context; AttestoMCP.Anubis.put_auth/1 projects it into the Anubis frame regardless of which authenticator ran.

Options accepted by Attesto.Plug.Authenticate, including :config, :replay_check, :nonce_check, :nonce_issue, :cert_der, :htu, :credential_from_conn, :bearer_methods, :send_error, :www_authenticate, and :no_store, are passed through.

MCP defaults to bearer_methods: [:header], matching protected-resource metadata that advertises bearer_methods_supported: ["header"]. A host that genuinely needs RFC 6750 §2.2 form-body tokens can opt in with bearer_methods: [:header, :body], but body credentials are easier to leak through logs, caches, retries, and replay tooling than an Authorization header.

Additional options:

  • :principal - optional callback that receives verified claims and sender context, returning {:ok, principal} or {:error, reason}.
  • :resource_metadata_url - URL string, (conn -> url) callback, or {module, fun} / {module, fun, args} tuple that appends an RFC 9728 resource_metadata auth-param to WWW-Authenticate challenges unless a custom :www_authenticate callback is already supplied. This is a total override: it takes precedence over :base_url/:origin, and a (conn -> url) form that derives from the connection bypasses origin pinning - pin via :base_url/:origin (which the default derivation honors) rather than a conn-deriving :resource_metadata_url callback behind a proxy. A custom :www_authenticate callback replaces challenge handling entirely, so it must append its own resource_metadata if wanted.
  • :resource_path - MCP endpoint path used to derive :resource_metadata_url. Its origin is resolved by AttestoMCP.Metadata.resolve_origin/2, so a pinned origin applies.
  • :base_url / :origin - pin the origin of the derived resource_metadata challenge URL (a String.t() or (conn -> url)), instead of deriving it from the request connection. Use behind a TLS-terminating proxy so the advertised metadata URL cannot be spoofed via X-Forwarded-*. When omitted, the live request origin is used. This origin is the resource server's own; it is independent of the :config issuer (the authorization server).