mirror of
https://github.com/fosrl/pangolin.git
synced 2026-10-26 05:29:05 +01:00
Optionally forward identity headers
This commit is contained in:
@@ -857,7 +857,10 @@ export async function verifyResourceSession(
|
|||||||
|
|
||||||
return allowed(
|
return allowed(
|
||||||
res,
|
res,
|
||||||
whitelistEmail ? { email: whitelistEmail } : undefined,
|
forwardedUserData(
|
||||||
|
resource,
|
||||||
|
whitelistEmail ? { email: whitelistEmail } : undefined
|
||||||
|
),
|
||||||
dontStripSession
|
dontStripSession
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -899,7 +902,11 @@ export async function verifyResourceSession(
|
|||||||
parsedBody.data
|
parsedBody.data
|
||||||
);
|
);
|
||||||
|
|
||||||
return allowed(res, userData, dontStripSession);
|
return allowed(
|
||||||
|
res,
|
||||||
|
forwardedUserData(resource, userData),
|
||||||
|
dontStripSession
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@@ -951,7 +958,10 @@ export async function verifyResourceSession(
|
|||||||
|
|
||||||
return allowed(
|
return allowed(
|
||||||
res,
|
res,
|
||||||
{ ...allowedUserData, dontStripSession },
|
forwardedUserData(resource, {
|
||||||
|
...allowedUserData,
|
||||||
|
dontStripSession
|
||||||
|
}),
|
||||||
dontStripSession
|
dontStripSession
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1158,6 +1168,19 @@ async function notAllowed(
|
|||||||
return response<VerifyUserResponse>(res, data);
|
return response<VerifyUserResponse>(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<T>(
|
||||||
|
resource: Resource,
|
||||||
|
userData: T | undefined
|
||||||
|
): T | undefined {
|
||||||
|
// Treat a missing value (older hybrid payloads) as enabled
|
||||||
|
return resource.forwardIdentityHeaders === false ? undefined : userData;
|
||||||
|
}
|
||||||
|
|
||||||
function allowed(
|
function allowed(
|
||||||
res: Response,
|
res: Response,
|
||||||
userData?: BasicUserData | EmailOnlyUserData,
|
userData?: BasicUserData | EmailOnlyUserData,
|
||||||
@@ -1209,7 +1232,11 @@ async function allowAccessToken(
|
|||||||
|
|
||||||
if (!tokenItem.persistSession) {
|
if (!tokenItem.persistSession) {
|
||||||
logAccessTokenAccessAudit(tokenItem, resource, userData, auditBody);
|
logAccessTokenAccessAudit(tokenItem, resource, userData, auditBody);
|
||||||
return allowed(res, userData, dontStripSession);
|
return allowed(
|
||||||
|
res,
|
||||||
|
forwardedUserData(resource, userData),
|
||||||
|
dontStripSession
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceSessionToken = extractResourceSessionToken(
|
const resourceSessionToken = extractResourceSessionToken(
|
||||||
@@ -1241,7 +1268,11 @@ async function allowAccessToken(
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
"Resource allowed because existing access token session is valid"
|
"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);
|
res.appendHeader("Set-Cookie", cookie);
|
||||||
logger.debug("Access token is valid, creating new session");
|
logger.debug("Access token is valid, creating new session");
|
||||||
return allowed(res, userData);
|
return allowed(res, forwardedUserData(resource, userData));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAccessTokenUserData(
|
async function getAccessTokenUserData(
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ function ProxyResourceHttpForm({
|
|||||||
message: t("proxyErrorInvalidHeader")
|
message: t("proxyErrorInvalidHeader")
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
forwardIdentityHeaders: z.boolean(),
|
||||||
requestHeaders: z
|
requestHeaders: z
|
||||||
.array(z.object({ name: z.string(), value: z.string() }))
|
.array(z.object({ name: z.string(), value: z.string() }))
|
||||||
.nullable(),
|
.nullable(),
|
||||||
@@ -143,6 +144,7 @@ function ProxyResourceHttpForm({
|
|||||||
ssl: resource.ssl,
|
ssl: resource.ssl,
|
||||||
tlsServerName: resource.tlsServerName || "",
|
tlsServerName: resource.tlsServerName || "",
|
||||||
setHostHeader: resource.setHostHeader || "",
|
setHostHeader: resource.setHostHeader || "",
|
||||||
|
forwardIdentityHeaders: resource.forwardIdentityHeaders,
|
||||||
requestHeaders: resource.requestHeaders,
|
requestHeaders: resource.requestHeaders,
|
||||||
responseHeaders: resource.responseHeaders
|
responseHeaders: resource.responseHeaders
|
||||||
},
|
},
|
||||||
@@ -184,6 +186,7 @@ function ProxyResourceHttpForm({
|
|||||||
ssl: data.ssl,
|
ssl: data.ssl,
|
||||||
tlsServerName: data.tlsServerName || null,
|
tlsServerName: data.tlsServerName || null,
|
||||||
setHostHeader: data.setHostHeader || null,
|
setHostHeader: data.setHostHeader || null,
|
||||||
|
forwardIdentityHeaders: data.forwardIdentityHeaders,
|
||||||
requestHeaders: data.requestHeaders || null,
|
requestHeaders: data.requestHeaders || null,
|
||||||
responseHeaders: data.responseHeaders || null
|
responseHeaders: data.responseHeaders || null
|
||||||
}
|
}
|
||||||
@@ -207,6 +210,7 @@ function ProxyResourceHttpForm({
|
|||||||
ssl: data.ssl,
|
ssl: data.ssl,
|
||||||
tlsServerName: data.tlsServerName || null,
|
tlsServerName: data.tlsServerName || null,
|
||||||
setHostHeader: data.setHostHeader || null,
|
setHostHeader: data.setHostHeader || null,
|
||||||
|
forwardIdentityHeaders: data.forwardIdentityHeaders,
|
||||||
requestHeaders: data.requestHeaders || null,
|
requestHeaders: data.requestHeaders || null,
|
||||||
responseHeaders: data.responseHeaders || null
|
responseHeaders: data.responseHeaders || null
|
||||||
});
|
});
|
||||||
@@ -380,6 +384,32 @@ function ProxyResourceHttpForm({
|
|||||||
/>
|
/>
|
||||||
</SettingsFormCell>
|
</SettingsFormCell>
|
||||||
|
|
||||||
|
<SettingsFormCell span="full">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="forwardIdentityHeaders"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<SwitchInput
|
||||||
|
id="forward-identity-headers-toggle"
|
||||||
|
label={t(
|
||||||
|
"proxyForwardIdentityHeaders"
|
||||||
|
)}
|
||||||
|
description={t(
|
||||||
|
"proxyForwardIdentityHeadersDescription"
|
||||||
|
)}
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={
|
||||||
|
field.onChange
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SettingsFormCell>
|
||||||
|
|
||||||
<SettingsFormCell span="full">
|
<SettingsFormCell span="full">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
|||||||
Reference in New Issue
Block a user