Skip to content

Commit 10e935b

Browse files
authored
fix(TRI-1444): Allow only logins from WHITELISTED_EMAILS regex (fixes triggerdotdev#685) (triggerdotdev#721)
1 parent 02e453c commit 10e935b

File tree

5 files changed

+18
-1
lines changed

5 files changed

+18
-1
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ APP_ORIGIN=http://localhost:3030
1313
NODE_ENV=development
1414

1515
# OPTIONAL VARIABLES
16+
# This is used for validating emails that are allowed to log in. Every email that do not match this regex will be rejected.
17+
# WHITELISTED_EMAILS="authorized@yahoo\.com|authorized@gmail\.com"
1618
# This is used for logging in via GitHub. You can leave these commented out if you don't want to use GitHub for authentication.
1719
# AUTH_GITHUB_CLIENT_ID=
1820
# AUTH_GITHUB_CLIENT_SECRET=

apps/webapp/app/env.server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { z } from "zod";
22
import { SecretStoreOptionsSchema } from "./services/secrets/secretStore.server";
3+
import { isValidRegex } from "./utils/regex";
34

45
const EnvironmentSchema = z.object({
56
NODE_ENV: z.union([z.literal("development"), z.literal("production"), z.literal("test")]),
@@ -10,6 +11,7 @@ const EnvironmentSchema = z.object({
1011
SESSION_SECRET: z.string(),
1112
MAGIC_LINK_SECRET: z.string(),
1213
ENCRYPTION_KEY: z.string(),
14+
WHITELISTED_EMAILS: z.string().refine(isValidRegex, "WHITELISTED_EMAILS must be a valid regex.").optional(),
1315
REMIX_APP_PORT: z.string().optional(),
1416
LOGIN_ORIGIN: z.string().default("http://localhost:3030"),
1517
APP_ORIGIN: z.string().default("http://localhost:3030"),

apps/webapp/app/models/user.server.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Prisma, User } from "@trigger.dev/database";
22
import type { GitHubProfile } from "remix-auth-github";
33
import { prisma } from "~/db.server";
4+
import { env } from "~/env.server";
45
export type { User } from "@trigger.dev/database";
56

67
type FindOrCreateMagicLink = {
@@ -36,6 +37,10 @@ export async function findOrCreateUser(input: FindOrCreateUser): Promise<LoggedI
3637
export async function findOrCreateMagicLinkUser(
3738
input: FindOrCreateMagicLink
3839
): Promise<LoggedInUser> {
40+
if (env.WHITELISTED_EMAILS && !new RegExp(env.WHITELISTED_EMAILS).test(input.email)) {
41+
throw new Error("This email is unauthorized");
42+
}
43+
3944
const existingUser = await prisma.user.findFirst({
4045
where: {
4146
email: input.email,

apps/webapp/app/routes/magic.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
77

88
await authenticator.authenticate("email-link", request, {
99
successRedirect: redirectTo ?? "/",
10-
failureRedirect: "/login",
10+
failureRedirect: "/login/magic",
1111
});
1212
}

apps/webapp/app/utils/regex.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function isValidRegex(regex: string) {
2+
try {
3+
new RegExp(regex);
4+
return true;
5+
} catch (err) {
6+
return false;
7+
}
8+
}

0 commit comments

Comments
 (0)