From 8dc6bcba224ac17fdc777b982c13c2dac3b61db5 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 4 Aug 2025 19:50:32 -0400 Subject: [PATCH] fix: Add option as to whether state cookie is considered for team context (#9831) * fix: Do not consider host in cookies state unless its a workspace subdomain * fix: Add option as to whether state cookie is considered in team context --- server/routes/api/documents/documents.ts | 8 ++++++-- server/routes/api/shares/shares.ts | 6 ++++-- server/routes/app.ts | 2 +- server/utils/passport.ts | 18 ++++++++++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/server/routes/api/documents/documents.ts b/server/routes/api/documents/documents.ts index 64e845ce1f..4318f57f5b 100644 --- a/server/routes/api/documents/documents.ts +++ b/server/routes/api/documents/documents.ts @@ -568,7 +568,9 @@ router.post( const { id, shareId } = ctx.input.body; const { user } = ctx.state.auth; const apiVersion = getAPIVersion(ctx); - const teamFromCtx = await getTeamFromContext(ctx); + const teamFromCtx = await getTeamFromContext(ctx, { + includeStateCookie: false, + }); const { document, share, collection } = await documentLoader({ id, shareId, @@ -1027,7 +1029,9 @@ router.post( let isPublic = false; if (shareId) { - const teamFromCtx = await getTeamFromContext(ctx); + const teamFromCtx = await getTeamFromContext(ctx, { + includeStateCookie: false, + }); const result = await loadPublicShare({ id: shareId, teamId: teamFromCtx?.id, diff --git a/server/routes/api/shares/shares.ts b/server/routes/api/shares/shares.ts index 7fccceabc1..1acb0fbbaa 100644 --- a/server/routes/api/shares/shares.ts +++ b/server/routes/api/shares/shares.ts @@ -36,7 +36,9 @@ router.post( async (ctx: APIContext) => { const { id, collectionId, documentId } = ctx.input.body; const { user } = ctx.state.auth; - const teamFromCtx = await getTeamFromContext(ctx); + const teamFromCtx = await getTeamFromContext(ctx, { + includeStateCookie: false, + }); // only public link loads will send "id". if (id) { @@ -371,7 +373,7 @@ router.get( validate(T.SharesSitemapSchema), async (ctx: APIContext) => { const { id } = ctx.input.query; - const team = await getTeamFromContext(ctx); + const team = await getTeamFromContext(ctx, { includeStateCookie: false }); const { share, sharedTree } = await loadPublicShare({ id, diff --git a/server/routes/app.ts b/server/routes/app.ts index d2a84038b8..ea2ea1472e 100644 --- a/server/routes/app.ts +++ b/server/routes/app.ts @@ -152,7 +152,7 @@ export const renderShare = async (ctx: Context, next: Next) => { let analytics: Integration[] = []; try { - team = await getTeamFromContext(ctx); + team = await getTeamFromContext(ctx, { includeStateCookie: false }); const result = await loadPublicShare({ id: shareId, collectionId: collectionSlug, diff --git a/server/utils/passport.ts b/server/utils/passport.ts index b549f73f58..97c14e2e00 100644 --- a/server/utils/passport.ts +++ b/server/utils/passport.ts @@ -131,10 +131,24 @@ export function getClientFromContext(ctx: Context): Client { return client === Client.Desktop ? Client.Desktop : Client.Web; } -export async function getTeamFromContext(ctx: Context) { +type TeamFromContextOptions = { + /** + * Whether to consider the state cookie in the context when determining the team. + * If true, the state cookie will be parsed to determine the host and infer the team + * this should only be used in the authentication process. + */ + includeStateCookie?: boolean; +}; + +export async function getTeamFromContext( + ctx: Context, + options: TeamFromContextOptions = { includeStateCookie: true } +) { // "domain" is the domain the user came from when attempting auth // we use it to infer the team they intend on signing into - const state = ctx.cookies.get("state"); + const state = options.includeStateCookie + ? ctx.cookies.get("state") + : undefined; const host = state ? parseState(state).host : ctx.hostname; const domain = parseDomain(host);