fix(core): Fixed character re-auth issues

This commit is contained in:
Dmitry Popov
2026-03-26 01:10:57 +01:00
parent 9ab7fcc46e
commit d62ad709ab
3 changed files with 57 additions and 23 deletions
+32 -23
View File
@@ -897,33 +897,42 @@ defmodule WandererApp.Esi.ApiClient do
end
defp invalidate_character_tokens(character, character_id, expires_at, scopes) do
# Re-load from DB to avoid race with concurrent re-auth
case WandererApp.Api.Character.by_id(character_id) do
{:ok, current_character} ->
# Only invalidate if tokens haven't been refreshed since we started
if current_character.access_token == character.access_token do
attrs = %{access_token: nil, refresh_token: nil, expires_at: expires_at, scopes: scopes}
# Skip invalidation if the character was recently re-authorized via SSO.
# This protects fresh tokens from being wiped by transient invalid_grant
# errors that can occur shortly after re-auth.
if WandererApp.Cache.lookup!("character:#{character_id}:reauth_grace", false) do
Logger.info(
"[ApiClient] Skipping token invalidation for #{character_id} - within re-auth grace period"
)
else
# Re-load from DB to avoid race with concurrent re-auth
case WandererApp.Api.Character.by_id(character_id) do
{:ok, current_character} ->
# Only invalidate if tokens haven't been refreshed since we started
if current_character.access_token == character.access_token do
attrs = %{access_token: nil, refresh_token: nil, expires_at: expires_at, scopes: scopes}
with {:ok, _} <- WandererApp.Api.Character.update(current_character, attrs) do
WandererApp.Character.update_character(character_id, attrs)
with {:ok, _} <- WandererApp.Api.Character.update(current_character, attrs) do
WandererApp.Character.update_character(character_id, attrs)
else
error ->
Logger.error("Failed to clear tokens for #{character_id}: #{inspect(error)}")
end
Phoenix.PubSub.broadcast(
WandererApp.PubSub,
"character:#{character_id}",
:character_token_invalid
)
else
error ->
Logger.error("Failed to clear tokens for #{character_id}: #{inspect(error)}")
Logger.info(
"[ApiClient] Skipping token invalidation for #{character_id} - tokens were refreshed concurrently"
)
end
Phoenix.PubSub.broadcast(
WandererApp.PubSub,
"character:#{character_id}",
:character_token_invalid
)
else
Logger.info(
"[ApiClient] Skipping token invalidation for #{character_id} - tokens were refreshed concurrently"
)
end
{:error, _} ->
Logger.error("Failed to load character #{character_id} for token invalidation")
{:error, _} ->
Logger.error("Failed to load character #{character_id} for token invalidation")
end
end
:ok
@@ -46,6 +46,14 @@ defmodule WandererAppWeb.AuthController do
# premature token invalidation after a successful re-auth
WandererApp.Cache.delete("character:#{character.id}:invalid_grant_count")
# Set a grace period to protect fresh tokens from being wiped by
# in-flight or immediately-subsequent invalid_grant errors
WandererApp.Cache.put(
"character:#{character.id}:reauth_grace",
true,
ttl: :timer.minutes(5)
)
# Update corporation/alliance data from ESI to ensure access control is current
update_character_affiliation(character)
@@ -22,6 +22,11 @@ defmodule WandererAppWeb.CharactersLive do
"character:#{character_id}:corporation"
)
Phoenix.PubSub.subscribe(
WandererApp.PubSub,
"character:#{character_id}"
)
:ok = WandererApp.Character.TrackerManager.start_tracking(character_id)
end)
@@ -148,6 +153,18 @@ defmodule WandererAppWeb.CharactersLive do
{:noreply, socket |> assign(characters: characters |> Enum.map(&map_ui_character/1))}
end
@impl true
def handle_info(
event,
socket
)
when event in [:character_token_invalid, :token_updated] do
{:ok, characters} =
WandererApp.Api.Character.active_by_user(%{user_id: socket.assigns.user_id})
{:noreply, socket |> assign(characters: characters |> Enum.map(&map_ui_character/1))}
end
@impl true
def handle_info(
_event,