From 608ed4ce198062df9e7c6490bca200c0bc0dc3ae Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Thu, 2 Jul 2026 21:07:09 +0000 Subject: [PATCH] Auth: refresh JWT on verify so permission changes take effect without re-login Co-Authored-By: Claude Sonnet 4.6 --- src/routes/auth.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/routes/auth.js b/src/routes/auth.js index 991442a..f8bff25 100644 --- a/src/routes/auth.js +++ b/src/routes/auth.js @@ -186,6 +186,38 @@ export async function authRoutes(app) { ? allCaps.filter(c => c.startsWith(`${appSlug}:`)).map(c => c.slice(appSlug.length + 1)) : allCaps + // Refresh the JWT cookie with current DB state so downstream app backends + // (which read caps from the JWT) see the updated permissions immediately — + // without requiring the user to log out and back in. + const { rows: apps } = user.is_admin + ? await pool.query( + `SELECT slug FROM apps WHERE active = true` + ) + : await pool.query( + `SELECT DISTINCT a.slug FROM apps a + WHERE a.active = true + AND ( + EXISTS (SELECT 1 FROM user_app_perms p WHERE p.user_id = $1 AND p.app_id = a.id) + OR EXISTS ( + SELECT 1 FROM user_roles ur + JOIN role_app_perms rap ON rap.role_id = ur.role_id + WHERE ur.user_id = $1 AND rap.app_id = a.id + ) + )`, + [user.id] + ) + + const freshToken = await signToken({ + sub: user.email, + name: user.name, + user_id: user.id, + is_admin: user.is_admin, + offsite_allowed: user.offsite_allowed, + apps: apps.map(a => a.slug), + caps: allCaps, + }) + reply.setCookie('hnf_session', freshToken, cookieOpts(request)) + return { user_id: user.id, email: user.email,