I have this live view wherein I'm trying to do a plug which I've used in other, non-live, parts of my application:
defmodule MyApp123Web.MyLive do
use MyApp123Web, :live_view
# TODO
plug MyApp123Web.RequireAuthentication
===>
** (CompileError): undefined function plug/1 (there is no such import)
Is this a right approach for a live view in the first place? If not, how would it have to be implemented for a live view in a simple way?
My plug is this:
defmodule MyApp123Web.RequireAuthentication do
import Plug.Conn
def init(options), do: options
def call(conn, _opts) do
user = conn.assigns[:current_user]
if is_nil(user) do
|> Phoenix.Controller.redirect(conn, to: "/login")
|> halt()
else
conn
end
end
end
update 1
I have a few existing non-live routes, or a scope, that requires authentication already. How to incorporate the live-view ones with those?
scope "/my", App123Web, as: :my do
pipe_through [:browser, :csrf, :require_authentication]
get "/", My.DashboardController, :index
get "/index", My.DashboardController, :index2
# ???
live_session ???? do
???
end
Will a live_session
inside this scope
even have to be require authentication itself?
As pointed out in this guide, a plug isn't enough for a liveview and you also need to check authentication on mount:
LiveView begins its life-cycle as a regular HTTP request. Then a stateful connection is established. Both the HTTP request and the stateful connection receive the client data via parameters and session. This means that any session validation must happen both in the HTTP request (plug pipeline) and the stateful connection (LiveView mount).
As explained in this same article, you can define a reusable mount hook like:
defmodule MyAppWeb.UserLiveAuth do
import Phoenix.LiveView
def on_mount(:default, _params, %{"user_id" => user_id} = _session, socket) do
socket = assign_new(socket, :current_user, fn ->
Accounts.get_user!(user_id)
end)
if socket.assigns.current_user.confirmed_at do
{:cont, socket}
else
{:halt, redirect(socket, to: "/login")}
end
end
end
This hook can then simply be used either directly in your live view using Phoenix.LiveView.on_mount/1
, or in the router with Phoenix.LiveView.Router.live_session/3
:
live_session :default, on_mount: MyAppWeb.UserLiveAuth do
live "/foo", FooLive, :index
end