Dstar.Plugs.RenameCsrfParam (dstar v0.2.0)

Copy Markdown View Source

Renames a CSRF body param to _csrf_token so that Plug.CSRFProtection can find it.

Why this exists

Phoenix expects the CSRF token in conn.body_params["_csrf_token"] (or the x-csrf-token header). Datastar sends its signals with every request, but _-prefixed signal keys are front-end-only — never sent to the backend — so a token named _csrf_token would never arrive.

The shim: expose the token as a non-prefixed signal (default csrf). Because it is not _-prefixed, Datastar includes it in every request. This plug then copies that value into _csrf_token in body_params before Plug.CSRFProtection runs.

How the token travels (Datastar v1.0)

Datastar transports signals differently depending on the HTTP method:

  • POST / PUT / PATCH — signals are sent as the JSON request body, so the token arrives as a top-level body param (e.g. body_params["csrf"]).
  • GET / DELETE — signals are serialized into the datastar URL query parameter as a JSON object (e.g. ?datastar={"csrf":"..."}), because these methods carry no body. This plug decodes that parameter and extracts the token from it, so DELETE requests — which Plug.CSRFProtection does check — pass validation too.

The plug checks both channels, so one setup covers page event() POSTs, stream connect() POSTs, component events, and all verb helpers.

Security note

Because the token is a non-prefixed signal, it rides along on every request — and on GET/DELETE that means the URL query string, not the body. The token is still validated cryptographically against the session-derived value by Plug.CSRFProtection, so this does not weaken forgery protection. But a per-session credential sitting in URLs ends up in access/proxy logs and same-origin Referer headers. If that matters for your threat model, see the README's CSRF section for hardening options (log scrubbing, Referrer-Policy, header-based transport).

Usage

# In your Phoenix router (before :protect_from_forgery):
plug Dstar.Plugs.RenameCsrfParam

# With a custom source param name:
plug Dstar.Plugs.RenameCsrfParam, from: "my_token"

# With a custom Datastar query param name (default "datastar"):
plug Dstar.Plugs.RenameCsrfParam, datastar_param: "ds"

Options

  • :from — Source param name to copy from. Default: "csrf".
  • :datastar_param — Name of the Datastar query parameter that carries the signals JSON on GET/DELETE requests. Default: "datastar".