You should be using live_session with an on_mount
hook to ensure the user is authenticated.
The following is what mix phx.gen.auth
adds to myapp_web/router.ex
, and is worth running in a fresh project to understand all of the code it generates:
scope "/", MyAppWeb do
pipe_through [:browser, :redirect_if_user_is_authenticated]
live_session :redirect_if_user_is_authenticated,
on_mount: [{MyAppWeb.UserAuth, :redirect_if_user_is_authenticated}] do
live "/users/register", UserRegistrationLive, :new
live "/users/log_in", UserLoginLive, :new
live "/users/reset_password", UserForgotPasswordLive, :new
live "/users/reset_password/:token", UserResetPasswordLive, :edit
end
post "/users/log_in", UserSessionController, :create
end
scope "/", MyAppWeb do
pipe_through [:browser, :require_authenticated_user]
live_session :require_authenticated_user,
on_mount: [{MyAppWeb.UserAuth, :ensure_authenticated}] do
live "/users/settings", UserSettingsLive, :edit
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
end
scope "/", MyAppWeb do
pipe_through [:browser]
delete "/users/log_out", UserSessionController, :delete
live_session :current_user,
on_mount: [{MyAppWeb.UserAuth, :mount_current_user}] do
live "/users/confirm/:token", UserConfirmationLive, :edit
live "/users/confirm", UserConfirmationInstructionsLive, :new
end
end
end
The relevant hooks used above are in MyAppWeb.UserAuth
, generated in myapp_web/user_auth.ex
A key step when signing out a user is broadcasting the disconnect event to ensure all websocket channels on all nodes are also disconnected, which is already done for you in myapp_web/user_auth.ex
.
Getting authentication right an handling all edge cases is hard, IMO its better start with a good foundation and customise from there.