From 5b0c7ed5453f85fdcdc3d4bf8a310bd3b98f6c58 Mon Sep 17 00:00:00 2001 From: Camilo Hollanda <775409+prem-prakash@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:21:05 -0300 Subject: [PATCH] Make the dashboard work under host CSRF protection pipelines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `FunWithFlags.UI.Router` is forwarded under a host pipeline that already runs `Plug.CSRFProtection` — for example Phoenix's standard `:browser` pipeline — the host registers a `before_send` callback that raises `Plug.CSRFProtection.InvalidCrossOriginRequestError` whenever a non-XHR GET returns a JavaScript response. The dashboard serves its own `/assets/details.js` exactly that way, so the asset is rejected and the UI fails to load. The router now opts its own static asset GET/HEAD requests out of CSRF protection by setting the documented `:plug_skip_csrf_protection` flag before the asset is sent. `Plug.CSRFProtection` reads that flag at send time, so it correctly suppresses the cross-origin check even though the host registered its callback first. State-changing requests are never skipped and remain fully CSRF-protected. This means the dashboard works under the standard `:browser` pipeline with no special pipeline and no host-side configuration. The previously documented `:mounted_apps` recipe (which omitted `:protect_from_forgery`) is no longer necessary. Fixes #52. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 1 + README.md | 28 ++++----- lib/fun_with_flags/ui/router.ex | 34 +++++++++++ test/fun_with_flags/ui/router_test.exs | 81 ++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bda7e9..9585e0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v1.2.0 (unreleased) +* `FunWithFlags.UI.Router` now works under Phoenix's standard `:browser` pipeline (or any host pipeline that uses `Plug.CSRFProtection`) without extra configuration. The router opts its own static asset `GET`/`HEAD` requests out of the host's CSRF protection, so the dashboard's cross-origin `