mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00
fix: getLogStores
Property and Handle 401 Error from Refresh Token Request (#1084)
* fix(getLogStores): correct wrong prop passed to keyv opts: duration -> ttl * fix: edge case where we get a blank screen if the initially intercepted 401 error is from a refresh token request; in this case, make explicit to the server that we are retrying from a refreshToken request
This commit is contained in:
parent
abbc57a49a
commit
6cb561abcf
5 changed files with 33 additions and 27 deletions
2
api/cache/getLogStores.js
vendored
2
api/cache/getLogStores.js
vendored
|
@ -19,7 +19,7 @@ const pending_req = isEnabled(USE_REDIS)
|
|||
|
||||
const namespaces = {
|
||||
pending_req,
|
||||
ban: new Keyv({ store: keyvMongo, namespace: 'bans', duration }),
|
||||
ban: new Keyv({ store: keyvMongo, namespace: 'bans', ttl: duration }),
|
||||
general: new Keyv({ store: logFile, namespace: 'violations' }),
|
||||
concurrent: createViolationInstance('concurrent'),
|
||||
non_browser: createViolationInstance('non_browser'),
|
||||
|
|
|
@ -106,6 +106,9 @@ const refreshController = async (req, res) => {
|
|||
const token = await setAuthTokens(userId, res, session._id);
|
||||
const userObj = user.toJSON();
|
||||
res.status(200).send({ token, user: userObj });
|
||||
} else if (req?.query?.retry) {
|
||||
// Retrying from a refresh token request that failed (401)
|
||||
res.status(403).send('No session found');
|
||||
} else if (payload.exp < Date.now() / 1000) {
|
||||
res.status(403).redirect('/login');
|
||||
} else {
|
||||
|
|
|
@ -52,7 +52,7 @@ export const loginFacebook = () => '/api/auth/facebook';
|
|||
|
||||
export const loginGoogle = () => '/api/auth/google';
|
||||
|
||||
export const refreshToken = () => '/api/auth/refresh';
|
||||
export const refreshToken = (retry?: boolean) => `/api/auth/refresh${retry ? '?retry=true' : ''}`;
|
||||
|
||||
export const requestPasswordReset = () => '/api/auth/requestPasswordReset';
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ export const register = (payload: t.TRegisterUser) => {
|
|||
return request.post(endpoints.register(), payload);
|
||||
};
|
||||
|
||||
export const refreshToken = () => request.post(endpoints.refreshToken());
|
||||
export const refreshToken = (retry?: boolean) => request.post(endpoints.refreshToken(retry));
|
||||
|
||||
export const userKeyQuery = (name: string): Promise<t.TCheckUserKeyResponse> =>
|
||||
request.get(endpoints.userKeyQuery(name));
|
||||
|
|
|
@ -23,44 +23,47 @@ axios.interceptors.response.use(
|
|||
(response) => response,
|
||||
async (error) => {
|
||||
const originalRequest = error.config;
|
||||
|
||||
if (error.response.status === 401 && !originalRequest._retry) {
|
||||
originalRequest._retry = true;
|
||||
|
||||
if (isRefreshing) {
|
||||
try {
|
||||
const token = await new Promise(function (resolve, reject) {
|
||||
const token = await new Promise((resolve, reject) => {
|
||||
failedQueue.push({ resolve, reject });
|
||||
});
|
||||
originalRequest.headers['Authorization'] = 'Bearer ' + token;
|
||||
return await axios(originalRequest);
|
||||
} catch (err) {
|
||||
return await Promise.reject(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
originalRequest._retry = true;
|
||||
isRefreshing = true;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
refreshToken()
|
||||
.then(({ token }) => {
|
||||
if (token) {
|
||||
originalRequest.headers['Authorization'] = 'Bearer ' + token;
|
||||
setTokenHeader(token);
|
||||
window.dispatchEvent(new CustomEvent('tokenUpdated', { detail: token }));
|
||||
processQueue(null, token);
|
||||
resolve(axios(originalRequest));
|
||||
} else {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
processQueue(err, null);
|
||||
reject(err);
|
||||
})
|
||||
.then(() => {
|
||||
isRefreshing = false;
|
||||
});
|
||||
});
|
||||
try {
|
||||
const { token } = 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 : false,
|
||||
);
|
||||
|
||||
if (token) {
|
||||
originalRequest.headers['Authorization'] = 'Bearer ' + token;
|
||||
setTokenHeader(token);
|
||||
window.dispatchEvent(new CustomEvent('tokenUpdated', { detail: token }));
|
||||
processQueue(null, token);
|
||||
return await axios(originalRequest);
|
||||
} else {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
} catch (err) {
|
||||
processQueue(err as AxiosError, null);
|
||||
return Promise.reject(err);
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue