Login User With LiveView

The initial phx.gen.auth generates the complete user authentication using Phoenix regular Views. Nothing LiveView about it. I am trying to register the user using a LiveView. Here is the “save” event of the LiveView

def handle_event("save", %{"user" => user_params}, socket) do
    case Accounts.register_user(user_params) do
      {:ok, user} ->
        {:ok, _} =
          Accounts.deliver_user_confirmation_instructions(
            user,
            &Routes.user_confirmation_url(socket, :edit, &1)
          )
        socket
        |> put_flash(
          :info,
          "You are registered and a confirmation email is sent. Check your email."
        )
        |> UserAuth.log_in_user(socket, user)
    end
  end

I am getting an weird error that UserToken.user_id in insert does not match type :id. However, the same code is working with a regular view. Any idea what mistake I am committing?
The UserAuth module is same as what is generated.

You cannot use liveview for this because You don’t have access to session.

In fact, You can with some hack… but it implies going to a non liveview controller to set the session. and return back to liveview.

There is a new live_session, that might help simplify auth a bit.

1 Like

@kokolegorille is right, it is all about the session. Bruce at Groxio did a great video about it here Liveview Auth

2 Likes

I’m trying to understand a bit of code to use Liveview in user registration. In my example I have used mix phx.gen.auth and moved the registration to a liveview module.

  def handle_event("save", %{"password_credential" => user_params}, socket) do
    case Accounts.register_user_with_password_credential(user_params) do
      {:ok, password_credential, _saga_results} ->
        password_credential = Repo.preload(password_credential, :user)

        {:ok, _} =
          Accounts.deliver_user_confirmation_instructions(
            password_credential,
            &Routes.user_confirmation_url(socket, :edit, &1)
          )

      # conn
      # |> put_flash(:info, "User created successfully.")
      # |> UserAuth.log_in_user(password_credential.user)

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign(socket, changeset: changeset)}
    end
  end

I’ve been stuck for a few hours trying to grok this but I just can’t understand the working code we have and even trying to create a new example to try to grok it failed me haha, appreciate any help making this work so I can finally understand.

How can I UserAuth.log_in_user if @conn is not available in liveview? :thinking:

EDIT: I think I get it… We use phx-trigger-action to call the plain old controller version of login which does have the @conn. I’ll try this out and if so write a blog post cause I imagine a lot of people have trouble with this.

        <.form
          id="login-form"
          let={f}
          for={@changeset}
          action={Routes.user_session_path(@socket, :create, user_return_to: @user_return_to)}
          as={:user}
          phx-submit="login"
          phx-change="validate"
          phx-trigger-action={@trigger_login}

Alright it works that was the bit I was not grokking. Blogpost incoming.

I think the following might also be useful:

2 Likes