From 41ab24dc07e5a54a4690570d801b743440f584f0 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sun, 19 Apr 2026 21:24:03 +0000 Subject: [PATCH] feat(graphile): propagate jwt.claims.session_id to pgSettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pairs with constructive-io/constructive-db#908, which adds session_id to the RETURNS TABLE of authenticate() and authenticate_strict(). Now that req.token.session_id is populated by the auth middleware, surface it as "jwt.claims.session_id" on the request transaction so jwt_private.current_session_id() returns a real value. Without this, every session-scoped DB procedure (sign_out, revoke_session, extend_token_expires, verify_password, verify_totp, require_step_up, webauthn_*) silently matches zero rows — the MFA step-up window in particular never elevates because verify_password updates sessions.last_password_verified WHERE id = NULL. - types.ts: add session_id?: string to ConstructiveAPIToken - graphile.ts: set pgSettings['jwt.claims.session_id'] when present --- graphql/server/src/middleware/graphile.ts | 4 ++++ graphql/server/src/middleware/types.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/graphql/server/src/middleware/graphile.ts b/graphql/server/src/middleware/graphile.ts index e6ccb3cf7..e2affc290 100644 --- a/graphql/server/src/middleware/graphile.ts +++ b/graphql/server/src/middleware/graphile.ts @@ -239,6 +239,10 @@ const buildPreset = ( ...context, }; + if (req.token.session_id) { + pgSettings['jwt.claims.session_id'] = req.token.session_id; + } + // Propagate credential metadata as JWT claims so PG functions // can read them via current_setting('jwt.claims.access_level') etc. if (req.token.access_level) { diff --git a/graphql/server/src/middleware/types.ts b/graphql/server/src/middleware/types.ts index 0d22e982c..327f6d222 100644 --- a/graphql/server/src/middleware/types.ts +++ b/graphql/server/src/middleware/types.ts @@ -3,6 +3,7 @@ import type { ApiStructure } from '../types'; export type ConstructiveAPIToken = { id?: string; user_id?: string; + session_id?: string; access_level?: string; kind?: string; [key: string]: unknown;