Problem Description
When embedding FunWithFlags UI in Phoenix applications (or other frameworks with built-in CSRF protection), static assets (JavaScript/CSS) fail to load due to CSRF conflicts.
Error
** (Plug.CSRFProtection.InvalidCrossOriginRequestError) security warning: an embedded <script> tag on another site requested protected JavaScript (if you know what you're doing, disable forgery protection for this route)
Root Cause
- FunWithFlags UI serves static assets via
Plug.Static at /assets/*
- All requests (including assets) go through FunWithFlags' CSRF protection pipeline
- When embedded in Phoenix apps, both Phoenix and FunWithFlags try to manage CSRF protection
- Phoenix treats FunWithFlags asset requests as potentially dangerous cross-origin requests
- JavaScript and CSS assets are blocked, breaking the UI
Current README Solution vs. User Experience Reality
README Documents a Workaround
The README mentions using a special :mounted_apps pipeline:
pipeline :mounted_apps do
plug :accepts, ["html"]
plug :put_secure_browser_headers
# Notice: NO :protect_from_forgery
end
scope path: "/feature-flags" do
pipe_through :mounted_apps # Use special pipeline
forward "/", FunWithFlags.UI.Router
end
Note: There is no need to add :protect_from_forgery to the :mounted_apps pipeline because this package already implements CSRF protection.
UX Problems with README Approach
1. Discovery Problem
- Users naturally try the
:browser pipeline first (standard Phoenix practice)
- Hit the CSRF error with no clear guidance toward the solution
- Must dig through README to find the
:mounted_apps workaround
2. Not Intuitive
Most Phoenix developers expect this to work:
scope "/admin" do
pipe_through [:browser, :require_authenticated_user] # Natural approach
forward "/feature-flags", FunWithFlags.UI.Router
end
3. Documentation Gap
- README mentions
:mounted_apps but doesn't clearly explain WHY you need it
- No clear guidance on when you need this special pipeline vs. regular
:browser
- Users must understand CSRF conflicts to know they need the workaround
Reproduction Steps
- Create a Phoenix application with CSRF protection (default setup)
- Add FunWithFlags UI dependency
- Try the obvious/intuitive approach - mount using
:browser pipeline:
scope "/admin" do
pipe_through [:browser, :require_authenticated_user, :require_admin]
forward "/feature-flags", FunWithFlags.UI.Router
end
- Navigate to
/admin/feature-flags
- Browser console shows CSRF errors and UI assets fail to load
- User gets stuck and has to research/discover the
:mounted_apps workaround
Real-World Evidence
Despite the README documentation, users consistently create their own workarounds:
# Example from actual Phoenix apps
pipeline :no_csrf do
plug :accepts, ["html"]
plug :fetch_session
# Skip :protect_from_forgery - FunWithFlags has built-in CSRF protection
end
This shows the README solution has poor discoverability and user experience.
Expected Behavior
FunWithFlags UI should work seamlessly when embedded in Phoenix applications using the standard :browser pipeline without requiring:
- Special documentation discovery
- Custom pipeline creation
- Understanding of CSRF conflict internals
Solution
Implement automatic pipeline separation within FunWithFlags UI to handle CSRF conflicts transparently - see PR #51 for the fix that makes the obvious approach "just work".
Environment
- Phoenix applications with default CSRF protection
- FunWithFlags UI embedded via
forward in router using standard :browser pipeline
- Any Elixir web framework with CSRF protection that conflicts with Plug.CSRFProtection
Problem Description
When embedding FunWithFlags UI in Phoenix applications (or other frameworks with built-in CSRF protection), static assets (JavaScript/CSS) fail to load due to CSRF conflicts.
Error
Root Cause
Plug.Staticat/assets/*Current README Solution vs. User Experience Reality
README Documents a Workaround
The README mentions using a special
:mounted_appspipeline:UX Problems with README Approach
1. Discovery Problem
:browserpipeline first (standard Phoenix practice):mounted_appsworkaround2. Not Intuitive
Most Phoenix developers expect this to work:
3. Documentation Gap
:mounted_appsbut doesn't clearly explain WHY you need it:browserReproduction Steps
:browserpipeline:/admin/feature-flags:mounted_appsworkaroundReal-World Evidence
Despite the README documentation, users consistently create their own workarounds:
This shows the README solution has poor discoverability and user experience.
Expected Behavior
FunWithFlags UI should work seamlessly when embedded in Phoenix applications using the standard
:browserpipeline without requiring:Solution
Implement automatic pipeline separation within FunWithFlags UI to handle CSRF conflicts transparently - see PR #51 for the fix that makes the obvious approach "just work".
Environment
forwardin router using standard:browserpipeline