mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
🔄 fix: Resolve Infinite Refresh Loop on OpenID Provider/Database Switch (#11002)
The refreshController was not updating user openidId when found by email with a different openidId already set. This caused an infinite loop where: 1. JWT auth failed (openidId mismatch) 2. Refresh found user by email but didn't update openidId 3. Next JWT auth failed again → loop Now updates openidId when either migration is needed OR when the stored openidId doesn't match the token's sub claim. Added debug logging for visibility into auth state during refresh.
This commit is contained in:
parent
b4459ab564
commit
d505e3124f
1 changed files with 30 additions and 2 deletions
|
|
@ -10,7 +10,13 @@ const {
|
|||
setAuthTokens,
|
||||
registerUser,
|
||||
} = require('~/server/services/AuthService');
|
||||
const { findUser, getUserById, deleteAllUserSessions, findSession } = require('~/models');
|
||||
const {
|
||||
deleteAllUserSessions,
|
||||
getUserById,
|
||||
findSession,
|
||||
updateUser,
|
||||
findUser,
|
||||
} = require('~/models');
|
||||
const { getGraphApiToken } = require('~/server/services/GraphTokenService');
|
||||
const { getOAuthReconnectionManager } = require('~/config');
|
||||
const { getOpenIdConfig } = require('~/strategies');
|
||||
|
|
@ -72,16 +78,38 @@ const refreshController = async (req, res) => {
|
|||
const openIdConfig = getOpenIdConfig();
|
||||
const tokenset = await openIdClient.refreshTokenGrant(openIdConfig, refreshToken);
|
||||
const claims = tokenset.claims();
|
||||
const { user, error } = await findOpenIDUser({
|
||||
const { user, error, migration } = await findOpenIDUser({
|
||||
findUser,
|
||||
email: claims.email,
|
||||
openidId: claims.sub,
|
||||
idOnTheSource: claims.oid,
|
||||
strategyName: 'refreshController',
|
||||
});
|
||||
|
||||
logger.debug(
|
||||
`[refreshController] findOpenIDUser result: user=${user?.email ?? 'null'}, error=${error ?? 'null'}, migration=${migration}, userOpenidId=${user?.openidId ?? 'null'}, claimsSub=${claims.sub}`,
|
||||
);
|
||||
|
||||
if (error || !user) {
|
||||
logger.warn(
|
||||
`[refreshController] Redirecting to /login: error=${error ?? 'null'}, user=${user ? 'exists' : 'null'}`,
|
||||
);
|
||||
return res.status(401).redirect('/login');
|
||||
}
|
||||
|
||||
// Handle migration: update user with openidId if found by email without openidId
|
||||
// Also handle case where user has mismatched openidId (e.g., after database switch)
|
||||
if (migration || user.openidId !== claims.sub) {
|
||||
const reason = migration ? 'migration' : 'openidId mismatch';
|
||||
await updateUser(user._id.toString(), {
|
||||
provider: 'openid',
|
||||
openidId: claims.sub,
|
||||
});
|
||||
logger.info(
|
||||
`[refreshController] Updated user ${user.email} openidId (${reason}): ${user.openidId ?? 'null'} -> ${claims.sub}`,
|
||||
);
|
||||
}
|
||||
|
||||
const token = setOpenIDAuthTokens(tokenset, res, user._id.toString(), refreshToken);
|
||||
|
||||
user.federatedTokens = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue