Join embeds over a socket that doesn't need the session cookie

2f6152a · Gabriel Morell · 2026-10-13 15:02

6 files +14 -1
Message
{commit_body(@commit)}

Files changed

modified assets/js/app.js
+5 −1
@@ -26,7 +26,11 @@ import {hooks as colocatedHooks} from "phoenix-colocated/diogramos"
26 26 import topbar from "../vendor/topbar"
27 27
28 28 const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
29 −const liveSocket = new LiveSocket("/live", Socket, {
29 +// Embeds are usually framed by another site, where the browser withholds
30 +// the (SameSite=Lax) session cookie, so they join over a socket that does
31 +// not ask for one. See DiogramosWeb.Endpoint.
32 +const livePath = window.location.pathname.startsWith("/embed/") ? "/live-embed" : "/live"
33 +const liveSocket = new LiveSocket(livePath, Socket, {
30 34 longPollFallbackMs: 2500,
31 35 params: {_csrf_token: csrfToken},
32 36 hooks: {...colocatedHooks},
modified lib/diogramos_web/endpoint.ex
+9 −0
@@ -21,6 +21,15 @@ defmodule DiogramosWeb.Endpoint do
21 21 websocket: [connect_info: [:uri, :x_headers, session: @session_options]],
22 22 longpoll: [connect_info: [:uri, :x_headers, session: @session_options]]
23 23
24 + # Embeds, framed on third-party pages. Browsers don't send the Lax session
25 + # cookie into a cross-site iframe, and without it /live refuses the join,
26 + # so the embed would never leave its static render. Embeds are public by
27 + # token and read no session, so this socket doesn't load one: anything
28 + # joined over it sees a logged-out visitor.
29 + socket "/live-embed", Phoenix.LiveView.Socket,
30 + websocket: true,
31 + longpoll: true
32 +
24 33 # Native clients. Authenticates with an "api" bearer token in the query
25 34 # string rather than the browser session, so it deliberately does not
26 35 # share the LiveView socket's connect_info.

Parents: 8823810