f0rest8
Invalid csrf error on phoenix 1.6.7 in (Plug.CSRFProtection.InvalidCSRFTokenError)
In development I noticed that when I update to the latest version of Phoenix (1.6.7), I now receive an invalid csrf error when attempting to login.
Deps Versions that work
- phoenix 1.6.6
- plug 1.13.4 / 1.13.6
- phoenix_live_view 0.17.7 / 0.17.9
- phoenix_pubsub 2.1.0 / 2.1.1
Error on phoenix 1.6.7
* The session cookie is being sent and session is loaded
* The request include a valid '_csrf_token' param or 'x-csrf-token' header
(plug 1.13.6) lib/plug/csrf_protection.ex:316: Plug.CSRFProtection.call/2
(metamorphic_web 0.1.0) MetamorphicWeb.Router.browser/2
(metamorphic_web 0.1.0) lib/metamorphic_web/router.ex:1: MetamorphicWeb.Router.__pipe_through9__/1
(phoenix 1.6.7) lib/phoenix/router.ex:347: Phoenix.Router.__call__/2
(metamorphic_web 0.1.0) lib/metamorphic_web/endpoint.ex:1: MetamorphicWeb.Endpoint.plug_builder_call/2
(metamorphic_web 0.1.0) lib/plug/debugger.ex:136: MetamorphicWeb.Endpoint."call (overridable 3)"/2
(metamorphic_web 0.1.0) lib/metamorphic_web/endpoint.ex:1: MetamorphicWeb.Endpoint.call/2
(phoenix 1.6.7) lib/phoenix/endpoint/cowboy2_handler.ex:54: Phoenix.Endpoint.Cowboy2Handler.init/4
(cowboy 2.9.0) /home/mark/github/eclogite/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
(cowboy 2.9.0) /home/mark/github/eclogite/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
(cowboy 2.9.0) /home/mark/github/eclogite/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
(stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Router
Below is router.ex file:
defmodule MetamorphicWeb.Router do
use MetamorphicWeb, :router
import Phoenix.LiveDashboard.Router
import MetamorphicWeb.PersonAuth
alias MetamorphicWeb.Plugs.{EnsurePrivilege, VerifyPortalPass, PlugAttack}
if Application.get_env(:metamorphic_web, :http_headers) == :prod do
pipeline :browser do
plug PlugAttack
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :protect_from_forgery
plug :put_secure_browser_headers, %{
"referrer-policy" => "no-referrer",
"permissions-policy" => "interest-cohort=()",
"strict-transport-security" => "max-age=31536000; includeSubDomains"
}
plug :fetch_current_person
end
pipeline :gpc do
plug PlugAttack
plug :accepts, ["json"]
end
else
pipeline :browser do
plug PlugAttack
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :protect_from_forgery
plug :put_secure_browser_headers, %{
"referrer-policy" => "no-referrer",
"permissions-policy" => "interest-cohort=()"
}
plug :fetch_current_person
end
pipeline :gpc do
plug PlugAttack
plug :accepts, ["json"]
end
end
pipeline :api do
plug PlugAttack
plug :accepts, ["json"]
end
pipeline :marketing_layout do
plug :put_root_layout, {MetamorphicWeb.LayoutView, :marketing}
end
pipeline :pre_release_layout do
plug :put_root_layout, {MetamorphicWeb.LayoutView, :pre_release}
end
pipeline :register_layout do
plug :put_root_layout, {MetamorphicWeb.LayoutView, :register}
end
pipeline :app_layout do
plug :put_root_layout, {MetamorphicWeb.LayoutView, :root}
end
pipeline :admin do
plug EnsurePrivilege, :admin
end
pipeline :person do
plug EnsurePrivilege, [:admin, :person]
end
pipeline :require_portal_pass do
plug VerifyPortalPass
end
# Other scopes may use custom stacks.
# scope "/api", MetamorphicWeb do
# pipe_through :api
# end
# Enables LiveDashboard only for development
#
# If you want to use the LiveDashboard in production, you should put
# it behind authentication and allow only admins to access it.
# If your application does not have an admins-only section yet,
# you can use Plug.BasicAuth to set up some basic authentication
# as long as you are also using SSL (which you should anyway).
#
# We are using live dash in production. It is behind the admin
# authentication and authorization.
# Enables displaying emails via Bamboo LocalAdapter for
# development.
if Mix.env() == :dev do
# If using Phoenix
forward "/sent_emails", Bamboo.SentEmailViewerPlug
end
# Health check
scope "/", MetamorphicWeb do
pipe_through [:browser, :marketing_layout]
get "/healthz", HealthCheckController, :index, as: :health_check
end
# Global Privacy Control route.
scope "/", MetamorphicWeb do
pipe_through [:gpc]
get "/.well-known/gpc.json", GlobalPrivacyController, :global_privacy_response
end
##
## Requires AUTHENTICATED person routes
##
# 2FA (two-factor authentication).
scope "/", MetamorphicWeb do
pipe_through [:browser, :register_layout, :require_authenticated_person, :person]
get "/people/totp", PersonTOTPController, :new
post "/people/totp", PersonTOTPController, :create
end
# Subscriptions
scope "/", MetamorphicWeb do
pipe_through [
:browser,
:register_layout,
:require_authenticated_person,
:redirect_if_person_has_subscription
]
live "/subscriptions/new", SubscriptionLive.New, :new
end
# Dashboard, settings, and support.
scope "/", MetamorphicWeb do
pipe_through [
:browser,
:app_layout,
:require_authenticated_person,
:redirect_if_admin,
:person
]
live_session :authenticated_redirect_if_admin,
root_layout: {MetamorphicWeb.LayoutView, :root},
on_mount: [{MetamorphicWeb.PersonLiveAuth, :redirect_if_admin}, MetamorphicWeb.Nav] do
live "/dashboard", DashboardLive.Index, :index, as: :dashboard
live "/people/settings", PersonSettingsLive.Index, :index, as: :person_settings
live "/people/settings/billing", PersonSettingsLive.Billing, :billing, as: :person_settings
live "/people/settings/data", PersonSettingsLive.Data, :data, as: :person_settings
live "/people/settings/security", PersonSettingsLive.Security, :security, as: :person_settings
live "/support", SupportLive.Index, :index, as: :support
end
get "/people/settings/data/download-stripe-data",
PersonSettingsController,
:download_stripe_data
get "/people/settings/data/download-encrypted-person",
PersonSettingsController,
:download_encrypted_person_data
get "/people/settings/data/download-encrypted-memories",
PersonSettingsController,
:download_encrypted_memory_data
get "/people/settings/data/download-encrypted-letters",
PersonSettingsController,
:download_encrypted_letter_data
get "/people/settings/data/download-encrypted-portals",
PersonSettingsController,
:download_encrypted_portal_data
get "/people/settings/data/download-encrypted-person-relationships",
PersonSettingsController,
:download_encrypted_relationship_person_data
get "/people/settings/data/download-encrypted-relation-relationships",
PersonSettingsController,
:download_encrypted_relationship_relation_data
get "/people/settings/confirm_email/:token", PersonSettingsController, :confirm_email
put "/people/settings/update_password", PersonSettingsController, :update_password
end
# Log out.
scope "/", MetamorphicWeb do
pipe_through [:browser, :app_layout, :require_authenticated_person, :person]
delete "/people/log_out", PersonSessionController, :delete
end
# Letters, memories, relationships, portals (:index, :new, and :edit).
scope "/", MetamorphicWeb do
pipe_through [
:browser,
:app_layout,
:require_authenticated_person,
:require_active_subscription,
:person
]
live_session :authenticated,
root_layout: {MetamorphicWeb.LayoutView, :root},
on_mount: [{MetamorphicWeb.PersonLiveAuth, :ensure_authenticated}, MetamorphicWeb.Nav] do
live "/letters", LetterLive.Index, :index, as: :letters
live "/letters/new", LetterLive.Index, :new, as: :letters
live "/letters/mailbox", LetterLive.Mailbox, :mailbox, as: :letters
live "/letters/mailbox/new", LetterLive.Mailbox, :compose, as: :letters
live "/letters/:id/read", LetterLive.Mailbox, :read, as: :letters
# live "/letters/:id/edit", LetterLive.Index, :edit, as: :letters
live "/memories", MemoryLive.Index, :index, as: :memories
# live "/memories/:id/edit", MemoryLive.Index, :edit, as: :memories
live "/memories/new", MemoryLive.Index, :new, as: :memories
get "/memories/shared/download", MemoryDownloadsController, :download_shared_memory,
as: :memories
get "/memories/download", MemoryDownloadsController, :download_memory, as: :memories
# live "/memories/:id", MemoryLive.Show, :show, as: :memories
# live "/memories/:id/show/edit", MemoryLive.Show, :edit
live "/portals", PortalLive.Index, :index, as: :portal
# live "/portals/:id/edit", PortalLive.Index, :edit, as: :portal
live "/portals/new", PortalLive.New, :new, as: :portal
live "/relationships", RelationshipLive.Index, :index, as: :relationships
live "/relationships/new", RelationshipLive.Index, :new, as: :relationships
live "/relationships/:id/edit", RelationshipLive.Index, :edit, as: :relationships
# live "/relationships/:id", RelationshipLive.Show, :show
# live "/relationships/:id/show/edit", RelationshipLive.Show, :edit
live "/roadmap", RoadmapLive.Index, :index, as: :roadmap
end
end
# Portals (:show) with :require_portal_pass plug.
scope "/", MetamorphicWeb do
pipe_through [
:browser,
:app_layout,
:require_authenticated_person,
:require_active_subscription,
:require_portal_pass,
:person
]
live "/portals/open/:slug", PortalLive.Show, :show, as: :portal
end
##
## Does NOT require authenticated person routes
##
# Registration and log in pages for people's accounts.
scope "/", MetamorphicWeb do
pipe_through [:browser, :register_layout, :redirect_if_person_is_authenticated]
get "/people/log_in", PersonSessionController, :new
post "/people/log_in", PersonSessionController, :create
live_session :register,
root_layout: {MetamorphicWeb.LayoutView, :register},
on_mount: {MetamorphicWeb.PersonLiveAuth, :register} do
live "/people/register", PersonRegistrationLive.New, :new, as: :person_registration
end
# get "/people/reset_password", PersonResetPasswordController, :new
# post "/people/reset_password", PersonResetPasswordController, :create
# live "/people/reset_password/:token", PersonResetPasswordLive.Edit, :edit, as: :person_reset_password
# put "/people/reset_password/:token", PersonResetPasswordController, :update
end
# Resend confirmation instructions for a person's account.
scope "/", MetamorphicWeb do
pipe_through [:browser, :register_layout]
get "/people/confirm", PersonConfirmationController, :new
post "/people/confirm", PersonConfirmationController, :create
get "/people/confirm/:token", PersonConfirmationController, :confirm
get "/invitations/confirm", InviteConfirmationController, :new
post "/invitations/confirm", InviteConfirmationController, :create
get "/invitations/confirm/:token", InviteConfirmationController, :confirm
end
# Marketing pages.
scope "/", MetamorphicWeb do
pipe_through [:browser, :marketing_layout]
# live_session :pre_release, root_layout: {MetamorphicWeb.LayoutView, :pre_release}, on_mount: {MetamorphicWeb.PersonLiveAuth, :pre_release} do
# live "/", PageLive.Index, :index, as: :page
# end
live_session :marketing,
root_layout: {MetamorphicWeb.LayoutView, :marketing},
on_mount: {MetamorphicWeb.PersonLiveAuth, :marketing} do
live "/", PageLive.Index, :index, as: :page
live "/about", AboutLive.Index, :index, as: :about
live "/built-to-code", BuiltToCodeLive.Index, :index, as: :built_to_code
live "/customer-rights", CustomerRightsLive.Index, :index, as: :customer_rights
live "/faq", FaqLive.Index, :index, as: :faq
live "/features", FeaturesLive.Index, :index, as: :features
live "/find-your-peace", FindYourPeaceLive.Index, :index, as: :find_your_peace
live "/hassle-free", HassleFreeLive.Index, :index, as: :hassle_free
live "/pricing", PricingLive.Index, :index, as: :pricing
live "/privacy", PrivacyLive.Index, :index, as: :privacy
live "/security", SecurityLive.Index, :index, as: :security
live "/rocks", SpecialThanksLive.Index, :index, as: :thanks
live "/terms", TermsLive.Index, :index, as: :terms
live "/why-metamorphic", WhyMetamorphicLive.Index, :index, as: :why_metamorphic
live "/blog", BlogLive.Index, :index, as: :blog
live "/blog/clean-cookies", BlogLive.Posts.CleanCookies, :index,
as: :blog_posts_clean_cookies
live "/blog/early-access-sign-ups", BlogLive.Posts.EarlyAccessSignUps, :index,
as: :blog_posts_early_access_sign_ups
live "/blog/markdown-guide", BlogLive.Posts.MarkdownGuide, :index,
as: :blog_posts_markdown_guide
end
end
# Pre-release invitations page.
# scope "/", MetamorphicWeb do
# pipe_through [:browser, :pre_release_layout]
# live "/", PageLive.Index, :index, as: :page
# end
##
## Requires ADMIN AUTHENTICATED routes.
##
scope "/odus", MetamorphicWeb do
pipe_through [:browser, :app_layout, :require_authenticated_person, :admin]
live_dashboard "/sys_dash", metrics: MetamorphicWeb.Telemetry
end
scope "/odus", MetamorphicWeb do
pipe_through [:browser, :app_layout, :require_authenticated_person, :admin]
live_session :admin,
root_layout: {MetamorphicWeb.LayoutView, :root},
on_mount: [{MetamorphicWeb.PersonLiveAuth, :admin}, MetamorphicWeb.Nav] do
live "/dashboard", DashboardLive.Admin, :admin, as: :admin_dashboard
live "/invitations", InviteLive.Admin, :admin, as: :admin_invite
live "/invitations/new", InviteLive.Admin, :admin_new, as: :admin_invite_new
live "/invitations/:id/edit", InviteLive.Admin, :admin_edit, as: :admin_invite_edit
live "/invitations/:id", InviteLive.Show, :show
live "/invitations/:id/show/edit", InviteLive.Show, :edit
live "/people/settings", PersonSettingsLive.Admin, :admin, as: :admin_settings
live "/roadmap", RoadmapLive.Admin, :admin, as: :admin_roadmap
live "/roadmap/new", RoadmapLive.Admin, :admin_new, as: :admin_roadmap_new
live "/roadmap/:id/edit", RoadmapLive.Admin, :admin_edit, as: :admin_roadmap_edit
live "/roadmap/:id/update", RoadmapLive.Admin, :admin_update, as: :admin_roadmap_update
live "/roadmap/:id/delete", RoadmapLive.Admin, :admin_delete, as: :admin_roadmap_delete
live "/support", SupportLive.Admin, :admin, as: :admin_support
end
get "/people/settings/data/download-encrypted-admin",
PersonSettingsController,
:download_encrypted_admin_data
get "/people/settings/confirm_email/:token", PersonSettingsController, :confirm_email
put "/people/settings/update_password", PersonSettingsController, :update_password
delete "/people/log_out", PersonSessionController, :delete
end
end
Marked As Solved
wkirschbaum
Another solution will be to change the url option to action. It seems like the csrf token only gets added if the action gets set.
<.form let={f} for={@conn} action={Routes.person_session_path(@conn, :create)} as={:person}>
...
</.form>
3
Also Liked
weego
We had the same issue with our activation page and had to add the csrf_input_tag in manually. I am assuming this is a bug.
2
wkirschbaum
This is the breaking change: Do not generate csrf tokens for forms with no action · phoenixframework/phoenix_live_view@e9fd7fa · GitHub
1
Popular in Questions
lets say i have a sample like
a = 20; b = 10;
if (a > b) do
{:ok, "a"}
end
if (a < b) do
{:ok, b}
end
if (a == b) do
{:ok, "equa...
New
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
If I have a post route which an argument:
post /my_post_route/:my_param1, MyController.my_post_handler
How would get the post params ...
New
can someone please explain to me how Enum.reduce works with maps
New
Hello, how can I check the Phoenix version ?
Thanks !
New
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors:
[WARN] - (starship::utils): Executing command ...
New
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
Hello!
Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
Other popular topics
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
If I have a post route which an argument:
post /my_post_route/:my_param1, MyController.my_post_handler
How would get the post params ...
New
Hi guys, i’m new in the Elixir world, and i have to say, that i love it!
i’m having some problem to understand anonymous functions with ...
New
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
Hi!
In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir?
Searched the docs for ip address and the web, no good results.
Thanks!
New
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine)
This is a plugin that adds support for Elixir to JetBrains IntelliJ...
New
What is the proper way to load a module from a file in to IEX?
In the python world, doing something like this pretty standard:
from ....
New
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including.
What is Phoenix LiveV...
New
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
New
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance










