Fix OIDC account linking by using SystemActor in LinkOidcAccountLive
- Add SystemActor to all Ash operations in LinkOidcAccountLive - Enables user lookup, reload, and oidc_id linking during OIDC flow - User is not yet logged in during linking, so SystemActor provides authorization
This commit is contained in:
parent
fe07a4e955
commit
21d8d65492
1 changed files with 16 additions and 4 deletions
|
|
@ -20,10 +20,13 @@ defmodule MvWeb.LinkOidcAccountLive do
|
|||
|
||||
@impl true
|
||||
def mount(_params, session, socket) do
|
||||
# Use SystemActor for authorization during OIDC linking (user is not yet logged in)
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
with user_id when not is_nil(user_id) <- Map.get(session, "oidc_linking_user_id"),
|
||||
oidc_user_info when not is_nil(oidc_user_info) <-
|
||||
Map.get(session, "oidc_linking_user_info"),
|
||||
{:ok, user} <- Ash.get(Mv.Accounts.User, user_id) do
|
||||
{:ok, user} <- Ash.get(Mv.Accounts.User, user_id, actor: system_actor) do
|
||||
# Check if user is passwordless
|
||||
if passwordless?(user) do
|
||||
# Auto-link passwordless user immediately
|
||||
|
|
@ -46,9 +49,12 @@ defmodule MvWeb.LinkOidcAccountLive do
|
|||
end
|
||||
|
||||
defp reload_user!(user_id) do
|
||||
# Use SystemActor for authorization during OIDC linking (user is not yet logged in)
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
Mv.Accounts.User
|
||||
|> Ash.Query.filter(id == ^user_id)
|
||||
|> Ash.read_one!()
|
||||
|> Ash.read_one!(actor: system_actor)
|
||||
end
|
||||
|
||||
defp reset_password_form(socket) do
|
||||
|
|
@ -58,13 +64,16 @@ defmodule MvWeb.LinkOidcAccountLive do
|
|||
defp auto_link_passwordless_user(socket, user, oidc_user_info) do
|
||||
oidc_id = Map.get(oidc_user_info, "sub") || Map.get(oidc_user_info, "id")
|
||||
|
||||
# Use SystemActor for authorization (passwordless user auto-linking)
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
case user.id
|
||||
|> reload_user!()
|
||||
|> Ash.Changeset.for_update(:link_oidc_id, %{
|
||||
oidc_id: oidc_id,
|
||||
oidc_user_info: oidc_user_info
|
||||
})
|
||||
|> Ash.update() do
|
||||
|> Ash.update(actor: system_actor) do
|
||||
{:ok, updated_user} ->
|
||||
Logger.info(
|
||||
"Passwordless account auto-linked to OIDC: user_id=#{updated_user.id}, oidc_id=#{oidc_id}"
|
||||
|
|
@ -187,6 +196,9 @@ defmodule MvWeb.LinkOidcAccountLive do
|
|||
defp link_oidc_account(socket, user, oidc_user_info) do
|
||||
oidc_id = Map.get(oidc_user_info, "sub") || Map.get(oidc_user_info, "id")
|
||||
|
||||
# Use SystemActor for authorization (user just verified password but is not yet logged in)
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
# Update the user with the OIDC ID
|
||||
case user.id
|
||||
|> reload_user!()
|
||||
|
|
@ -194,7 +206,7 @@ defmodule MvWeb.LinkOidcAccountLive do
|
|||
oidc_id: oidc_id,
|
||||
oidc_user_info: oidc_user_info
|
||||
})
|
||||
|> Ash.update() do
|
||||
|> Ash.update(actor: system_actor) do
|
||||
{:ok, updated_user} ->
|
||||
# After successful linking, redirect to OIDC login
|
||||
# Since the user now has an oidc_id, the next OIDC login will succeed
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue