▚▚ fix(organization): refresh session cookie cache after accepting an invitation - #11281
▚▚ fix(organization): refresh session cookie cache after accepting an invitation#11281breken-ai wants to merge 1 commit into
Conversation
…vitation `acceptInvitation` writes the accepted organization to the session row via `adapter.setActiveOrganization` but never re-signs the session cookie from that result. With `session.cookieCache.enabled`, every cached read (`GET /get-session` without `disableCookieCache`) keeps returning the pre-accept `activeOrganizationId` until the cache TTL expires, even though the database is already updated. The single-team branch did sign the cookie, but before the organization write, so it too carried the stale value. Sign the cookie once, after the last active-pointer write, from the session returned by `setActiveOrganization`, so both `activeTeamId` and `activeOrganizationId` reach the cookie cache immediately. Closes better-auth#11275 Claude-Session: https://claude.ai/code/session_0134ujLF81GyXsCByibLcYsz
|
Someone is attempting to deploy a commit to the better-auth Team on Vercel. A member of the Team first needs to authorize it. |
|
Thanks for your contribution! PR titles need to follow Conventional Commits format. It looks like your title needs a small adjustment. Hint: |
|
| }, | ||
| plugins: [organization()], | ||
| }, | ||
| { clientOptions: { plugins: [organizationClient()] } }, |
There was a problem hiding this comment.
This regression test configures organization() without team support and creates the invitation without a teamId, so it never runs the changed single-team branch where the early cookie write was removed. It also checks only activeOrganizationId. As a result, a future regression that drops activeTeamId from the final cached session would not be caught. Please enable teams, accept an invitation for one team, and assert both cached active pointers.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
1 issue found across 3 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/better-auth/src/plugins/organization/routes/crud-invites.test.ts">
<violation number="1" location="packages/better-auth/src/plugins/organization/routes/crud-invites.test.ts:923">
P2: Enable teams and accept a team invitation in this regression test, then assert both `activeOrganizationId` and `activeTeamId`. With team support disabled here, the test never exercises the changed team path or verifies that the final cached session preserves both active pointers.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| maxAge: 300, | ||
| }, | ||
| }, | ||
| plugins: [organization()], |
There was a problem hiding this comment.
P2: Enable teams and accept a team invitation in this regression test, then assert both activeOrganizationId and activeTeamId. With team support disabled here, the test never exercises the changed team path or verifies that the final cached session preserves both active pointers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/better-auth/src/plugins/organization/routes/crud-invites.test.ts, line 923:
<comment>Enable teams and accept a team invitation in this regression test, then assert both `activeOrganizationId` and `activeTeamId`. With team support disabled here, the test never exercises the changed team path or verifies that the final cached session preserves both active pointers.</comment>
<file context>
@@ -906,3 +906,79 @@ describe("invitation teamId must belong to the invitation's organization", async
+ maxAge: 300,
+ },
+ },
+ plugins: [organization()],
+ },
+ { clientOptions: { plugins: [organizationClient()] } },
</file context>
Closes #11275.
With
session.cookieCache.enabled: true,POST /organization/accept-invitationupdates the session row in the database but never re-signs the session cookie from that write. Thesession_datacookie keeps the pre-accept snapshot, soGET /get-session(withoutdisableCookieCache) returns the oldactiveOrganizationId— usuallynull— until the cache TTL expires, even though the row already holds the accepted organization.Root cause
In
acceptInvitation,adapter.setActiveOrganization(...)was called bare and its returned session discarded, sosetSessionCookienever ran for the organization write. The single-team branch did callsetSessionCookie, but fromsetActiveTeam's result and before the organization write, so that cookie also carried the staleactiveOrganizationId. The/organization/set-activeendpoint already re-signs the cookie from thesetActiveOrganizationresult; this endpoint did not.Fix
packages/better-auth/src/plugins/organization/routes/crud-invites.ts: sign the session cookie once, after the last active-pointer write, from the session returned bysetActiveOrganization. The team branch keeps itssetActiveTeamcall but drops its early cookie write, so a singleSet-Cookiecarries bothactiveTeamIdandactiveOrganizationId..changeset/accept-invitation-cookie-cache.md:better-authpatch.Tests
crud-invites.test.ts: new regression (@seeorganization.acceptInvitation never refreshes the session cookie after the active-organization write, leaving the cookie cache stale #11275) enables the cookie cache, signs in the invitee capturing the full cookie set, accepts the invitation while applying the response cookies, then asserts the live session (disableCookieCache: true) and the cached session both report the accepted organization. Without the fix the cached read returnsnull.pnpm typecheckclean.Not changed
/organization/createalso callssetActiveOrganization/setActiveTeamwithout re-signing the cookie (crud-org.ts:274, 286). Same class of gap, but outside this issue; left for a separate change.▚▚ Shipped by breken — self-healing software. This one's on us. breken.ai
Summary by cubic
Fixes
acceptInvitationleaving the session cookie cache stale whensession.cookieCache.enabledis on. The endpoint wrote the accepted organization to the session row but never re-signed the session cookie, so cachedGET /get-sessionreads kept returning the oldactiveOrganizationIduntil the cache TTL expired. The cookie is now signed once after the final active-pointer write, so bothactiveTeamIdandactiveOrganizationIdare reflected immediately.Bug Fixes
setActiveTeamstill runs, but the session returned bysetActiveOrganizationproduces oneSet-Cookiewith both values.better-authpatch changeset./organization/createwith the same gap for a separate change.Closes #11275.
Written for commit 2044b5f. Summary will update on new commits.