Skip to content

Commit 01a0ee2

Browse files
committed
Fixed whitelisted emails.
1 parent ff61ef0 commit 01a0ee2

3 files changed

Lines changed: 56 additions & 8 deletions

File tree

src/api/middlewares/FirebaseAuth.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import {
77
import { firebaseAdmin } from "../../firebase";
88
import { getManager } from "typeorm";
99
import { UserModel } from "../../models/UserModel";
10-
import { isAllowedLoginEmail } from "../../utils/allowlistedEmail";
10+
import {
11+
buildForbiddenEmailMessage,
12+
isAllowedLoginEmail,
13+
} from "../../utils/allowlistedEmail";
1114

1215
export const FirebaseCurrentUserChecker = async (
1316
action: Action,
@@ -27,9 +30,7 @@ export const FirebaseCurrentUserChecker = async (
2730
const userId = decodedToken.uid;
2831
const email = decodedToken.email;
2932
if (!isAllowedLoginEmail(email)) {
30-
throw new ForbiddenError(
31-
"Only Cornell email addresses or allowlisted emails are allowed",
32-
);
33+
throw new ForbiddenError(buildForbiddenEmailMessage(email));
3334
}
3435
// Fetch and return the user from the database
3536
const user = await getManager().findOne(UserModel, {
@@ -40,6 +41,9 @@ export const FirebaseCurrentUserChecker = async (
4041
}
4142
return user;
4243
} catch (error) {
44+
if (error instanceof ForbiddenError || error instanceof NotFoundError) {
45+
throw error;
46+
}
4347
throw new UnauthorizedError("Invalid or expired authorization token");
4448
}
4549
};

src/app.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ import resellConnection from './utils/DB';
2626
import { ReportService } from './services/ReportService';
2727
import { reportToString } from './utils/Requests';
2828
import { startTransactionConfirmationCron } from './cron/transactionCron';
29-
import { isAllowedLoginEmail } from './utils/allowlistedEmail';
29+
import {
30+
buildForbiddenEmailMessage,
31+
isAllowedLoginEmail,
32+
} from './utils/allowlistedEmail';
3033

3134
// Setup dependency injection containers
3235
routingUseContainer(Container);
@@ -62,9 +65,7 @@ async function main() {
6265
action.request.email = email;
6366
action.request.firebaseUid = userId;
6467
if (!isAllowedLoginEmail(email)) {
65-
throw new ForbiddenError(
66-
"Only Cornell email addresses or allowlisted emails are allowed",
67-
);
68+
throw new ForbiddenError(buildForbiddenEmailMessage(email));
6869
}
6970
// Find or create user in your database using Firebase UID
7071
const manager = getManager();

src/utils/allowlistedEmail.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,46 @@ export function isAllowedLoginEmail(
3434
}
3535
return whitelist.has(e);
3636
}
37+
38+
function isProdEnv(): boolean {
39+
return process.env.IS_PROD?.toLowerCase() === "true";
40+
}
41+
42+
/**
43+
* Human-readable token email for logs / dev error text (never throws).
44+
*/
45+
export function normalizedTokenEmailForDebug(
46+
email: string | undefined,
47+
): string {
48+
if (!email || !email.trim()) {
49+
return "(no email claim on ID token)";
50+
}
51+
return normalizeEmail(email);
52+
}
53+
54+
/**
55+
* 403 message for disallowed emails. In non-prod, includes normalized token
56+
* email and parsed EMAIL_WHITELIST for debugging. Prod stays generic.
57+
* Always logs a line to stderr when called.
58+
*/
59+
export function buildForbiddenEmailMessage(email: string | undefined): string {
60+
const base =
61+
"Only Cornell email addresses or whitelisted emails are allowed.";
62+
const normalizedFromToken = normalizedTokenEmailForDebug(email);
63+
const whitelistEntries = Array.from(getEmailWhitelist()).sort();
64+
const listText =
65+
whitelistEntries.length > 0
66+
? whitelistEntries.join(", ")
67+
: "(EMAIL_WHITELIST is empty)";
68+
69+
console.warn("[email-auth] rejected", {
70+
normalizedFromToken,
71+
whitelistEntryCount: whitelistEntries.length,
72+
whitelistEntries: isProdEnv() ? "[redacted in prod logs]" : whitelistEntries,
73+
});
74+
75+
if (isProdEnv()) {
76+
return base;
77+
}
78+
return `${base} Token email (normalized): "${normalizedFromToken}". Whitelist: ${listText}.`;
79+
}

0 commit comments

Comments
 (0)