diff --git a/api/server/controllers/AuthController.js b/api/server/controllers/AuthController.js index d9bc87a5b..08d649932 100644 --- a/api/server/controllers/AuthController.js +++ b/api/server/controllers/AuthController.js @@ -96,14 +96,17 @@ const refreshController = async (req, res) => { return res.status(200).send({ token, user }); } - // Find the session with the hashed refresh token - const session = await findSession({ - userId: userId, - refreshToken: refreshToken, - }); + /** Session with the hashed refresh token */ + const session = await findSession( + { + userId: userId, + refreshToken: refreshToken, + }, + { lean: false }, + ); if (session && session.expiration > new Date()) { - const token = await setAuthTokens(userId, res, session._id); + const token = await setAuthTokens(userId, res, session); res.status(200).send({ token, user }); } else if (req?.query?.retry) { // Retrying from a refresh token request that failed (401) diff --git a/api/server/services/AuthService.js b/api/server/services/AuthService.js index ae2e48b8d..2ca9aa56b 100644 --- a/api/server/services/AuthService.js +++ b/api/server/services/AuthService.js @@ -357,23 +357,18 @@ const resetPassword = async (userId, token, password) => { /** * Set Auth Tokens - * * @param {String | ObjectId} userId - * @param {Object} res - * @param {String} sessionId + * @param {ServerResponse} res + * @param {ISession | null} [session=null] * @returns */ -const setAuthTokens = async (userId, res, sessionId = null) => { +const setAuthTokens = async (userId, res, _session = null) => { try { - const user = await getUserById(userId); - const token = await generateToken(user); - - let session; + let session = _session; let refreshToken; let refreshTokenExpires; - if (sessionId) { - session = await findSession({ sessionId: sessionId }, { lean: false }); + if (session && session._id && session.expiration != null) { refreshTokenExpires = session.expiration.getTime(); refreshToken = await generateRefreshToken(session); } else { @@ -383,6 +378,9 @@ const setAuthTokens = async (userId, res, sessionId = null) => { refreshTokenExpires = session.expiration.getTime(); } + const user = await getUserById(userId); + const token = await generateToken(user); + res.cookie('refreshToken', refreshToken, { expires: new Date(refreshTokenExpires), httpOnly: true, diff --git a/api/typedefs.js b/api/typedefs.js index d26617356..6cf87ef61 100644 --- a/api/typedefs.js +++ b/api/typedefs.js @@ -873,6 +873,13 @@ * @typedef {import('@librechat/data-schemas').IMongoFile} MongoFile * @memberof typedefs */ + +/** + * @exports ISession + * @typedef {import('@librechat/data-schemas').ISession} ISession + * @memberof typedefs + */ + /** * @exports IBalance * @typedef {import('@librechat/data-schemas').IBalance} IBalance diff --git a/packages/data-provider/src/request.ts b/packages/data-provider/src/request.ts index 3aa2021ea..8ca3980c7 100644 --- a/packages/data-provider/src/request.ts +++ b/packages/data-provider/src/request.ts @@ -98,12 +98,6 @@ if (typeof window !== 'undefined') { if (originalRequest.url?.includes('/api/auth/logout') === true) { return Promise.reject(error); } - if (originalRequest.url?.includes('/api/auth/refresh') === true) { - // Refresh token itself failed - redirect to login - console.log('Refresh token request failed, redirecting to login...'); - window.location.href = '/login'; - return Promise.reject(error); - } if (error.response.status === 401 && !originalRequest._retry) { console.warn('401 error, refreshing token'); @@ -124,7 +118,10 @@ if (typeof window !== 'undefined') { isRefreshing = true; try { - const response = await refreshToken(); + const response = await refreshToken( + // Handle edge case where we get a blank screen if the initial 401 error is from a refresh token request + originalRequest.url?.includes('api/auth/refresh') === true ? true : false, + ); const token = response?.token ?? '';