diff --git a/server/routers/badger/verifySession.ts b/server/routers/badger/verifySession.ts index e24e64729..748164dc8 100644 --- a/server/routers/badger/verifySession.ts +++ b/server/routers/badger/verifySession.ts @@ -857,7 +857,10 @@ export async function verifyResourceSession( return allowed( res, - whitelistEmail ? { email: whitelistEmail } : undefined, + forwardedUserData( + resource, + whitelistEmail ? { email: whitelistEmail } : undefined + ), dontStripSession ); } @@ -899,7 +902,11 @@ export async function verifyResourceSession( parsedBody.data ); - return allowed(res, userData, dontStripSession); + return allowed( + res, + forwardedUserData(resource, userData), + dontStripSession + ); } logger.debug( @@ -951,7 +958,10 @@ export async function verifyResourceSession( return allowed( res, - { ...allowedUserData, dontStripSession }, + forwardedUserData(resource, { + ...allowedUserData, + dontStripSession + }), dontStripSession ); } @@ -1158,6 +1168,19 @@ async function notAllowed( return response(res, data); } +// Badger only sets the Remote-* identity headers for fields present in the +// response, so omitting the user data is enough to keep them off the upstream +// request. Some backends (e.g. embedded device web servers) reject requests +// carrying headers they don't recognize. Inference resources skip this since +// the AI gateway relies on those headers for attribution. +function forwardedUserData( + resource: Resource, + userData: T | undefined +): T | undefined { + // Treat a missing value (older hybrid payloads) as enabled + return resource.forwardIdentityHeaders === false ? undefined : userData; +} + function allowed( res: Response, userData?: BasicUserData | EmailOnlyUserData, @@ -1209,7 +1232,11 @@ async function allowAccessToken( if (!tokenItem.persistSession) { logAccessTokenAccessAudit(tokenItem, resource, userData, auditBody); - return allowed(res, userData, dontStripSession); + return allowed( + res, + forwardedUserData(resource, userData), + dontStripSession + ); } const resourceSessionToken = extractResourceSessionToken( @@ -1241,7 +1268,11 @@ async function allowAccessToken( logger.debug( "Resource allowed because existing access token session is valid" ); - return allowed(res, userData, dontStripSession); + return allowed( + res, + forwardedUserData(resource, userData), + dontStripSession + ); } } @@ -1274,7 +1305,7 @@ async function createAccessTokenSession( ); res.appendHeader("Set-Cookie", cookie); logger.debug("Access token is valid, creating new session"); - return allowed(res, userData); + return allowed(res, forwardedUserData(resource, userData)); } async function getAccessTokenUserData( diff --git a/src/app/[orgId]/settings/resources/public/[niceId]/http/page.tsx b/src/app/[orgId]/settings/resources/public/[niceId]/http/page.tsx index fcdd9b25a..0346a98f2 100644 --- a/src/app/[orgId]/settings/resources/public/[niceId]/http/page.tsx +++ b/src/app/[orgId]/settings/resources/public/[niceId]/http/page.tsx @@ -127,6 +127,7 @@ function ProxyResourceHttpForm({ message: t("proxyErrorInvalidHeader") } ), + forwardIdentityHeaders: z.boolean(), requestHeaders: z .array(z.object({ name: z.string(), value: z.string() })) .nullable(), @@ -143,6 +144,7 @@ function ProxyResourceHttpForm({ ssl: resource.ssl, tlsServerName: resource.tlsServerName || "", setHostHeader: resource.setHostHeader || "", + forwardIdentityHeaders: resource.forwardIdentityHeaders, requestHeaders: resource.requestHeaders, responseHeaders: resource.responseHeaders }, @@ -184,6 +186,7 @@ function ProxyResourceHttpForm({ ssl: data.ssl, tlsServerName: data.tlsServerName || null, setHostHeader: data.setHostHeader || null, + forwardIdentityHeaders: data.forwardIdentityHeaders, requestHeaders: data.requestHeaders || null, responseHeaders: data.responseHeaders || null } @@ -207,6 +210,7 @@ function ProxyResourceHttpForm({ ssl: data.ssl, tlsServerName: data.tlsServerName || null, setHostHeader: data.setHostHeader || null, + forwardIdentityHeaders: data.forwardIdentityHeaders, requestHeaders: data.requestHeaders || null, responseHeaders: data.responseHeaders || null }); @@ -380,6 +384,32 @@ function ProxyResourceHttpForm({ /> + + ( + + + + + + )} + /> + +