Instantly share code, notes, and snippets.
Last active
August 7, 2025 15:30
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save gaieges/1e0644731abcc6ce3209d9eeeacdec99 to your computer and use it in GitHub Desktop.
Librechat Custom Middleware using domain cookie
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* LibreChat middleware to inject req.user from a Django Allauth session cookie that our backend provides and we grab from the user. | |
* | |
* Looks up the user by calling the Django user info endpoint (provided by django allauth) | |
*/ | |
const axios = require('axios'); | |
const { logger } = require('~/config'); | |
const { setAuthTokens } = require('~/server/services/AuthService'); | |
const { findUser, createUser } = require('~/models'); | |
const { getBalanceConfig } = require('~/server/services/Config'); | |
/** | |
* Django allauth response looks like: | |
* { | |
"status": 200, | |
"data": { | |
"user": { | |
"display": "frank rizzo", | |
"has_usable_password": false, | |
"id": 1, | |
"email": "[email protected]", | |
"username": "frank", | |
"first_name": "frank", | |
"last_name": "rizzo", | |
"picture": "https://lh3.googleusercontent.com/a/ACRBYHtpCW7NQwuN-MyTTPww=s96-c" | |
}, | |
"methods": [ | |
{ | |
"method": "socialaccount", | |
"at": 1753993216.6699917, | |
"provider": "google", | |
"uid": "1122" | |
} | |
] | |
}, | |
"meta": { | |
"is_authenticated": true | |
} | |
} | |
* | |
*/ | |
module.exports = async function domainCookieSessionIdAuth(req, res, next) { | |
const sessionId = req.cookies['sessionid']; // Django session cookie | |
logger.debug(`[domainCookieSessionIdAuth] checking session id: ${sessionId}`); | |
if (!sessionId) { | |
return next(); // Let other auth methods handle this | |
} | |
// Pass cookies to Django backend to authenticate the user | |
try { | |
const response = await axios.get('https://api.mybackend.com/_allauth/browser/v1/auth/session', { | |
headers: { | |
// Forward the cookie for session authentication | |
Cookie: `sessionid=${sessionId}`, | |
}, | |
withCredentials: true, | |
}); | |
logger.debug(`${response.status} response: ${JSON.stringify(response.data, null, 2)}`); | |
const content = response.data; | |
if (content?.meta?.is_authenticated === false) { | |
logger.warn("not authenticated from server"); | |
return next(); | |
} | |
if (response.status === 200 && content?.data?.user) { | |
logger.debug("good status response from auth server"); | |
// Map backend user to an existing (or new) LibreChat Mongo user | |
const userData = content.data.user; | |
let mongoUser; | |
try { | |
mongoUser = await findUser({ email: userData.email }, '-password -__v -totpSecret'); | |
if (!mongoUser) { | |
const balanceConfig = await getBalanceConfig(); | |
const newUserData = { | |
provider: 'domainCookie', | |
email: userData.email, | |
username: userData.username || userData.email, | |
name: | |
((userData.first_name ?? '') + ' ' + (userData.last_name ?? '')).trim() || | |
userData.display || | |
userData.username || | |
userData.email, | |
avatar: userData.picture || null, | |
role: 'user', | |
emailVerified: true, | |
cookieId: userData.id, | |
}; | |
mongoUser = await createUser(newUserData, balanceConfig, true, true); | |
logger.info(`[domainCookieSessionIdAuth] created local user for ${userData.email}`); | |
} | |
} catch (userErr) { | |
logger.error('[domainCookieSessionIdAuth] error fetching/creating local user:', userErr); | |
return next(); | |
} | |
// Ensure downstream middleware sees a fully-formed user object | |
req.user = mongoUser.toObject ? mongoUser.toObject() : { ...mongoUser }; | |
req.user.id = mongoUser._id.toString(); | |
// Keep original backend payload for reference | |
req.user._authData = response.data; | |
logger.debug(`[domainCookieSessionIdAuth] authenticated user: ${req.user.username || req.user.email}`); | |
/* ------------------------------------------------------------------ | |
* Mint LibreChat auth tokens (refresh cookie + JWT) | |
* ----------------------------------------------------------------- */ | |
try { | |
if (!req.cookies.refreshToken) { | |
const token = await setAuthTokens(req.user.id, res); | |
// Allow downstream middlewares to see the JWT immediately | |
req.headers.authorization = `Bearer ${token}`; | |
logger.debug('[domainCookieSessionIdAuth] issued LibreChat tokens for user via cookie auth'); | |
} | |
} catch (tokenErr) { | |
logger.error('[domainCookieSessionIdAuth] error issuing auth tokens:', tokenErr); | |
} | |
} | |
} catch (err) { | |
logger.error(`[domainCookieSessionIdAuth] couldnt authenticate user: ${err}`); | |
return next(); | |
} | |
logger.debug(`[domainCookieSessionIdAuth] exiting auth middleware with req.user set to: ${JSON.stringify(req.user, null, 2)}`); | |
next(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment