Skip to content

Commit ff61ef0

Browse files
committed
Implemented secret email whitelist for Appstore testing.
1 parent 6654b87 commit ff61ef0

4 files changed

Lines changed: 48 additions & 6 deletions

File tree

.env_template

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ PORT=
99
IMAGE_UPLOAD_URL=
1010
UPLOAD_BUCKET_NAME=
1111
UPLOAD_SIZE_LIMIT=
12+
# Comma-separated full email addresses allowed in addition to @cornell.edu (case-insensitive)
13+
EMAIL_WHITELIST=

src/api/middlewares/FirebaseAuth.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { firebaseAdmin } from "../../firebase";
88
import { getManager } from "typeorm";
99
import { UserModel } from "../../models/UserModel";
10+
import { isAllowedLoginEmail } from "../../utils/allowlistedEmail";
1011

1112
export const FirebaseCurrentUserChecker = async (
1213
action: Action,
@@ -25,9 +26,10 @@ export const FirebaseCurrentUserChecker = async (
2526
const decodedToken = await firebaseAdmin.auth().verifyIdToken(token);
2627
const userId = decodedToken.uid;
2728
const email = decodedToken.email;
28-
// Enforce Cornell email domain restriction
29-
if (email && !email.endsWith("@cornell.edu")) {
30-
throw new ForbiddenError("Only Cornell email addresses are allowed");
29+
if (!isAllowedLoginEmail(email)) {
30+
throw new ForbiddenError(
31+
"Only Cornell email addresses or allowlisted emails are allowed",
32+
);
3133
}
3234
// Fetch and return the user from the database
3335
const user = await getManager().findOne(UserModel, {

src/app.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ 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';
2930

3031
// Setup dependency injection containers
3132
routingUseContainer(Container);
@@ -56,13 +57,14 @@ async function main() {
5657
try {
5758
// Verify the token using Firebase Admin SDK
5859
const decodedToken = await admin.auth().verifyIdToken(token);
59-
// Check if the email is a Cornell email
6060
const email = decodedToken.email;
6161
const userId = decodedToken.uid;
6262
action.request.email = email;
6363
action.request.firebaseUid = userId;
64-
if (!email || !email.endsWith("@cornell.edu")) {
65-
throw new ForbiddenError("Only Cornell email addresses are allowed");
64+
if (!isAllowedLoginEmail(email)) {
65+
throw new ForbiddenError(
66+
"Only Cornell email addresses or allowlisted emails are allowed",
67+
);
6668
}
6769
// Find or create user in your database using Firebase UID
6870
const manager = getManager();

src/utils/allowlistedEmail.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const CORNELL_SUFFIX = "@cornell.edu";
2+
3+
function normalizeEmail(email: string): string {
4+
return email.trim().toLowerCase();
5+
}
6+
7+
/** Full addresses from EMAIL_WHITELIST (comma-separated), lowercased. */
8+
export function getEmailWhitelist(): Set<string> {
9+
const raw = process.env.EMAIL_WHITELIST ?? "";
10+
const set = new Set<string>();
11+
for (const part of raw.split(",")) {
12+
const normalized = normalizeEmail(part);
13+
if (normalized.length > 0) {
14+
set.add(normalized);
15+
}
16+
}
17+
return set;
18+
}
19+
20+
/**
21+
* True if the Firebase user email may use the API: @cornell.edu or listed in EMAIL_WHITELIST.
22+
* When true, `email` is a non-empty string.
23+
*/
24+
export function isAllowedLoginEmail(
25+
email: string | undefined,
26+
whitelist: Set<string> = getEmailWhitelist(),
27+
): email is string {
28+
if (!email) {
29+
return false;
30+
}
31+
const e = normalizeEmail(email);
32+
if (e.endsWith(CORNELL_SUFFIX)) {
33+
return true;
34+
}
35+
return whitelist.has(e);
36+
}

0 commit comments

Comments
 (0)