mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-14 22:48:52 +01:00
🍪 refactor: Move OpenID Tokens from Cookies to Server-Side Sessions (#11236)
* refactor: OpenID token handling by storing tokens in session to reduce cookie size * refactor: Improve OpenID user identification logic in logout controller * refactor: Enhance OpenID logout flow by adding post-logout redirect URI * refactor: Update logout process to clear additional OpenID user ID cookie
This commit is contained in:
parent
3b41e392ba
commit
348b4a4a32
8 changed files with 105 additions and 38 deletions
|
|
@ -66,14 +66,17 @@ const resetPasswordController = async (req, res) => {
|
|||
};
|
||||
|
||||
const refreshController = async (req, res) => {
|
||||
const refreshToken = req.headers.cookie ? cookies.parse(req.headers.cookie).refreshToken : null;
|
||||
const token_provider = req.headers.cookie
|
||||
? cookies.parse(req.headers.cookie).token_provider
|
||||
: null;
|
||||
if (!refreshToken) {
|
||||
return res.status(200).send('Refresh token not provided');
|
||||
}
|
||||
if (token_provider === 'openid' && isEnabled(process.env.OPENID_REUSE_TOKENS) === true) {
|
||||
const parsedCookies = req.headers.cookie ? cookies.parse(req.headers.cookie) : {};
|
||||
const token_provider = parsedCookies.token_provider;
|
||||
|
||||
if (token_provider === 'openid' && isEnabled(process.env.OPENID_REUSE_TOKENS)) {
|
||||
/** For OpenID users, read refresh token from session to avoid large cookie issues */
|
||||
const refreshToken = req.session?.openidTokens?.refreshToken || parsedCookies.refreshToken;
|
||||
|
||||
if (!refreshToken) {
|
||||
return res.status(200).send('Refresh token not provided');
|
||||
}
|
||||
|
||||
try {
|
||||
const openIdConfig = getOpenIdConfig();
|
||||
const tokenset = await openIdClient.refreshTokenGrant(openIdConfig, refreshToken);
|
||||
|
|
@ -110,7 +113,7 @@ const refreshController = async (req, res) => {
|
|||
);
|
||||
}
|
||||
|
||||
const token = setOpenIDAuthTokens(tokenset, res, user._id.toString(), refreshToken);
|
||||
const token = setOpenIDAuthTokens(tokenset, req, res, user._id.toString(), refreshToken);
|
||||
|
||||
user.federatedTokens = {
|
||||
access_token: tokenset.access_token,
|
||||
|
|
@ -125,6 +128,13 @@ const refreshController = async (req, res) => {
|
|||
return res.status(403).send('Invalid OpenID refresh token');
|
||||
}
|
||||
}
|
||||
|
||||
/** For non-OpenID users, read refresh token from cookies */
|
||||
const refreshToken = parsedCookies.refreshToken;
|
||||
if (!refreshToken) {
|
||||
return res.status(200).send('Refresh token not provided');
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
|
||||
const user = await getUserById(payload.id, '-password -__v -totpSecret -backupCodes');
|
||||
|
|
|
|||
|
|
@ -5,15 +5,28 @@ const { logoutUser } = require('~/server/services/AuthService');
|
|||
const { getOpenIdConfig } = require('~/strategies');
|
||||
|
||||
const logoutController = async (req, res) => {
|
||||
const refreshToken = req.headers.cookie ? cookies.parse(req.headers.cookie).refreshToken : null;
|
||||
const parsedCookies = req.headers.cookie ? cookies.parse(req.headers.cookie) : {};
|
||||
const isOpenIdUser = req.user?.openidId != null && req.user?.provider === 'openid';
|
||||
|
||||
/** For OpenID users, read refresh token from session; for others, use cookie */
|
||||
let refreshToken;
|
||||
if (isOpenIdUser && req.session?.openidTokens) {
|
||||
refreshToken = req.session.openidTokens.refreshToken;
|
||||
delete req.session.openidTokens;
|
||||
}
|
||||
refreshToken = refreshToken || parsedCookies.refreshToken;
|
||||
|
||||
try {
|
||||
const logout = await logoutUser(req, refreshToken);
|
||||
const { status, message } = logout;
|
||||
|
||||
res.clearCookie('refreshToken');
|
||||
res.clearCookie('openid_access_token');
|
||||
res.clearCookie('openid_user_id');
|
||||
res.clearCookie('token_provider');
|
||||
const response = { message };
|
||||
if (
|
||||
req.user.openidId != null &&
|
||||
isOpenIdUser &&
|
||||
isEnabled(process.env.OPENID_USE_END_SESSION_ENDPOINT) &&
|
||||
process.env.OPENID_ISSUER
|
||||
) {
|
||||
|
|
@ -27,7 +40,12 @@ const logoutController = async (req, res) => {
|
|||
? openIdConfig.serverMetadata().end_session_endpoint
|
||||
: null;
|
||||
if (endSessionEndpoint) {
|
||||
response.redirect = endSessionEndpoint;
|
||||
const endSessionUrl = new URL(endSessionEndpoint);
|
||||
/** Redirect back to app's login page after IdP logout */
|
||||
const postLogoutRedirectUri =
|
||||
process.env.OPENID_POST_LOGOUT_REDIRECT_URI || `${process.env.DOMAIN_CLIENT}/login`;
|
||||
endSessionUrl.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri);
|
||||
response.redirect = endSessionUrl.toString();
|
||||
} else {
|
||||
logger.warn(
|
||||
'[logoutController] end_session_endpoint not found in OpenID issuer metadata. Please verify that the issuer is correct.',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue