mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-30 14:57:59 +01:00
Add TOTP support in the invalidation session plug (#87)
This commit is contained in:
parent
72f53d378d
commit
051a204d55
2 changed files with 60 additions and 3 deletions
|
@ -87,9 +87,14 @@ defmodule PhilomenaWeb.PowInvalidatedSessionPlug do
|
||||||
defp maybe_put_cache(conn, user, old_token, opts) do
|
defp maybe_put_cache(conn, user, old_token, opts) do
|
||||||
fetch_fn = Keyword.fetch!(opts, :fetch_token)
|
fetch_fn = Keyword.fetch!(opts, :fetch_token)
|
||||||
|
|
||||||
|
metadata =
|
||||||
|
conn.private
|
||||||
|
|> Map.get(:pow_session_metadata, [])
|
||||||
|
|> Keyword.take([:valid_totp_at])
|
||||||
|
|
||||||
case fetch_fn.(conn) do
|
case fetch_fn.(conn) do
|
||||||
^old_token -> conn
|
^old_token -> conn
|
||||||
_token -> put_cache(conn, user, old_token, opts)
|
_token -> put_cache(conn, {user, metadata}, old_token, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -106,8 +111,15 @@ defmodule PhilomenaWeb.PowInvalidatedSessionPlug do
|
||||||
{store, store_config} = invalidated_cache(conn, opts)
|
{store, store_config} = invalidated_cache(conn, opts)
|
||||||
|
|
||||||
case store.get(store_config, token) do
|
case store.get(store_config, token) do
|
||||||
:not_found -> conn
|
:not_found ->
|
||||||
user -> Plug.assign_current_user(conn, user, config)
|
conn
|
||||||
|
|
||||||
|
{user, metadata} ->
|
||||||
|
metadata = Keyword.merge(metadata, conn.private[:pow_session_metadata] || [])
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> Conn.put_private(:pow_session_metadata, metadata)
|
||||||
|
|> Plug.assign_current_user(user, config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,16 @@ defmodule PhilomenaWeb.PowInvalidatedSessionPlugTest do
|
||||||
|
|
||||||
assert Pow.Plug.current_user(conn).id == user.id
|
assert Pow.Plug.current_user(conn).id == user.id
|
||||||
assert Conn.get_session(conn, @session_key) != session_id
|
assert Conn.get_session(conn, @session_key) != session_id
|
||||||
|
assert metadata = conn.private[:pow_session_metadata]
|
||||||
|
refute metadata[:valid_totp_at]
|
||||||
|
|
||||||
:timer.sleep(100)
|
:timer.sleep(100)
|
||||||
conn = run_plug(init_conn, config)
|
conn = run_plug(init_conn, config)
|
||||||
|
|
||||||
assert Pow.Plug.current_user(conn).id == user.id
|
assert Pow.Plug.current_user(conn).id == user.id
|
||||||
assert Conn.get_session(conn, @session_key) == session_id
|
assert Conn.get_session(conn, @session_key) == session_id
|
||||||
|
assert metadata = conn.private[:pow_session_metadata]
|
||||||
|
refute metadata[:valid_totp_at]
|
||||||
|
|
||||||
:timer.sleep(@invalidated_ttl - 100)
|
:timer.sleep(@invalidated_ttl - 100)
|
||||||
conn = run_plug(init_conn)
|
conn = run_plug(init_conn)
|
||||||
|
@ -65,12 +69,16 @@ defmodule PhilomenaWeb.PowInvalidatedSessionPlugTest do
|
||||||
|
|
||||||
assert Pow.Plug.current_user(conn).id == user.id
|
assert Pow.Plug.current_user(conn).id == user.id
|
||||||
assert conn.cookies[@cookie_key] != persistent_session_id
|
assert conn.cookies[@cookie_key] != persistent_session_id
|
||||||
|
assert metadata = conn.private[:pow_session_metadata]
|
||||||
|
refute metadata[:valid_totp_at]
|
||||||
|
|
||||||
:timer.sleep(100)
|
:timer.sleep(100)
|
||||||
conn = run_plug(init_conn)
|
conn = run_plug(init_conn)
|
||||||
|
|
||||||
assert Pow.Plug.current_user(conn).id == user.id
|
assert Pow.Plug.current_user(conn).id == user.id
|
||||||
assert conn.cookies[@cookie_key] == persistent_session_id
|
assert conn.cookies[@cookie_key] == persistent_session_id
|
||||||
|
assert metadata = conn.private[:pow_session_metadata]
|
||||||
|
refute metadata[:valid_totp_at]
|
||||||
|
|
||||||
:timer.sleep(@invalidated_ttl - 100)
|
:timer.sleep(@invalidated_ttl - 100)
|
||||||
conn = run_plug(init_conn)
|
conn = run_plug(init_conn)
|
||||||
|
@ -79,6 +87,42 @@ defmodule PhilomenaWeb.PowInvalidatedSessionPlugTest do
|
||||||
assert conn.cookies[@cookie_key] == persistent_session_id
|
assert conn.cookies[@cookie_key] == persistent_session_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "call/2 with TOTP turned on", %{conn: init_conn, user: user} do
|
||||||
|
user =
|
||||||
|
user
|
||||||
|
|> Ecto.Changeset.change(%{otp_required_for_login: true})
|
||||||
|
|> Repo.update!()
|
||||||
|
|
||||||
|
config = Keyword.put(@config, :session_ttl_renewal, 0)
|
||||||
|
|
||||||
|
no_otp_auth_conn =
|
||||||
|
init_conn
|
||||||
|
|> prepare_session_conn(user, config)
|
||||||
|
|> init_plug(config)
|
||||||
|
|
||||||
|
assert no_otp_auth_conn.halted
|
||||||
|
|
||||||
|
init_conn =
|
||||||
|
init_conn
|
||||||
|
|> Conn.put_private(:pow_session_metadata, valid_totp_at: DateTime.utc_now())
|
||||||
|
|> prepare_session_conn(user, config)
|
||||||
|
|
||||||
|
conn = run_plug(init_conn, config)
|
||||||
|
|
||||||
|
assert Pow.Plug.current_user(conn).id == user.id
|
||||||
|
assert metadata = conn.private[:pow_session_metadata]
|
||||||
|
assert metadata[:valid_totp_at]
|
||||||
|
assert metadata[:inserted_at]
|
||||||
|
|
||||||
|
:timer.sleep(100)
|
||||||
|
conn = run_plug(init_conn, config)
|
||||||
|
|
||||||
|
assert Pow.Plug.current_user(conn).id == user.id
|
||||||
|
assert metadata = conn.private[:pow_session_metadata]
|
||||||
|
assert metadata[:valid_totp_at]
|
||||||
|
refute metadata[:inserted_at]
|
||||||
|
end
|
||||||
|
|
||||||
defp init_session_plug(conn) do
|
defp init_session_plug(conn) do
|
||||||
conn
|
conn
|
||||||
|> Map.put(:secret_key_base, String.duplicate("abcdefghijklmnopqrstuvxyz0123456789", 2))
|
|> Map.put(:secret_key_base, String.duplicate("abcdefghijklmnopqrstuvxyz0123456789", 2))
|
||||||
|
@ -97,6 +141,7 @@ defmodule PhilomenaWeb.PowInvalidatedSessionPlugTest do
|
||||||
|> Session.call(Session.init(config))
|
|> Session.call(Session.init(config))
|
||||||
|> Cookie.call(Cookie.init([]))
|
|> Cookie.call(Cookie.init([]))
|
||||||
|> PowInvalidatedSessionPlug.call(PowInvalidatedSessionPlug.init(:load))
|
|> PowInvalidatedSessionPlug.call(PowInvalidatedSessionPlug.init(:load))
|
||||||
|
|> PhilomenaWeb.TotpPlug.call(PhilomenaWeb.TotpPlug.init([]))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp run_plug(conn, config \\ @config) do
|
defp run_plug(conn, config \\ @config) do
|
||||||
|
|
Loading…
Reference in a new issue