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