@@ -40,7 +40,7 @@ export class AuthCookieService {
4040 private poller : SessionCookiePoller | null = null ;
4141 private clientUat : ClientUatCookieHandler ;
4242 private sessionCookie : SessionCookieHandler ;
43- private activeOrgCookie : ReturnType < typeof createCookieHandler > ;
43+ private activeCookie : ReturnType < typeof createCookieHandler > ;
4444 private devBrowser : DevBrowser ;
4545
4646 public static async create (
@@ -73,7 +73,7 @@ export class AuthCookieService {
7373
7474 this . clientUat = createClientUatCookie ( cookieSuffix ) ;
7575 this . sessionCookie = createSessionCookie ( cookieSuffix ) ;
76- this . activeOrgCookie = createCookieHandler ( 'clerk_active_org ' ) ;
76+ this . activeCookie = createCookieHandler ( 'clerk_active_context ' ) ;
7777 this . devBrowser = createDevBrowser ( {
7878 frontendApi : clerk . frontendApi ,
7979 fapiClient,
@@ -82,6 +82,10 @@ export class AuthCookieService {
8282 }
8383
8484 public async setup ( ) {
85+ // Cleanup old cookie
86+ // TODO: This should be removed after 2025-08-01
87+ createCookieHandler ( 'clerk_active_org' ) . remove ( ) ;
88+
8589 if ( this . instanceType === 'production' ) {
8690 return this . setupProduction ( ) ;
8791 } else {
@@ -166,13 +170,12 @@ export class AuthCookieService {
166170 }
167171
168172 private updateSessionCookie ( token : string | null ) {
169- // only update session cookie from the active tab,
170- // or if the tab's selected organization matches the session's active organization
171- if ( ! document . hasFocus ( ) && ! this . isCurrentOrganizationActive ( ) ) {
173+ // Only allow background tabs to update if both session and organization match
174+ if ( ! document . hasFocus ( ) && ! this . isCurrentContextActive ( ) ) {
172175 return ;
173176 }
174177
175- this . setActiveOrganizationInStorage ( ) ;
178+ this . setActiveContextInStorage ( ) ;
176179
177180 return token ? this . sessionCookie . set ( token ) : this . sessionCookie . remove ( ) ;
178181 }
@@ -210,29 +213,35 @@ export class AuthCookieService {
210213 }
211214
212215 /**
213- * The below methods are used to determine whether or not an unfocused tab can be responsible
214- * for setting the session cookie. A session cookie should only be set by a tab who's selected
215- * organization matches the session's active organization. By storing the active organization
216- * ID in a cookie, we can check the value across tabs. If a tab's organization ID does not
217- * match the value in the active org cookie, it is not responsible for updating the session cookie.
216+ * The below methods handle active context tracking (session and organization) to ensure
217+ * only tabs with matching context can update the session cookie.
218+ * The format of the cookie value is "<session id>:<org id>" where either part can be empty.
218219 */
219220
220- public setActiveOrganizationInStorage ( ) {
221- if ( this . clerk . organization ?. id ) {
222- this . activeOrgCookie . set ( this . clerk . organization . id ) ;
221+ public setActiveContextInStorage ( ) {
222+ const sessionId = this . clerk . session ?. id || '' ;
223+ const orgId = this . clerk . organization ?. id || '' ;
224+ const contextValue = `${ sessionId } :${ orgId } ` ;
225+
226+ if ( contextValue !== ':' ) {
227+ this . activeCookie . set ( contextValue ) ;
223228 } else {
224- this . activeOrgCookie . remove ( ) ;
229+ this . activeCookie . remove ( ) ;
225230 }
226231 }
227232
228- private isCurrentOrganizationActive ( ) {
229- const activeOrganizationId = this . activeOrgCookie . get ( ) ;
230-
231- if ( ! activeOrganizationId && ! this . clerk . organization ?. id ) {
233+ private isCurrentContextActive ( ) {
234+ const activeContext = this . activeCookie . get ( ) ;
235+ if ( ! activeContext ) {
236+ // we should always have an active context, so return true if there isn't one and treat the current context as active
232237 return true ;
233238 }
234239
235- return this . clerk . organization ?. id === activeOrganizationId ;
240+ const [ activeSessionId , activeOrgId ] = activeContext . split ( ':' ) ;
241+ const currentSessionId = this . clerk . session ?. id || '' ;
242+ const currentOrgId = this . clerk . organization ?. id || '' ;
243+
244+ return activeSessionId === currentSessionId && activeOrgId === currentOrgId ;
236245 }
237246
238247 public getSessionCookie ( ) {
0 commit comments