| |
| const express = require('express'); |
| const passport = require('passport'); |
| const { randomState } = require('openid-client'); |
| const { logger } = require('@librechat/data-schemas'); |
| const { ErrorTypes } = require('librechat-data-provider'); |
| const { isEnabled, createSetBalanceConfig } = require('@librechat/api'); |
| const { checkDomainAllowed, loginLimiter, logHeaders, checkBan } = require('~/server/middleware'); |
| const { syncUserEntraGroupMemberships } = require('~/server/services/PermissionService'); |
| const { setAuthTokens, setOpenIDAuthTokens } = require('~/server/services/AuthService'); |
| const { getAppConfig } = require('~/server/services/Config'); |
| const { Balance } = require('~/db/models'); |
|
|
| const setBalanceConfig = createSetBalanceConfig({ |
| getAppConfig, |
| Balance, |
| }); |
|
|
| const router = express.Router(); |
|
|
| const domains = { |
| client: process.env.DOMAIN_CLIENT, |
| server: process.env.DOMAIN_SERVER, |
| }; |
|
|
| router.use(logHeaders); |
| router.use(loginLimiter); |
|
|
| const oauthHandler = async (req, res, next) => { |
| try { |
| if (res.headersSent) { |
| return; |
| } |
|
|
| await checkBan(req, res); |
| if (req.banned) { |
| return; |
| } |
| if ( |
| req.user && |
| req.user.provider == 'openid' && |
| isEnabled(process.env.OPENID_REUSE_TOKENS) === true |
| ) { |
| await syncUserEntraGroupMemberships(req.user, req.user.tokenset.access_token); |
| setOpenIDAuthTokens(req.user.tokenset, res, req.user._id.toString()); |
| } else { |
| await setAuthTokens(req.user._id, res); |
| } |
| res.redirect(domains.client); |
| } catch (err) { |
| logger.error('Error in setting authentication tokens:', err); |
| next(err); |
| } |
| }; |
|
|
| router.get('/error', (req, res) => { |
| |
| const errorMessage = req.session?.messages?.pop() || 'Unknown error'; |
| logger.error('Error in OAuth authentication:', { |
| message: errorMessage, |
| }); |
|
|
| res.redirect(`${domains.client}/login?redirect=false&error=${ErrorTypes.AUTH_FAILED}`); |
| }); |
|
|
| |
| |
| |
| router.get( |
| '/google', |
| passport.authenticate('google', { |
| scope: ['openid', 'profile', 'email'], |
| session: false, |
| }), |
| ); |
|
|
| router.get( |
| '/google/callback', |
| passport.authenticate('google', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| scope: ['openid', 'profile', 'email'], |
| }), |
| setBalanceConfig, |
| checkDomainAllowed, |
| oauthHandler, |
| ); |
|
|
| |
| |
| |
| router.get( |
| '/facebook', |
| passport.authenticate('facebook', { |
| scope: ['public_profile'], |
| profileFields: ['id', 'email', 'name'], |
| session: false, |
| }), |
| ); |
|
|
| router.get( |
| '/facebook/callback', |
| passport.authenticate('facebook', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| scope: ['public_profile'], |
| profileFields: ['id', 'email', 'name'], |
| }), |
| setBalanceConfig, |
| checkDomainAllowed, |
| oauthHandler, |
| ); |
|
|
| |
| |
| |
| router.get('/openid', (req, res, next) => { |
| return passport.authenticate('openid', { |
| session: false, |
| state: randomState(), |
| })(req, res, next); |
| }); |
|
|
| router.get( |
| '/openid/callback', |
| passport.authenticate('openid', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| }), |
| setBalanceConfig, |
| checkDomainAllowed, |
| oauthHandler, |
| ); |
|
|
| |
| |
| |
| router.get( |
| '/github', |
| passport.authenticate('github', { |
| scope: ['user:email', 'read:user'], |
| session: false, |
| }), |
| ); |
|
|
| router.get( |
| '/github/callback', |
| passport.authenticate('github', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| scope: ['user:email', 'read:user'], |
| }), |
| setBalanceConfig, |
| checkDomainAllowed, |
| oauthHandler, |
| ); |
|
|
| |
| |
| |
| router.get( |
| '/discord', |
| passport.authenticate('discord', { |
| scope: ['identify', 'email'], |
| session: false, |
| }), |
| ); |
|
|
| router.get( |
| '/discord/callback', |
| passport.authenticate('discord', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| scope: ['identify', 'email'], |
| }), |
| setBalanceConfig, |
| checkDomainAllowed, |
| oauthHandler, |
| ); |
|
|
| |
| |
| |
| router.get( |
| '/apple', |
| passport.authenticate('apple', { |
| session: false, |
| }), |
| ); |
|
|
| router.post( |
| '/apple/callback', |
| passport.authenticate('apple', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| }), |
| setBalanceConfig, |
| checkDomainAllowed, |
| oauthHandler, |
| ); |
|
|
| |
| |
| |
| router.get( |
| '/saml', |
| passport.authenticate('saml', { |
| session: false, |
| }), |
| ); |
|
|
| router.post( |
| '/saml/callback', |
| passport.authenticate('saml', { |
| failureRedirect: `${domains.client}/oauth/error`, |
| failureMessage: true, |
| session: false, |
| }), |
| oauthHandler, |
| ); |
|
|
| module.exports = router; |
|
|