diff --git a/apps/sim/lib/auth.ts b/apps/sim/lib/auth.ts index 4d1b0127e5..496abe3aa0 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 19c5581c0c..223e7f2f0b 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