Reconfigure session cookie (#3274)

* Reconfigure session cookie

* Allow configure secure cookie (#3277)

* Update config/runtime.exs

Co-authored-by: ruslandoga <doga.ruslan@gmail.com>

* fix runtime conf

* Revert "fix runtime conf"

This reverts commit ff37e479e4.

* Revert "Update config/runtime.exs"

This reverts commit 5d9b310b02.

* Revert "Allow configure secure cookie (#3277)"

This reverts commit 7401a2ad3f.

* Read SECURE_COOKIE with defaults per cloud/selfhost

* Include environment in cookie name

* Remove redundant option

* Format

* s/Map.replace/Map.put

* up

* One more try

* Prevent browser refreshes on socket connection error

We'll keep the log and don't make the page look dumb
even if there's some misconfiguration going on.

---------

Co-authored-by: ruslandoga <doga.ruslan@gmail.com>
This commit is contained in:
hq1 2023-08-21 11:47:11 +02:00 committed by GitHub
parent d6d4d3dd75
commit 63fabcbb5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 27 deletions

View File

@ -232,6 +232,11 @@ if byte_size(websocket_url) > 0 and
"""
end
secure_cookie =
config_dir
|> get_var_from_path_or_env("SECURE_COOKIE", if(is_selfhost, do: "false", else: "true"))
|> String.to_existing_atom()
config :plausible,
environment: env,
mailer_email: mailer_email,
@ -254,7 +259,8 @@ config :plausible, PlausibleWeb.Endpoint,
protocol_options: [max_request_line_length: 8192, max_header_value_length: 8192]
],
secret_key_base: secret_key_base,
websocket_url: websocket_url
websocket_url: websocket_url,
secure_cookie: secure_cookie
maybe_ipv6 = if System.get_env("ECTO_IPV6"), do: [:inet6], else: []

View File

@ -3,9 +3,10 @@ defmodule PlausibleWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :plausible
@session_options [
# key to be patched
key: "",
store: :cookie,
key: "_plausible_key",
signing_salt: "3IL0ob4k",
signing_salt: "I45i0SKHEku2f3tJh6y4v8gztrb/eG5KGCOe/o/AwFb7VHeuvDOn7AAq6KsdmOFM",
# 5 years, this is super long but the SlidingSessionTimeout will log people out if they don't return for 2 weeks
max_age: 60 * 60 * 24 * 365 * 5,
extra: "SameSite=Lax"
@ -16,58 +17,62 @@ defmodule PlausibleWeb.Endpoint do
#
# You should set gzip to true if you are running phx.digest
# when deploying your static files in production.
plug PlausibleWeb.Tracker
plug PlausibleWeb.Favicon
plug(PlausibleWeb.Tracker)
plug(PlausibleWeb.Favicon)
plug Plug.Static,
plug(Plug.Static,
at: "/",
from: :plausible,
gzip: false,
only: ~w(css images js favicon.ico robots.txt)
)
plug Plug.Static,
plug(Plug.Static,
at: "/kaffy",
from: :kaffy,
gzip: false,
only: ~w(assets)
)
# Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint.
if code_reloading? do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug Phoenix.CodeReloader
socket("/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket)
plug(Phoenix.LiveReloader)
plug(Phoenix.CodeReloader)
end
plug Plug.RequestId
plug PromEx.Plug, prom_ex_module: Plausible.PromEx
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
plug(Plug.RequestId)
plug(PromEx.Plug, prom_ex_module: Plausible.PromEx)
plug(Plug.Telemetry, event_prefix: [:phoenix, :endpoint])
plug Plug.Parsers,
plug(Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Phoenix.json_library()
)
plug Sentry.PlugContext
plug(Sentry.PlugContext)
plug Plug.MethodOverride
plug Plug.Head
plug(Plug.MethodOverride)
plug(Plug.Head)
plug PlausibleWeb.Plugs.RuntimeSessionAdapter, @session_options
plug(PlausibleWeb.Plugs.RuntimeSessionAdapter, @session_options)
socket "/live", Phoenix.LiveView.Socket,
socket("/live", PlausibleWeb.LiveSocket,
websocket: [
check_origin: true,
connect_info: [session: {__MODULE__, :patch_session_opts, []}]
]
)
plug CORSPlug
plug PlausibleWeb.Router
plug(CORSPlug)
plug(PlausibleWeb.Router)
def secure_cookie?, do: config!(:secure_cookie)
def websocket_url() do
:plausible
|> Application.fetch_env!(__MODULE__)
|> Keyword.fetch!(:websocket_url)
config!(:websocket_url)
end
def patch_session_opts() do
@ -75,6 +80,15 @@ defmodule PlausibleWeb.Endpoint do
# is used to inject the domain - this way we can authenticate
# websocket requests within single root domain, in case websocket_url()
# returns a ws{s}:// scheme (in which case SameSite=Lax is not applicable).
Keyword.put(@session_options, :domain, host())
@session_options
|> Keyword.put(:domain, host())
|> Keyword.put(:key, "_plausible_#{Application.fetch_env!(:plausible, :environment)}")
|> Keyword.put(:secure, secure_cookie?())
end
defp config!(key) do
:plausible
|> Application.fetch_env!(__MODULE__)
|> Keyword.fetch!(key)
end
end

View File

@ -0,0 +1,15 @@
defmodule PlausibleWeb.LiveSocket do
use Phoenix.LiveView.Socket
require Logger
def connect(params, %Phoenix.Socket{} = socket, connect_info) do
case Phoenix.LiveView.Socket.connect(params, socket, connect_info) do
{:ok, %Phoenix.Socket{private: %{connect_info: %{session: nil}}}} ->
Logger.error("Could not connect the live socket: no session found")
{:error, :socket_auth_error}
other ->
other
end
end
end

View File

@ -21,10 +21,16 @@ defmodule PlausibleWeb.Plugs.RuntimeSessionAdapter do
end
defp patch_cookie_domain(%{cookie_opts: cookie_opts} = runtime_opts) do
Map.replace(
Map.put(
runtime_opts,
:cookie_opts,
Keyword.put_new(cookie_opts, :domain, PlausibleWeb.Endpoint.host())
cookie_opts
|> Keyword.put_new(:domain, PlausibleWeb.Endpoint.host())
|> Keyword.put(
:secure,
Application.fetch_env!(:plausible, PlausibleWeb.Endpoint)[:secure_cookie]
)
)
|> Map.put(:key, "_plausible_#{Application.fetch_env!(:plausible, :environment)}")
end
end