Skip to content

Commit 99a0262

Browse files
author
Abdessabour Moutik
committed
feat: final implementation hopefully we can put this to rest
1 parent e7c4877 commit 99a0262

File tree

3 files changed

+55
-35
lines changed

3 files changed

+55
-35
lines changed

lib/ash_authentication_phoenix/controller.ex

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ defmodule AshAuthentication.Phoenix.Controller do
1515
use MyAppWeb, :controller
1616
use AshAuthentication.Phoenix.Controller
1717
18-
def success(conn, _activity, user, _token) do
18+
def success(conn, _activity, user, token) do
1919
conn
2020
|> store_in_session(user)
2121
|> assign(:current_user, user)
22+
|> set_live_socket_id(token)
2223
|> redirect(to: Routes.page_path(conn, :index))
2324
end
2425
@@ -78,6 +79,9 @@ defmodule AshAuthentication.Phoenix.Controller do
7879

7980
alias AshAuthentication.Plug.Dispatcher
8081
alias AshAuthentication.Plug.Helpers
82+
83+
alias AshAuthentication.TokenResource.Info
84+
alias AshAuthentication.Jwt
8185
alias Plug.Conn
8286

8387
@type t :: module
@@ -227,4 +231,24 @@ defmodule AshAuthentication.Phoenix.Controller do
227231
|> Helpers.revoke_session_tokens(otp_app)
228232
|> Plug.Conn.clear_session()
229233
end
234+
235+
@doc """
236+
Set the live socket id so we can send disconnects from the server when the token is revoked.
237+
238+
This ensures that the user can't use the application with revoked tokens.
239+
"""
240+
def set_live_socket_id(conn, token) do
241+
with {:ok, claims} <- Jwt.peek(token),
242+
otp_app <- conn.private.phoenix_endpoint.config(:otp_app),
243+
{:ok, resource} <- Jwt.token_to_resource(token, otp_app),
244+
{:ok, token_resource} <-
245+
AshAuthentication.Info.authentication_tokens_token_resource(resource),
246+
{:ok, template_fn} <-
247+
Info.token_live_socket_id_template(token_resource) do
248+
conn
249+
|> Plug.Conn.put_session(:live_socket_id, template_fn.(claims))
250+
else
251+
_ -> conn
252+
end
253+
end
230254
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
defmodule AshAuthentication.Phoenix.TokenRevocationNotifier do
2+
use Ash.Notifier
3+
alias AshAuthentication.TokenResource.Info
4+
require Logger
5+
6+
def notify(%Ash.Notifier.Notification{
7+
data: %{subject: "user"}
8+
}),
9+
do: :ok
10+
11+
def notify(%Ash.Notifier.Notification{
12+
data: data,
13+
resource: token_resource
14+
}) do
15+
with {:ok, template_fn} <- Info.token_live_socket_id_template(token_resource),
16+
socket_id <- template_fn.(data),
17+
{:ok, endpoints} when endpoints != [] <- Info.token_endpoints(token_resource) do
18+
endpoints |> Enum.each(&apply(&1, :broadcast, [socket_id, "disconnect", %{}]))
19+
end
20+
end
21+
end

lib/mix/tasks/ash_authentication_phoenix.install.ex

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,7 @@ if Code.ensure_loaded?(Igniter) do
9595
"Which Phoenix router should be modified to allow authentication?"
9696
)
9797

98-
with {igniter, router}
99-
when not is_nil(router) <-
100-
Igniter.Libs.Phoenix.select_router(
101-
igniter,
102-
"Which Phoenix router should be modified to allow authentication?"
103-
),
104-
{igniter, [endpoint | _]} <-
105-
Igniter.Libs.Phoenix.endpoints_for_router(
106-
igniter,
107-
router
108-
) do
98+
if router do
10999
web_module = Igniter.Libs.Phoenix.web_module(igniter)
110100
overrides = Igniter.Libs.Phoenix.web_module_name(igniter, "AuthOverrides")
111101
otp_app = Igniter.Project.Application.app_name(igniter)
@@ -116,26 +106,17 @@ if Code.ensure_loaded?(Igniter) do
116106
|> setup_routes_alias()
117107
|> warn_on_missing_modules(options, argv, install?)
118108
|> do_or_explain_tailwind_changes()
119-
|> create_auth_controller(otp_app, endpoint)
109+
|> create_auth_controller(otp_app)
120110
|> create_overrides_module(overrides)
121111
|> add_auth_routes(overrides, options, router, web_module)
122112
|> create_live_user_auth(web_module)
123113
else
124-
{igniter, nil} ->
125-
igniter
126-
|> Igniter.add_warning("""
127-
AshAuthenticationPhoenix installer could not find a Phoenix router. Skipping installation.
128-
129-
Set up a phoenix router and reinvoke the installer with `mix igniter.install ash_authentication_phoenix`.
130-
""")
131-
132-
{igniter, []} ->
133-
igniter
134-
|> Igniter.add_warning("""
135-
AshAuthenticationPhoenix installer could not find any Phoenix endpoints attached to the router you selected. Skipping installation.
114+
igniter
115+
|> Igniter.add_warning("""
116+
AshAuthenticationPhoenix installer could not find a Phoenix router. Skipping installation.
136117
137-
Set up a phoenix endpoint and reinvoke the installer with `mix igniter.install ash_authentication_phoenix`.
138-
""")
118+
Set up a phoenix router and reinvoke the installer with `mix igniter.install ash_authentication_phoenix`.
119+
""")
139120
end
140121
end
141122

@@ -345,7 +326,7 @@ if Code.ensure_loaded?(Igniter) do
345326
)
346327
end
347328

348-
defp create_auth_controller(igniter, otp_app, endpoint) do
329+
defp create_auth_controller(igniter, otp_app) do
349330
Igniter.Project.Module.create_module(
350331
igniter,
351332
Igniter.Libs.Phoenix.web_module_name(igniter, "AuthController"),
@@ -363,12 +344,10 @@ if Code.ensure_loaded?(Igniter) do
363344
_ -> "You are now signed in"
364345
end
365346
366-
{:ok, %{"jti" => jti}} = AshAuthentication.Jwt.peek(token)
367-
368347
conn
369348
|> delete_session(:return_to)
370349
|> store_in_session(user)
371-
|> put_session(:live_socket_id, "users_socket:\#{jti}")
350+
|> set_live_socket_id(token)
372351
# If your resource has a different name, update the assign name here (i.e :current_admin)
373352
|> assign(:current_user, user)
374353
|> put_flash(:info, message)
@@ -401,14 +380,10 @@ if Code.ensure_loaded?(Igniter) do
401380
def sign_out(conn, _params) do
402381
return_to = get_session(conn, :return_to) || ~p"/"
403382
404-
live_socket_id =
405-
get_session(conn, :live_socket_id)
406-
407383
conn
408384
|> clear_session(:#{otp_app})
409385
|> put_flash(:info, "You are now signed out")
410386
|> redirect(to: return_to)
411-
|> tap(fn _ -> #{inspect(endpoint)}.broadcast(live_socket_id, "disconnect", %{}) end)
412387
end
413388
"""
414389
)

0 commit comments

Comments
 (0)