Packages
livebook
0.6.3
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Current section
Files
Jump to
Current section
Files
lib/livebook_web/plugs/auth_plug.ex
defmodule LivebookWeb.AuthPlug do
@moduledoc false
@behaviour Plug
import Plug.Conn
import Phoenix.Controller
@impl true
def init(opts), do: opts
@impl true
def call(conn, _opts) do
mode = Livebook.Config.auth_mode()
if authenticated?(conn, mode) do
conn
else
authenticate(conn, mode)
end
end
@doc """
Stores in the session the secret for the given mode.
"""
def store(conn, mode, value) do
put_session(conn, key(conn.port, mode), hash(value))
end
@doc """
Checks if given connection is already authenticated.
"""
@spec authenticated?(Plug.Conn.t(), Livebook.Config.auth_mode()) :: boolean()
def authenticated?(conn, mode) do
authenticated?(get_session(conn), conn.port, mode)
end
@doc """
Checks if the given session is authenticated.
"""
@spec authenticated?(map(), non_neg_integer(), Livebook.Config.auth_mode()) :: boolean()
def authenticated?(session, port, mode)
def authenticated?(_session, _port, :disabled) do
true
end
def authenticated?(session, port, mode) when mode in [:token, :password] do
secret = session[key(port, mode)]
is_binary(secret) and Plug.Crypto.secure_compare(secret, expected(mode))
end
defp authenticate(conn, :password) do
redirect_to_authenticate(conn)
end
defp authenticate(conn, :token) do
{token, query_params} = Map.pop(conn.query_params, "token")
if is_binary(token) and Plug.Crypto.secure_compare(hash(token), expected(:token)) do
# Redirect to the same path without query params
conn
|> store(:token, token)
|> redirect(to: path_with_query(conn.request_path, query_params))
|> halt()
else
redirect_to_authenticate(conn)
end
end
defp redirect_to_authenticate(conn) do
conn
|> then(fn
%{method: "GET"} -> put_session(conn, :redirect_to, current_path(conn))
conn -> conn
end)
|> redirect(to: "/authenticate")
|> halt()
end
defp path_with_query(path, params) when params == %{}, do: path
defp path_with_query(path, params), do: path <> "?" <> URI.encode_query(params)
defp key(port, mode), do: "#{port}:#{mode}"
defp expected(mode), do: hash(Application.fetch_env!(:livebook, mode))
defp hash(value), do: :crypto.hash(:sha256, value)
end