Skip to content

Commit 70fb321

Browse files
authored
fix(runtime): propagate organizationName and organizationSlug from JWT metadata (#2580)
* fix(runtime): propagate organizationName and organizationSlug from JWT metadata The runtime withBindings() was not extracting organizationId, organizationName, and organizationSlug from the JWT metadata when tokenOrContext was an object. This caused MCPs to receive null for these fields even though the Mesh proxy correctly included them in the JWT. Also enriches the context-factory Mesh JWT flow to include org name/slug from metadata before falling back to a DB query. Made-with: Cursor * fix(runtime): bump version to 1.2.11 for npm publish Includes the fix for organizationName/organizationSlug propagation from JWT metadata in withBindings(). Made-with: Cursor
1 parent 9348fba commit 70fb321

4 files changed

Lines changed: 44 additions & 7 deletions

File tree

apps/mesh/src/api/routes/proxy.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,16 @@ async function createMCPProxyDoNotUseDirectly(
128128
if (ctx.organization && connection.organization_id !== ctx.organization.id) {
129129
throw new Error("Connection does not belong to the active organization");
130130
}
131-
ctx.organization ??= { id: connection.organization_id };
131+
if (!ctx.organization) {
132+
const org = await ctx.db
133+
.selectFrom("organization")
134+
.select(["id", "slug", "name"])
135+
.where("id", "=", connection.organization_id)
136+
.executeTakeFirst();
137+
ctx.organization = org
138+
? { id: org.id, slug: org.slug, name: org.name }
139+
: { id: connection.organization_id };
140+
}
132141

133142
// Check connection status
134143
if (connection.status !== "active") {

apps/mesh/src/core/context-factory.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,29 @@ async function authenticateRequest(
545545
role = membership?.role;
546546
}
547547

548+
let organization: OrganizationContext | undefined;
549+
const metaOrgId = meshJwtPayload.metadata?.organizationId;
550+
if (metaOrgId) {
551+
const metaName = meshJwtPayload.metadata?.organizationName;
552+
const metaSlug = meshJwtPayload.metadata?.organizationSlug;
553+
if (metaName || metaSlug) {
554+
organization = { id: metaOrgId, name: metaName, slug: metaSlug };
555+
} else {
556+
const orgRow = await timings.measure(
557+
"auth_query_org_for_mesh_jwt",
558+
() =>
559+
db
560+
.selectFrom("organization")
561+
.select(["id", "slug", "name"])
562+
.where("id", "=", metaOrgId)
563+
.executeTakeFirst(),
564+
);
565+
organization = orgRow
566+
? { id: orgRow.id, slug: orgRow.slug, name: orgRow.name }
567+
: { id: metaOrgId };
568+
}
569+
}
570+
548571
return {
549572
user: {
550573
id: meshJwtPayload.sub,
@@ -553,11 +576,7 @@ async function authenticateRequest(
553576
},
554577
role,
555578
permissions: meshJwtPayload.permissions,
556-
organization: meshJwtPayload.metadata?.organizationId
557-
? {
558-
id: meshJwtPayload.metadata?.organizationId,
559-
}
560-
: undefined,
579+
organization,
561580
};
562581
}
563582
} catch {

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@decocms/runtime",
3-
"version": "1.2.10",
3+
"version": "1.2.11",
44
"type": "module",
55
"scripts": {
66
"check": "tsc --noEmit",

packages/runtime/src/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,21 @@ export const withBindings = <TEnv>({
220220
state?: Record<string, unknown>;
221221
meshUrl?: string;
222222
connectionId?: string;
223+
organizationId?: string;
224+
organizationName?: string;
225+
organizationSlug?: string;
223226
}) ?? {};
224227
const appName = decoded.appName as string | undefined;
225228
context.authorization ??= authorization;
226229
context.callerApp = appName;
227230
context.connectionId ??=
228231
(decoded.connectionId as string) ?? metadata.connectionId;
232+
context.organizationId ??=
233+
(decoded.organizationId as string) ?? metadata.organizationId;
234+
context.organizationName ??=
235+
(decoded.organizationName as string) ?? metadata.organizationName;
236+
context.organizationSlug ??=
237+
(decoded.organizationSlug as string) ?? metadata.organizationSlug;
229238
context.ensureAuthenticated = AUTHENTICATED(decoded.user ?? decoded.sub);
230239
} else {
231240
context = {

0 commit comments

Comments
 (0)