Allow Livebook to run inside iframes (#1520)

This commit is contained in:
Alexandre de Souza 2022-11-10 12:02:59 -03:00 committed by GitHub
parent 936146e52c
commit 1cd92366d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 3 deletions

View file

@ -27,6 +27,7 @@ RUN mix do deps.get, deps.compile
COPY rel rel
COPY static static
COPY iframe/priv/static/iframe iframe/priv/static/iframe
COPY proto proto
COPY lib lib
# We need README.md during compilation
# (look for @external_resource "README.md")

View file

@ -206,6 +206,9 @@ The following environment variables configure Livebook:
* LIVEBOOK_SHUTDOWN_ENABLED - controls if a shutdown button should be shown
in the homepage. Set it to "true" to enable it.
* LIVEBOOK_WITHIN_IFRAME - controls if the application is running inside an
iframe. Set it to "true" to enable it.
* LIVEBOOK_TOKEN_ENABLED - controls whether token authentication is enabled.
Enabled by default unless `LIVEBOOK_PASSWORD` is set. Set it to "false" to
disable it.

View file

@ -27,6 +27,7 @@ config :livebook,
feature_flags: [],
plugs: [],
shutdown_enabled: false,
within_iframe: false,
storage: Livebook.Storage.Ets
# Import environment specific config. This must remain at the bottom

View file

@ -122,6 +122,10 @@ defmodule Livebook do
config :livebook, :shutdown_enabled, true
end
if Livebook.Config.boolean!("LIVEBOOK_WITHIN_IFRAME", false) do
config :livebook, :within_iframe, true
end
config :livebook,
:default_runtime,
Livebook.Config.default_runtime!("LIVEBOOK_DEFAULT_RUNTIME") ||

View file

@ -114,6 +114,14 @@ defmodule Livebook.Config do
Application.fetch_env!(:livebook, :shutdown_enabled)
end
@doc """
Returns whether the application is running inside an iframe.
"""
@spec within_iframe?() :: boolean()
def within_iframe? do
Application.fetch_env!(:livebook, :within_iframe)
end
@doc """
Returns the application service name.
"""

View file

@ -7,8 +7,7 @@ defmodule LivebookWeb.Endpoint do
@session_options [
store: :cookie,
key: "_livebook_key",
signing_salt: "deadbook",
same_site: "Lax"
signing_salt: "deadbook"
]
# Don't check the origin as we don't know how the web app is gonna be accessed.
@ -78,13 +77,23 @@ defmodule LivebookWeb.Endpoint do
plug Plug.MethodOverride
plug Plug.Head
plug Plug.Session, @session_options
plug :session
# Run custom plugs from the app configuration
plug LivebookWeb.ConfiguredPlug
plug LivebookWeb.Router
@plug_session Plug.Session.init(@session_options ++ [same_site: "Lax"])
@plug_session_iframe Plug.Session.init(@session_options ++ [same_site: "None", secure: true])
def session(conn, _opts) do
if Livebook.Config.within_iframe?() do
Plug.Session.call(conn, @plug_session_iframe)
else
Plug.Session.call(conn, @plug_session)
end
end
@plug_ssl Plug.SSL.init(host: {Application, :get_env, [:livebook, :force_ssl_host, nil]})
def force_ssl(conn, _opts) do
force_ssl_host = Application.get_env(:livebook, :force_ssl_host, nil)

View file

@ -9,6 +9,7 @@ defmodule LivebookWeb.Router do
plug :put_root_layout, {LivebookWeb.LayoutView, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :within_iframe_secure_headers
end
pipeline :auth do
@ -18,6 +19,7 @@ defmodule LivebookWeb.Router do
pipeline :js_view_assets do
plug :put_secure_browser_headers
plug :within_iframe_secure_headers
end
# The /public namespace includes routes with no authentication.
@ -102,4 +104,12 @@ defmodule LivebookWeb.Router do
get "/", AuthController, :index
post "/", AuthController, :authenticate
end
defp within_iframe_secure_headers(conn, _opts) do
if Livebook.Config.within_iframe?() do
delete_resp_header(conn, "x-frame-options")
else
conn
end
end
end