Tutorial

Set session values from LiveView

liveview session

Basically, every web application has a need to store session values for the user visiting the page. At least with some sort of authentication, you store an authentication token or current user ID so you can retrieve the user for every request. There are also other use cases like preferences regarding language or dark mode. In a live view application, which mainly communicates over web sockets, you can't set session values directly. However, as you can see here, when I click the Set Session button and refresh the page, the value is still accessible through the user's browser session. So in this video, I will go through how you can easily add this in an elegant way.

Setting Up the StoreSession Controller

As mentioned, I can't set a session value directly from the live view. I need to create a controller that I can post to, which in turn can set a session value for the user. The controller supports both encrypted and non-encrypted params, though I strongly recommend using encryption in production:

defmodule TutorialWeb.StoreSessionController do
use TutorialWeb, :controller
def create(conn, %{"encrypted" => token}) do
updated_conn =
case decrypt(token) do
{:ok, params} ->
Enum.reduce(params, conn, fn {key, value}, acc_conn ->
put_session(acc_conn, key, value)
end)
_ ->
conn
end
send_resp(updated_conn, 200, "")
end
# Note: For development only. Use encryption in production
def create(conn, params) do
updated_conn = Enum.reduce(params, conn, fn {key, value}, acc_conn ->
put_session(acc_conn, String.to_existing_atom(key), value)
end)
send_resp(updated_conn, 200, "")
end
defp decrypt(token) do
Phoenix.Token.decrypt(TutorialWeb.Endpoint, "secret_key", token, max_age: 600)
end
end

Note that for security reasons, we use String.to_existing_atom(key). We do that for security reasons, so this means that the atom needs to have been defined before. Also, for security, consider:

  1. Use a whitelist of allowed session keys
  2. Store the secret key in config
  3. Adjust the token max age based on your needs

Adding the Event Listener

Even though I added the controller, we can't post to it directly. Instead, we can dispatch a JavaScript event from inside the live view. So here in the app JavaScript file, I will add an event listener that listens for these events, takes the payload, and posts it to the new store session route:

window.addEventListener("phx:store-session", (event) => {
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
fetch('/store-session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token
},
body: JSON.stringify(event.detail)
})
})

One thing to note here is that I grabbed the CSRF token from the meta tag in the DOM and use it as a header when posting. That is a way for Phoenix to verify that the post is legitimate.

Configuring a Route for Session Storage

Before I can post to the controller, I need to set up a route for it. Depending on your app and your security concerns, you can put this behind an authenticated pipeline:

scope "/", TutorialWeb do
pipe_through :browser
post "/store-session", StoreSessionController, :create
end

LiveView Event Trigger Example

The final piece of the puzzle is triggering the session update from LiveView. By emitting a custom event, we can communicate with our JavaScript hook to initiate the session storage process. Here’s an example of how this is accomplished in LiveView:

def handle_event("demo", _param, socket) do
{
:noreply,
socket
|> push_event("store-session", %{encrypted: encrypt(%{my_key: "My Value"})})
}
end
defp encrypt(payload) do
Phoenix.Token.encrypt(TutorialWeb.Endpoint, "secret_key", payload)
end

Conclusion

So now we have overcome one of the limitations in Phoenix LiveView regarding session management. By combining a small amount of JavaScript with a custom controller, we can securely set session values directly from LiveView. I hope this helps you in your application.

Related Tutorials

Published 11 Apr

Activity Tracking in Phoenix LiveView

Most SaaS apps need some form of activity tracking — who did what and when. In this tutorial, we'll build an automatic activity tracking system that..

Published 11 Apr

Rendering an Activity Feed in Phoenix LiveView

In the previous tutorial, we built an automatic activity tracking system that records events whenever a tracked schema is inserted, updated, or dele..