You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was trying to use ash_authentication, ash_authentication_phoenix, and beacon in such a way that I could put the Beacon Admin functionality behind an Ash authentication. The desired behaviour I was after was for any request to something like /admin/cms to first of all trigger the usual authentication workflow, and then redirect to the originally requested URL.
After a very long chat [0] with @zachdaniel and @leandrocp today, there were a few changes made to both ash_authentication_phoenix and beacon to allow for scoping the BeaconCMS admin pages so that they trigger an ash_authentication workflow.
The results of that mean that you can now do something like this:
The only problem with this is that the default ash_authentication behaviour is that the app then returns to the page specified in MyappWeb.AuthController.success/4 like this:
defmoduleMyappWeb.AuthControllerdouseMyappWeb,:controlleruseAshAuthentication.Phoenix.Controllerdefsuccess(conn,activity,user,_token)doreturn_to=get_session(conn,:return_to)||~p"/app"message=caseactivitydo{:confirm_new_user,:confirm}->"Your email address has now been confirmed"{:password,:reset}->"Your password has successfully been reset"_->"You are now signed in"endconn|>delete_session(:return_to)|>store_in_session(user)|>assign(:current_user,user)|>put_flash(:info,message)|>redirect(to: return_to)enddeffailure(conn,activity,reason)domessage=case{activity,reason}do{_,%AshAuthentication.Errors.AuthenticationFailed{caused_by: %Ash.Error.Forbidden{errors: [%AshAuthentication.Errors.CannotConfirmUnconfirmedUser{}]}}}->""" You have already signed in another way, but have not confirmed your account. You can confirm your account using the link we sent to you, or by resetting your password. """_->"Incorrect email or password"endconn|>put_flash(:error,message)|>redirect(to: ~p"/sign-in")enddefsign_out(conn,_params)doconn|>delete_session(:return_to)|>clear_session()|>put_flash(:info,"You are now signed out")|>redirect(to: ~p"/")endend
Unless, that is, you can inject return_to into the session somehow. After a bit of guidance from @zachdaniel we came up with a solution that I know is not perfect, but kind of works. Well, almost kind of.
First I made a new plug:
defmoduleMyappWebb.Plugs.SetReturnToBasedOnUriPlugdo@moduledoc""" A plug that sets the session's `:return_to` key to the current URI. This is useful for redirecting users back to the original page after authentication or other actions. """importPlug.Conn@behaviourPlug@impltrue@specinit(Keyword.t())::Keyword.t()definit(opts),do: opts@impltrue@speccall(Plug.Conn.t(),Keyword.t())::Plug.Conn.t()defcall(conn,_opts)doput_session(conn,:return_to,current_uri(conn))end@docfalse@speccurrent_uri(Plug.Conn.t())::String.t()defpcurrent_uri(%Plug.Conn{request_path: path,query_string: ""}),do: pathdefpcurrent_uri(%Plug.Conn{request_path: path,query_string: query}),do: "#{path}?#{query}"end
What is happening now is that that put_session(conn, :return_to, return_to) call ends up leaving the return_to value set in the session so that any subsequent sign-out/sign-in attempt sees the old value and ends up returning to that page even if the user just tries to sign in to /app.
I am trying to track that down now, but in the meantime, if there is a better way to manage this return_to functionality, I'd love to hear about it.
UPDATE-MDS20250218: Tidied up SetReturnToBasedOnUriPlug after re-examining the (very rough) first version of the code.
UPDATE-MFS20250217: I noticed a very obvious bug in the first version, which I have now edited. The code above works from the perspective of :return_to functionality. Just waiting on the fix for AshAuth+Beacon integration.
I was trying to use ash_authentication, ash_authentication_phoenix, and beacon in such a way that I could put the Beacon Admin functionality behind an Ash authentication. The desired behaviour I was after was for any request to something like
/admin/cms
to first of all trigger the usual authentication workflow, and then redirect to the originally requested URL.After a very long chat [0] with @zachdaniel and @leandrocp today, there were a few changes made to both ash_authentication_phoenix and beacon to allow for scoping the BeaconCMS admin pages so that they trigger an ash_authentication workflow.
The results of that mean that you can now do something like this:
The only problem with this is that the default ash_authentication behaviour is that the app then returns to the page specified in
MyappWeb.AuthController.success/4
like this:Unless, that is, you can inject
return_to
into the session somehow. After a bit of guidance from @zachdaniel we came up with a solution that I know is not perfect, but kind of works. Well, almost kind of.First I made a new plug:
And then I added a new pipeline to my router:
And then updated the
/admin/cms
scope to look like this:Now, this almost works, but not quite.
What is happening now is that that
put_session(conn, :return_to, return_to)
call ends up leaving thereturn_to
value set in the session so that any subsequent sign-out/sign-in attempt sees the old value and ends up returning to that page even if the user just tries to sign in to/app
.I am trying to track that down now, but in the meantime, if there is a better way to manage this
return_to
functionality, I'd love to hear about it.UPDATE-MDS20250218: Tidied up
SetReturnToBasedOnUriPlug
after re-examining the (very rough) first version of the code.UPDATE-MFS20250217: I noticed a very obvious bug in the first version, which I have now edited. The code above works from the perspective of
:return_to
functionality. Just waiting on the fix for AshAuth+Beacon integration.References:
[0]: 20250216 Slack conversation that motivated the idea: https://elixir-lang.slack.com/archives/C02T04D147M/p1739642323323869
The text was updated successfully, but these errors were encountered: