fix(auth): resolve Discord display name in the server-side session load #23

Merged
yami merged 1 commit from dev into main 2026-08-11 13:29:59 -04:00
Owner

The nav rendered "Account" instead of the username for Discord accounts.

Auth/GetDiscordUserInfo returns Ok(responseString) where responseString is
already JSON, so ASP.NET sends it with a text/plain content type. apiGet
branches on content-type and therefore handed back the raw string, and
.username on a string is undefined — so the server produced a user with no
username and getDisplayName() fell through to its 'Account' default. id was
undefined for the same reason, which also poisoned the
${provider}:${id} cache key used by the saved-statics summaries.

The client had always handled this: it JSON.parses a string response and
prefers Discord's global_name over username for the display name. The
server-side loader reimplemented the call without either step.

Extracted that handling into normalizeDiscordUserInfo, exported from
auth.service and now used by both callers, so the two cannot drift again.
Malformed payloads fall through to a null user, which after the previous
commit means the client re-probes rather than being stranded.

Only the email/Identity branch was exercised when SSR was added — the local
verification stack had no Discord app — which is exactly why this shipped.
Verified the fix against the literal wire payload
({"id":...,"username":"handle","global_name":"Yami",...} as a text/plain
string): before, username resolved undefined and the nav showed "Account";
after, it resolves to "Yami". Email login re-verified end to end against the
local stack, including logged-out isolation.

The nav rendered "Account" instead of the username for Discord accounts. Auth/GetDiscordUserInfo returns `Ok(responseString)` where responseString is already JSON, so ASP.NET sends it with a text/plain content type. apiGet branches on content-type and therefore handed back the raw string, and `.username` on a string is undefined — so the server produced a user with no username and getDisplayName() fell through to its 'Account' default. `id` was undefined for the same reason, which also poisoned the `${provider}:${id}` cache key used by the saved-statics summaries. The client had always handled this: it JSON.parses a string response and prefers Discord's `global_name` over `username` for the display name. The server-side loader reimplemented the call without either step. Extracted that handling into normalizeDiscordUserInfo, exported from auth.service and now used by both callers, so the two cannot drift again. Malformed payloads fall through to a null user, which after the previous commit means the client re-probes rather than being stranded. Only the email/Identity branch was exercised when SSR was added — the local verification stack had no Discord app — which is exactly why this shipped. Verified the fix against the literal wire payload (`{"id":...,"username":"handle","global_name":"Yami",...}` as a text/plain string): before, username resolved undefined and the nav showed "Account"; after, it resolves to "Yami". Email login re-verified end to end against the local stack, including logged-out isolation.
fix(auth): resolve Discord display name in the server-side session load
All checks were successful
Docker Build & Push / build-and-push (push) Successful in 38s
8c645c2249
The nav rendered "Account" instead of the username for Discord accounts.

Auth/GetDiscordUserInfo returns `Ok(responseString)` where responseString is
already JSON, so ASP.NET sends it with a text/plain content type. apiGet
branches on content-type and therefore handed back the raw string, and
`.username` on a string is undefined — so the server produced a user with no
username and getDisplayName() fell through to its 'Account' default. `id` was
undefined for the same reason, which also poisoned the
`${provider}:${id}` cache key used by the saved-statics summaries.

The client had always handled this: it JSON.parses a string response and
prefers Discord's `global_name` over `username` for the display name. The
server-side loader reimplemented the call without either step.

Extracted that handling into normalizeDiscordUserInfo, exported from
auth.service and now used by both callers, so the two cannot drift again.
Malformed payloads fall through to a null user, which after the previous
commit means the client re-probes rather than being stranded.

Only the email/Identity branch was exercised when SSR was added — the local
verification stack had no Discord app — which is exactly why this shipped.
Verified the fix against the literal wire payload
(`{"id":...,"username":"handle","global_name":"Yami",...}` as a text/plain
string): before, username resolved undefined and the nav showed "Account";
after, it resolves to "Yami". Email login re-verified end to end against the
local stack, including logged-out isolation.
yami merged commit c1dde9fe22 into main 2026-08-11 13:29:59 -04:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
yami/xivloot-rewrite!23
No description provided.