From c5510768623a17e283cedadc8986fe5e726c643b Mon Sep 17 00:00:00 2001 From: waleedlatif1 Date: Thu, 7 Aug 2025 23:26:25 -0700 Subject: [PATCH] feat(whitelist): add email & domain-based whitelisting for signups --- apps/sim/lib/auth.ts | 33 +++++++++++++++++++++++++++++++++ apps/sim/lib/env.ts | 2 ++ 2 files changed, 35 insertions(+) diff --git a/apps/sim/lib/auth.ts b/apps/sim/lib/auth.ts index 4d1b0127e58..496abe3aa07 100644 --- a/apps/sim/lib/auth.ts +++ b/apps/sim/lib/auth.ts @@ -181,6 +181,39 @@ export const auth = betterAuth({ if (ctx.path.startsWith('/sign-up') && isTruthy(env.DISABLE_REGISTRATION)) throw new Error('Registration is disabled, please contact your admin.') + // Check email and domain whitelist for sign-in and sign-up + if ( + (ctx.path.startsWith('/sign-in') || ctx.path.startsWith('/sign-up')) && + (env.ALLOWED_LOGIN_EMAILS || env.ALLOWED_LOGIN_DOMAINS) + ) { + const requestEmail = ctx.body?.email?.toLowerCase() + + if (requestEmail) { + let isAllowed = false + + // Check specific email whitelist + if (env.ALLOWED_LOGIN_EMAILS) { + const allowedEmails = env.ALLOWED_LOGIN_EMAILS.split(',').map((email) => + email.trim().toLowerCase() + ) + isAllowed = allowedEmails.includes(requestEmail) + } + + // Check domain whitelist if not already allowed + if (!isAllowed && env.ALLOWED_LOGIN_DOMAINS) { + const allowedDomains = env.ALLOWED_LOGIN_DOMAINS.split(',').map((domain) => + domain.trim().toLowerCase() + ) + const emailDomain = requestEmail.split('@')[1] + isAllowed = emailDomain && allowedDomains.includes(emailDomain) + } + + if (!isAllowed) { + throw new Error('Access restricted. Please contact your administrator.') + } + } + } + return }), }, diff --git a/apps/sim/lib/env.ts b/apps/sim/lib/env.ts index 19c5581c0c2..223e7f2f0bb 100644 --- a/apps/sim/lib/env.ts +++ b/apps/sim/lib/env.ts @@ -20,6 +20,8 @@ export const env = createEnv({ BETTER_AUTH_URL: z.string().url(), // Base URL for Better Auth service BETTER_AUTH_SECRET: z.string().min(32), // Secret key for Better Auth JWT signing DISABLE_REGISTRATION: z.boolean().optional(), // Flag to disable new user registration + ALLOWED_LOGIN_EMAILS: z.string().optional(), // Comma-separated list of allowed email addresses for login + ALLOWED_LOGIN_DOMAINS: z.string().optional(), // Comma-separated list of allowed email domains for login ENCRYPTION_KEY: z.string().min(32), // Key for encrypting sensitive data INTERNAL_API_SECRET: z.string().min(32), // Secret for internal API authentication SIM_AGENT_API_KEY: z.string().min(1).optional(), // Secret for internal sim agent API authentication