diff --git a/api/server/controllers/AuthController.js b/api/server/controllers/AuthController.js index 22e53dcfc9..5348ed41df 100644 --- a/api/server/controllers/AuthController.js +++ b/api/server/controllers/AuthController.js @@ -74,7 +74,42 @@ const refreshController = async (req, res) => { const refreshToken = req.session?.openidTokens?.refreshToken || parsedCookies.refreshToken; if (!refreshToken) { - return res.status(200).send('Refresh token not provided'); + const accessToken = req.session?.openidTokens?.accessToken; + const storedUserId = req.session?.openidTokens?.userId; + + if (!accessToken || !storedUserId) { + return res.status(200).send('Refresh token not provided'); + } + + let tokenExpired = false; + try { + const decoded = jwt.decode(accessToken); + if (decoded?.exp && decoded.exp < Date.now() / 1000) { + tokenExpired = true; + } + } catch { + const expiresAt = req.session?.openidTokens?.expiresAt; + if (expiresAt && expiresAt < Date.now()) { + tokenExpired = true; + } + } + + if (tokenExpired) { + logger.warn('[refreshController] Access token expired and no refresh token available'); + return res.status(401).redirect('/login'); + } + + const user = await getUserById(storedUserId, '-password -__v -totpSecret -backupCodes'); + if (!user) { + return res.status(401).redirect('/login'); + } + + user.federatedTokens = { + access_token: accessToken, + expires_at: req.session?.openidTokens?.expiresAt, + }; + + return res.status(200).send({ token: accessToken, user }); } try { diff --git a/api/server/services/AuthService.js b/api/server/services/AuthService.js index a400bce8b7..101e748217 100644 --- a/api/server/services/AuthService.js +++ b/api/server/services/AuthService.js @@ -444,8 +444,9 @@ const setOpenIDAuthTokens = (tokenset, req, res, userId, existingRefreshToken) = const refreshToken = tokenset.refresh_token || existingRefreshToken; if (!refreshToken) { - logger.error('[setOpenIDAuthTokens] No refresh token available'); - return; + logger.warn( + '[setOpenIDAuthTokens] No refresh token available — session will not auto-refresh', + ); } /** Store tokens server-side in session to avoid large cookies */ @@ -454,6 +455,7 @@ const setOpenIDAuthTokens = (tokenset, req, res, userId, existingRefreshToken) = accessToken: tokenset.access_token, refreshToken: refreshToken, expiresAt: expirationDate.getTime(), + userId: userId, }; } else { logger.warn('[setOpenIDAuthTokens] No session available, falling back to cookies');