Skip to content

Commit a3253fb

Browse files
authored
improvement: revoke stored sessions on log out (#634)
1 parent 88c35b4 commit a3253fb

File tree

10 files changed

+57
-21
lines changed

10 files changed

+57
-21
lines changed

dev/dev_web/controllers/auth_controller.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule DevWeb.AuthController do
2626
@impl true
2727
def sign_out(conn, _params) do
2828
conn
29-
|> clear_session()
29+
|> clear_session(:ash_authentication_phoenix)
3030
|> render("sign_out.html")
3131
end
3232
end

documentation/tutorials/get-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ defmodule ExampleWeb.AuthController do
116116
return_to = get_session(conn, :return_to) || ~p"/"
117117

118118
conn
119-
|> clear_session()
119+
|> clear_session(:my_app)
120120
|> redirect(to: return_to)
121121
end
122122
end

lib/ash_authentication_phoenix/controller.ex

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ defmodule AshAuthentication.Phoenix.Controller do
7777
"""
7878

7979
alias AshAuthentication.Plug.Dispatcher
80+
alias AshAuthentication.Plug.Helpers
8081
alias Plug.Conn
8182

8283
@type t :: module
@@ -107,7 +108,7 @@ defmodule AshAuthentication.Phoenix.Controller do
107108
@behaviour AshAuthentication.Phoenix.Controller
108109
@behaviour AshAuthentication.Plug
109110
import Phoenix.Controller
110-
import Plug.Conn
111+
import Plug.Conn, except: [clear_session: 1]
111112
import AshAuthentication.Phoenix.Plug
112113
import AshAuthentication.Phoenix.Controller
113114

@@ -137,15 +138,6 @@ defmodule AshAuthentication.Phoenix.Controller do
137138
|> render("failure.html")
138139
end
139140

140-
@doc false
141-
@impl true
142-
@spec sign_out(Conn.t(), map) :: Conn.t()
143-
def sign_out(conn, _params) do
144-
conn
145-
|> clear_session()
146-
|> render("sign_out.html")
147-
end
148-
149141
@doc false
150142
@impl true
151143
@spec call(Conn.t(), any) :: Conn.t()
@@ -203,7 +195,36 @@ defmodule AshAuthentication.Phoenix.Controller do
203195
end
204196
end
205197

206-
defoverridable success: 4, failure: 3, sign_out: 2
198+
defoverridable success: 4, failure: 3
207199
end
208200
end
201+
202+
defmacro clear_session(_conn) do
203+
raise """
204+
Using clear_session/1 in your `auth_controller` is deprecated. Please use `clear_session/2` instead,
205+
passing the conn and the otp_app.
206+
207+
For example:
208+
209+
conn
210+
|> clear_session(conn, :my_app)
211+
212+
213+
This ensures that session tokens & bearer tokens are revoked on logout.
214+
215+
If you wish to retain the old behavior (not advised), call `Plug.Conn.clear_session/1` directly.
216+
"""
217+
end
218+
219+
@doc """
220+
Clears the session and revokes bearer and session tokens.
221+
222+
This ensures that session tokens & bearer tokens are revoked on logout.
223+
"""
224+
def clear_session(conn, otp_app) do
225+
conn
226+
|> Helpers.revoke_bearer_tokens(otp_app)
227+
|> Helpers.revoke_session_tokens(otp_app)
228+
|> Plug.Conn.clear_session()
229+
end
209230
end

lib/ash_authentication_phoenix/plug.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ defmodule AshAuthentication.Phoenix.Plug do
4949
Helpers.revoke_bearer_tokens(conn, otp_app)
5050
end
5151

52+
@doc """
53+
Revoke all token(s) in the session.
54+
55+
A wrapper around `AshAuthentication.Plug.Helpers.revoke_session_tokens/2` with
56+
the `otp_app` as extracted from the endpoint.
57+
"""
58+
@spec revoke_session_tokens(Conn.t(), any) :: Conn.t()
59+
def revoke_session_tokens(conn, _opts) do
60+
otp_app = conn.private.phoenix_endpoint.config(:otp_app)
61+
Helpers.revoke_session_tokens(conn, otp_app)
62+
end
63+
5264
@doc """
5365
Store the actor in the connections' session.
5466
"""

lib/mix/tasks/ash_authentication_phoenix.install.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,15 @@ if Code.ensure_loaded?(Igniter) do
9898
if router do
9999
web_module = Igniter.Libs.Phoenix.web_module(igniter)
100100
overrides = Igniter.Libs.Phoenix.web_module_name(igniter, "AuthOverrides")
101+
otp_app = Igniter.Project.Application.app_name(igniter)
101102

102103
igniter
103104
|> Igniter.Project.Formatter.import_dep(:ash_authentication_phoenix)
104105
|> Igniter.compose_task("igniter.add_extension", ["phoenix"])
105106
|> setup_routes_alias()
106107
|> warn_on_missing_modules(options, argv, install?)
107108
|> do_or_explain_tailwind_changes()
108-
|> create_auth_controller()
109+
|> create_auth_controller(otp_app)
109110
|> create_overrides_module(overrides)
110111
|> add_auth_routes(overrides, options, router, web_module)
111112
|> create_live_user_auth(web_module)
@@ -318,7 +319,7 @@ if Code.ensure_loaded?(Igniter) do
318319
)
319320
end
320321

321-
defp create_auth_controller(igniter) do
322+
defp create_auth_controller(igniter, otp_app) do
322323
Igniter.Project.Module.create_module(
323324
igniter,
324325
Igniter.Libs.Phoenix.web_module_name(igniter, "AuthController"),
@@ -372,7 +373,7 @@ if Code.ensure_loaded?(Igniter) do
372373
return_to = get_session(conn, :return_to) || ~p"/"
373374
374375
conn
375-
|> clear_session()
376+
|> clear_session(:#{otp_app})
376377
|> put_flash(:info, "You are now signed out")
377378
|> redirect(to: return_to)
378379
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ defmodule AshAuthentication.Phoenix.MixProject do
118118
# Run "mix help deps" to learn about dependencies.
119119
defp deps do
120120
[
121-
{:ash_authentication, "~> 4.8"},
121+
{:ash_authentication, "~> 4.9 and >= 4.9.1"},
122122
{:ash_phoenix, "~> 2.0"},
123123
{:ash, "~> 3.0"},
124124
{:jason, "~> 1.0"},

mix.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%{
2-
"ash": {:hex, :ash, "3.5.19", "defd1c6b94475352a7b69f430b792fb64e3a9f7ca030195737bb97dc0f1311b5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.4 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.11", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.2.65 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, ">= 0.2.6 and < 1.0.0-0", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ded976230b1ef823aeb25008cc62de6545bf3ad6208cf1f3badb598fa6c01375"},
3-
"ash_authentication": {:hex, :ash_authentication, "4.9.0", "0286b5df6e5006d16811b18f0efcd691fa7895a0a3aa1b091986a61da31a2a8a", [:mix], [{:argon2_elixir, "~> 4.0", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:ash, ">= 3.4.29 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_postgres, "~> 2.0", [hex: :ash_postgres, repo: "hexpm", optional: true]}, {:assent, "~> 0.2.13", [hex: :assent, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:finch, "~> 0.19", [hex: :finch, repo: "hexpm", optional: false]}, {:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.5", [hex: :joken, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}], "hexpm", "dde0c702b26e7354d81ea4a9bb334c27ce11a59876df8c5d4d5b0bebe4b7ad4e"},
2+
"ash": {:hex, :ash, "3.5.21", "389303c193962d67fd59da18a3557f5015fdfdaeddaa77150db539bc7203d1a1", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.4 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.11", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.2.65 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, ">= 0.2.6 and < 1.0.0-0", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cb90005d1972e22d0d2ae514394e43e0d67cce18c4485595aa3d3e4bbf25260f"},
3+
"ash_authentication": {:hex, :ash_authentication, "4.9.1", "f5465abb973777ed7150c94f89902d0050d4debca1cf6ba8930e18e4de379a08", [:mix], [{:argon2_elixir, "~> 4.0", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:ash, ">= 3.4.29 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_postgres, "~> 2.0", [hex: :ash_postgres, repo: "hexpm", optional: true]}, {:assent, "~> 0.2.13", [hex: :assent, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:finch, "~> 0.19", [hex: :finch, repo: "hexpm", optional: false]}, {:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.5", [hex: :joken, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}], "hexpm", "e5022a1d149c04fc529277a8174f0004b617d5530f080ce4e98a9452c5586970"},
44
"ash_phoenix": {:hex, :ash_phoenix, "2.3.6", "c2bea1673af52f305b2fe0c04999bd1f0dc8e127d4757a3d7f42d0b9dea16a7a", [:mix], [{:ash, ">= 3.5.13 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:igniter, "~> 0.6", [hex: :igniter, repo: "hexpm", optional: true]}, {:inertia, "~> 2.3", [hex: :inertia, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.6 or ~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.3 or ~> 1.0-rc.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:spark, ">= 2.2.29 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "6923dca70fe1d533864134999f4d9c5c59ef745a6b50982d42d60c18966474cd"},
55
"assent": {:hex, :assent, "0.2.13", "11226365d2d8661d23e9a2cf94d3255e81054ff9d88ac877f28bfdf38fa4ef31", [:mix], [{:certifi, ">= 0.0.0", [hex: :certifi, repo: "hexpm", optional: true]}, {:finch, "~> 0.15", [hex: :finch, repo: "hexpm", optional: true]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:req, "~> 0.4", [hex: :req, repo: "hexpm", optional: true]}, {:ssl_verify_fun, ">= 0.0.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: true]}], "hexpm", "bf9f351b01dd6bceea1d1f157f05438f6765ce606e6eb8d29296003d29bf6eab"},
66
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},

test/mix/tasks/ash_authentication_phoenix.install_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ defmodule Mix.Tasks.AshAuthenticationPhoenix.InstallTest do
142142
return_to = get_session(conn, :return_to) || ~p"/"
143143
144144
conn
145-
|> clear_session()
145+
|> clear_session(:test)
146146
|> put_flash(:info, "You are now signed out")
147147
|> redirect(to: return_to)
148148
end

test/support/accounts/user.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ defmodule Example.Accounts.User do
9696
end
9797

9898
authentication do
99+
session_identifier(:jti)
100+
99101
add_ons do
100102
confirmation :confirm do
101103
monitor_fields([:email])

test/support/auth_controller.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ defmodule AshAuthentication.Phoenix.Test.AuthController do
2626
@impl true
2727
def sign_out(conn, _params) do
2828
conn
29-
|> clear_session()
29+
|> clear_session(:ash_authentication_phoenix)
3030
|> render(:signed_out)
3131
end
3232
end

0 commit comments

Comments
 (0)