# `AttestoMCP.Plug.Authenticate`
[🔗](https://github.com/XukuLLC/attesto_mcp/blob/v1.0.5/lib/attesto_mcp/plug/authenticate.ex#L1)

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`,
`:trusted_audiences`, `: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:

  * `:resource_audience` - confines the token to this protected resource.
    Use `:resource` to derive the identifier from `:resource_path`, or pass a
    literal identifier / `(conn -> identifier)` / MFA callback. The resolved
    identifier becomes Attesto core's complete `:trusted_audiences` list, so
    a scalar `aud` must equal it and every member of an array-valued `aud`
    must equal it. `:resource_audience` and `:trusted_audiences` are mutually
    exclusive; configuring both raises rather than silently weakening either
    policy. A callback must return a valid identifier; `nil` or another
    malformed result fails authentication and never disables confinement.
  * `: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).

---

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