Send email whitelist user downstream headers

Fix #1226
This commit is contained in:
Owen
2026-08-14 10:36:56 -04:00
parent 5d37f44241
commit 125091d719
2 changed files with 60 additions and 4 deletions
+33 -1
View File
@@ -33,7 +33,9 @@ import {
resourcePolicyPassword, resourcePolicyPassword,
ResourcePolicyPassword, ResourcePolicyPassword,
resourcePolicyHeaderAuth, resourcePolicyHeaderAuth,
ResourcePolicyHeaderAuth ResourcePolicyHeaderAuth,
resourceWhitelist,
resourcePolicyWhiteList
} from "@server/db"; } from "@server/db";
import { alias } from "@server/db"; import { alias } from "@server/db";
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm"; import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
@@ -448,6 +450,36 @@ export async function getResourceRules(
return [...directRules, ...offsetPolicyRules] as ResourceRule[]; return [...directRules, ...offsetPolicyRules] as ResourceRule[];
} }
/**
* Get the whitelisted email associated with a resource session's whitelist
* match (either a direct resource whitelist entry or a resource policy
* whitelist entry).
*/
export async function getWhitelistEmail(
whitelistId?: number | null,
policyWhitelistId?: number | null
): Promise<string | null> {
if (whitelistId) {
const [row] = await db
.select({ email: resourceWhitelist.email })
.from(resourceWhitelist)
.where(eq(resourceWhitelist.whitelistId, whitelistId))
.limit(1);
return row?.email ?? null;
}
if (policyWhitelistId) {
const [row] = await db
.select({ email: resourcePolicyWhiteList.email })
.from(resourcePolicyWhiteList)
.where(eq(resourcePolicyWhiteList.whitelistId, policyWhitelistId))
.limit(1);
return row?.email ?? null;
}
return null;
}
/** /**
* Get organization login page * Get organization login page
*/ */
+27 -3
View File
@@ -15,7 +15,8 @@ import {
getRoleResourceAccess, getRoleResourceAccess,
getUserResourceAccess, getUserResourceAccess,
getOrgLoginPage, getOrgLoginPage,
getUserSessionWithUser getUserSessionWithUser,
getWhitelistEmail
} from "@server/db/queries/verifySessionQueries"; } from "@server/db/queries/verifySessionQueries";
import { getUserOrgRoles } from "@server/lib/userOrgRoles"; import { getUserOrgRoles } from "@server/lib/userOrgRoles";
import { import {
@@ -94,6 +95,13 @@ type BasicUserData = {
role: string | null; role: string | null;
}; };
// Some auth methods (e.g. email whitelist) only know the remote email and
// have no associated user record to attach userId/username/name/role to.
type EmailOnlyUserData = {
dontStripSession?: boolean;
email: string;
};
export type { ClientErrorResponse }; export type { ClientErrorResponse };
export type VerifyUserResponse = { export type VerifyUserResponse = {
@@ -782,6 +790,18 @@ export async function verifyResourceSession(
"Resource allowed because whitelist session is valid" "Resource allowed because whitelist session is valid"
); );
const whitelistCacheKey = `whitelistEmail:${resourceSession.whitelistId}:${resourceSession.policyWhitelistId}`;
let whitelistEmail: string | null | undefined =
localCache.get(whitelistCacheKey);
if (whitelistEmail === undefined) {
whitelistEmail = await getWhitelistEmail(
resourceSession.whitelistId,
resourceSession.policyWhitelistId
);
localCache.set(whitelistCacheKey, whitelistEmail, 12);
}
logRequestAudit( logRequestAudit(
{ {
action: true, action: true,
@@ -793,7 +813,11 @@ export async function verifyResourceSession(
parsedBody.data parsedBody.data
); );
return allowed(res, undefined, dontStripSession); return allowed(
res,
whitelistEmail ? { email: whitelistEmail } : undefined,
dontStripSession
);
} }
if (resourceSession.accessTokenId) { if (resourceSession.accessTokenId) {
@@ -1022,7 +1046,7 @@ async function notAllowed(
function allowed( function allowed(
res: Response, res: Response,
userData?: BasicUserData, userData?: BasicUserData | EmailOnlyUserData,
dontStripSession?: boolean, dontStripSession?: boolean,
virtualApiKeyId?: string virtualApiKeyId?: string
) { ) {