Skip to content

fix(auth): keep userGuid on session after better-auth 1.6 upgrade + broken-session recovery#20

Merged
chriskehayias merged 2 commits into
mainfrom
fix/better-auth-1.6-userguid
Jul 9, 2026
Merged

fix(auth): keep userGuid on session after better-auth 1.6 upgrade + broken-session recovery#20
chriskehayias merged 2 commits into
mainfrom
fix/better-auth-1.6-userguid

Conversation

@chriskehayias

Copy link
Copy Markdown
Contributor

Problem

better-auth 1.6 changed how additional user fields are parsed from the OAuth
provider profile. A user additionalField declared with input: false no
longer flows through when a value is supplied — in 1.6.11 the parser
(parseAdditionalUserInput, formerly parseAdditionalUserInputFromProviderProfile)
throws "userGuid is not allowed to be set".

Our userGuid field (MP User_GUID / OAuth sub) is populated server-side
via mapProfileToUser, so input: false broke it: session.user.userGuid
became undefined, which breaks every MP profile lookup — blank header avatar,
dead (non-interactive) user menu, and no way to sign out.

This shipped via the routine bump of better-auth from 1.4.x → 1.6.x. CI (build +
lint + unit tests) does not exercise a real OAuth login, so it passed silently.

Changes

Fix (fix(auth) commit)

  • Flip userGuid to input: true; extract to an exported userAdditionalFields
    const so a test can assert against the real config. Safe here: the app uses
    genericOAuth only — no email/password signup or update-user endpoint, so the
    field is only ever set server-side from the verified OAuth profile.
  • Add a regression guard in src/auth.test.ts that runs the real better-auth
    parser (parseAdditionalUserInput from better-auth/db) against the real
    field config — fails if someone flips it back OR a future better-auth version
    changes provider-profile parsing again.
  • Correct auth reference docs (user-identity.md, sessions.md), add a Better
    Auth upgrade checklist, and elevate the in-memory DB-adapter warning.

Recovery (feat(auth) commit)

  • AuthWrapper: a session with no userGuid now redirects to /session-error
    instead of rendering a dead app with no sign-out.
  • New /session-error page: recovery screen with a handleSignOut form button,
    placed outside the (web) route group so it can't redirect-loop.
  • auth-wrapper.test.tsx covers all branches (no session → /signin,
    no/null userGuid/session-error, healthy → children).

Verification

  • npm run lint — clean
  • npm run test:run — 670/670 pass, incl. the new real-library guard
  • npm run build — succeeds; emits the /session-error route

⚠️ Manual OAuth smoke test still required — automated checks pass whether or
not userGuid actually reaches the session. After merge: sign out, log in
fresh, open /api/auth/get-session, confirm user.userGuid is present and the
avatar/menu render with a working sign-out.

🤖 Generated with Claude Code

chriskehayias and others added 2 commits July 9, 2026 11:36
….6 regression)

better-auth 1.6 changed how additional user fields are parsed from the OAuth
provider profile: a user additionalField declared with input:false no longer
flows through when a value is supplied (in 1.6.11 the parser throws
"userGuid is not allowed to be set"). Our userGuid field (MP User_GUID / OAuth
sub) is populated server-side via mapProfileToUser, so input:false silently
broke it: session.user.userGuid became undefined, breaking every MP profile
lookup - blank avatar, dead user menu.

- Flip userGuid to input:true; extract to exported userAdditionalFields const.
- Add a regression guard test running the real better-auth parse function
  (parseAdditionalUserInput from better-auth/db) against the real field config.
- Correct auth reference docs (user-identity.md, sessions.md), add a Better
  Auth upgrade checklist and elevate the in-memory DB-adapter warning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…g the user

A session without a userGuid rendered a dead header - no avatar/menu, no
sign-out control, user stuck. Add a defensive guard so an unusable session
always has an exit, independent of root cause.

- AuthWrapper: session with no userGuid -> redirect to /session-error.
- New /session-error page: recovery screen with a handleSignOut form button,
  outside the (web) route group so it can't redirect-loop.
- auth-wrapper.test.tsx covers all guard branches (no session -> /signin,
  no userGuid -> /session-error, null userGuid -> /session-error, healthy).
- Document the recovery flow in route-protection.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chriskehayias
chriskehayias merged commit 6217f01 into main Jul 9, 2026
1 check passed
@chriskehayias
chriskehayias deleted the fix/better-auth-1.6-userguid branch July 9, 2026 15:41
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant