From 94ee00b0ff270a854e8efd3d02acc15be5200c44 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 10 Jun 2026 08:38:00 +0000 Subject: [PATCH] debug: gated auth diagnostics (AUTH_DEBUG) logging jwt claims on 401 --- server/middleware/1.auth.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/server/middleware/1.auth.ts b/server/middleware/1.auth.ts index 38e12d6..c4bca75 100644 --- a/server/middleware/1.auth.ts +++ b/server/middleware/1.auth.ts @@ -1,3 +1,5 @@ +import { decodeJwt } from "jose"; + // Gates every /api/** route. Static SPA assets stay public. export default defineEventHandler(async (event) => { const path = getRequestURL(event).pathname; @@ -14,12 +16,28 @@ export default defineEventHandler(async (event) => { const header = getHeader(event, "authorization") || ""; const token = header.startsWith("Bearer ") ? header.slice(7).trim() : ""; if (!token) { + if (process.env.AUTH_DEBUG === "1") console.error("[auth] no bearer token on", path); throw createError({ statusCode: 401, statusMessage: "Unauthorized" }); } try { event.context.user = await getVerifier()(token); - } catch { + } catch (e) { + if (process.env.AUTH_DEBUG === "1") { + let claims: Record = {}; + try { + const c = decodeJwt(token); + claims = { iss: c.iss, sub: c.sub, aud: c.aud, azp: c.azp, exp: c.exp, alg_present: true }; + } catch (de) { + claims = { not_a_jwt: String(de).slice(0, 80) }; + } + console.error( + "[auth] verify failed:", (e as Error).message, + "| claims:", JSON.stringify(claims), + "| ALLOWED_USER_IDS:", process.env.ALLOWED_USER_IDS, + "| ZITADEL_AUDIENCE:", process.env.ZITADEL_AUDIENCE, + ); + } throw createError({ statusCode: 401, statusMessage: "Unauthorized" }); } });