diff --git a/api/server/services/AuthService.js b/api/server/services/AuthService.js index 42198aa40..ae2e48b8d 100644 --- a/api/server/services/AuthService.js +++ b/api/server/services/AuthService.js @@ -3,12 +3,12 @@ const jwt = require('jsonwebtoken'); const { webcrypto } = require('node:crypto'); const { logger } = require('@librechat/data-schemas'); const { isEnabled, checkEmailConfig } = require('@librechat/api'); -const { SystemRoles, errorsToString } = require('librechat-data-provider'); +const { ErrorTypes, SystemRoles, errorsToString } = require('librechat-data-provider'); const { findUser, + findToken, createUser, updateUser, - findToken, countUsers, getUserById, findSession, @@ -181,6 +181,14 @@ const registerUser = async (user, additionalData = {}) => { let newUserId; try { + const appConfig = await getAppConfig(); + if (!isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains)) { + const errorMessage = + 'The email address provided cannot be used. Please use a different email address.'; + logger.error(`[registerUser] [Registration not allowed] [Email: ${user.email}]`); + return { status: 403, message: errorMessage }; + } + const existingUser = await findUser({ email }, 'email _id'); if (existingUser) { @@ -195,14 +203,6 @@ const registerUser = async (user, additionalData = {}) => { return { status: 200, message: genericVerificationMessage }; } - const appConfig = await getAppConfig({ role: user.role }); - if (!isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains)) { - const errorMessage = - 'The email address provided cannot be used. Please use a different email address.'; - logger.error(`[registerUser] [Registration not allowed] [Email: ${user.email}]`); - return { status: 403, message: errorMessage }; - } - //determine if this is the first registered user (not counting anonymous_user) const isFirstRegisteredUser = (await countUsers()) === 0; @@ -252,6 +252,13 @@ const registerUser = async (user, additionalData = {}) => { */ const requestPasswordReset = async (req) => { const { email } = req.body; + const appConfig = await getAppConfig(); + if (!isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains)) { + const error = new Error(ErrorTypes.AUTH_FAILED); + error.code = ErrorTypes.AUTH_FAILED; + error.message = 'Email domain not allowed'; + return error; + } const user = await findUser({ email }, 'email _id'); const emailEnabled = checkEmailConfig(); diff --git a/api/strategies/ldapStrategy.js b/api/strategies/ldapStrategy.js index 6f3adf694..2822bd8a2 100644 --- a/api/strategies/ldapStrategy.js +++ b/api/strategies/ldapStrategy.js @@ -122,17 +122,17 @@ const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => { ); } + const appConfig = await getAppConfig(); + if (!isEmailDomainAllowed(mail, appConfig?.registration?.allowedDomains)) { + logger.error( + `[LDAP Strategy] Authentication blocked - email domain not allowed [Email: ${mail}]`, + ); + return done(null, false, { message: 'Email domain not allowed' }); + } + if (!user) { const isFirstRegisteredUser = (await countUsers()) === 0; const role = isFirstRegisteredUser ? SystemRoles.ADMIN : SystemRoles.USER; - const appConfig = await getAppConfig({ role }); - - if (!isEmailDomainAllowed(mail, appConfig?.registration?.allowedDomains)) { - logger.error( - `[LDAP Strategy] Registration blocked - email domain not allowed [Email: ${mail}]`, - ); - return done(null, false, { message: 'Email domain not allowed for registration' }); - } user = { provider: 'ldap', diff --git a/api/strategies/openidStrategy.js b/api/strategies/openidStrategy.js index 6f35e2af8..011676eca 100644 --- a/api/strategies/openidStrategy.js +++ b/api/strategies/openidStrategy.js @@ -340,6 +340,19 @@ async function setupOpenId() { async (tokenset, done) => { try { const claims = tokenset.claims(); + const userinfo = { + ...claims, + ...(await getUserInfo(openidConfig, tokenset.access_token, claims.sub)), + }; + + const appConfig = await getAppConfig(); + if (!isEmailDomainAllowed(userinfo.email, appConfig?.registration?.allowedDomains)) { + logger.error( + `[OpenID Strategy] Authentication blocked - email domain not allowed [Email: ${userinfo.email}]`, + ); + return done(null, false, { message: 'Email domain not allowed' }); + } + const result = await findOpenIDUser({ openidId: claims.sub, email: claims.email, @@ -354,10 +367,7 @@ async function setupOpenId() { message: ErrorTypes.AUTH_FAILED, }); } - const userinfo = { - ...claims, - ...(await getUserInfo(openidConfig, tokenset.access_token, claims.sub)), - }; + const fullName = getFullName(userinfo); if (requiredRole) { @@ -399,15 +409,7 @@ async function setupOpenId() { ); } - const appConfig = await getAppConfig(); if (!user) { - if (!isEmailDomainAllowed(userinfo.email, appConfig?.registration?.allowedDomains)) { - logger.error( - `[OpenID Strategy] Registration blocked - email domain not allowed [Email: ${userinfo.email}]`, - ); - return done(null, false, { message: 'Email domain not allowed for registration' }); - } - user = { provider: 'openid', openidId: userinfo.sub, diff --git a/api/strategies/samlStrategy.js b/api/strategies/samlStrategy.js index ffc61ad19..a5f2e1d0b 100644 --- a/api/strategies/samlStrategy.js +++ b/api/strategies/samlStrategy.js @@ -193,16 +193,25 @@ async function setupSaml() { logger.info(`[samlStrategy] SAML authentication received for NameID: ${profile.nameID}`); logger.debug('[samlStrategy] SAML profile:', profile); + const userEmail = getEmail(profile) || ''; + const appConfig = await getAppConfig(); + + if (!isEmailDomainAllowed(userEmail, appConfig?.registration?.allowedDomains)) { + logger.error( + `[SAML Strategy] Authentication blocked - email domain not allowed [Email: ${userEmail}]`, + ); + return done(null, false, { message: 'Email domain not allowed' }); + } + let user = await findUser({ samlId: profile.nameID }); logger.info( `[samlStrategy] User ${user ? 'found' : 'not found'} with SAML ID: ${profile.nameID}`, ); if (!user) { - const email = getEmail(profile) || ''; - user = await findUser({ email }); + user = await findUser({ email: userEmail }); logger.info( - `[samlStrategy] User ${user ? 'found' : 'not found'} with email: ${profile.email}`, + `[samlStrategy] User ${user ? 'found' : 'not found'} with email: ${userEmail}`, ); } @@ -221,16 +230,7 @@ async function setupSaml() { getUserName(profile) || getGivenName(profile) || getEmail(profile), ); - const appConfig = await getAppConfig(); if (!user) { - const userEmail = getEmail(profile) || ''; - if (!isEmailDomainAllowed(userEmail, appConfig?.registration?.allowedDomains)) { - logger.error( - `[SAML Strategy] Registration blocked - email domain not allowed [Email: ${userEmail}]`, - ); - return done(null, false, { message: 'Email domain not allowed for registration' }); - } - user = { provider: 'saml', samlId: profile.nameID, diff --git a/api/strategies/socialLogin.js b/api/strategies/socialLogin.js index 902c9e873..5f7fab01c 100644 --- a/api/strategies/socialLogin.js +++ b/api/strategies/socialLogin.js @@ -15,19 +15,19 @@ const socialLogin = }); const appConfig = await getAppConfig(); - const existingUser = await findUser({ email: email.trim() }); - const ALLOW_SOCIAL_REGISTRATION = isEnabled(process.env.ALLOW_SOCIAL_REGISTRATION); - if (!existingUser && !isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains)) { + if (!isEmailDomainAllowed(email, appConfig?.registration?.allowedDomains)) { logger.error( - `[${provider}Login] Registration blocked - email domain not allowed [Email: ${email}]`, + `[${provider}Login] Authentication blocked - email domain not allowed [Email: ${email}]`, ); const error = new Error(ErrorTypes.AUTH_FAILED); error.code = ErrorTypes.AUTH_FAILED; - error.message = 'Email domain not allowed for registration'; + error.message = 'Email domain not allowed'; return cb(error); } + const existingUser = await findUser({ email: email.trim() }); + if (existingUser?.provider === provider) { await handleExistingUser(existingUser, avatarUrl, appConfig); return cb(null, existingUser); @@ -41,20 +41,29 @@ const socialLogin = return cb(error); } - if (ALLOW_SOCIAL_REGISTRATION) { - const newUser = await createSocialUser({ - email, - avatarUrl, - provider, - providerKey: `${provider}Id`, - providerId: id, - username, - name, - emailVerified, - appConfig, - }); - return cb(null, newUser); + const ALLOW_SOCIAL_REGISTRATION = isEnabled(process.env.ALLOW_SOCIAL_REGISTRATION); + if (!ALLOW_SOCIAL_REGISTRATION) { + logger.error( + `[${provider}Login] Registration blocked - social registration is disabled [Email: ${email}]`, + ); + const error = new Error(ErrorTypes.AUTH_FAILED); + error.code = ErrorTypes.AUTH_FAILED; + error.message = 'Social registration is disabled'; + return cb(error); } + + const newUser = await createSocialUser({ + email, + avatarUrl, + provider, + providerKey: `${provider}Id`, + providerId: id, + username, + name, + emailVerified, + appConfig, + }); + return cb(null, newUser); } catch (err) { logger.error(`[${provider}Login]`, err); return cb(err);