How to redirect after failed refresh token
I am using
react-query
along with axios
to communicate with my API. This is the interceptor I have built, to refresh the Access Token when it expires:
const BASE_URL = process.env.NEXT_PUBLIC_BACKEND_URL;
const client = axios.create({
baseURL: BASE_URL,
withCredentials: true,
headers: { 'Content-Type': 'application/json' },
});
const onFulfilled = (response) => response;
const onRejected = async (error) => {
const originalRequest = error.config;
// Check if the error is due to an expired token
const is401 = error.response.status === 401;
const isExpired = error.response.data.code === 'ACCESS_TOKEN_EXPIRED';
const isRetry = originalRequest._retry;
if (is401 && isExpired && !isRetry) {
// If the error is due to an expired token and the request hasn't been retried yet
originalRequest._retry = true; // Mark this request as already tried
try {
// Attempt to refresh the token by calling the '/refresh-token' endpoint.
await client.post('/v1/auth/refresh-token');
// The browser will automatically handle the new token as it's stored in an HttpOnly cookie.
// Retry the original request. Axios will automatically include the refreshed token (stored in HttpOnly cookie) with this request.
return client(originalRequest);
} catch (refreshError) {
// If token refresh fails, handle accordingly (e.g., redirect to login)
console.log('Refresh token failed');
console.log(refreshError);
return Promise.reject(refreshError);
}
}
// For any other error, just return it
return Promise.reject(error);
};
client.interceptors.response.use(onFulfilled, onRejected);
const BASE_URL = process.env.NEXT_PUBLIC_BACKEND_URL;
const client = axios.create({
baseURL: BASE_URL,
withCredentials: true,
headers: { 'Content-Type': 'application/json' },
});
const onFulfilled = (response) => response;
const onRejected = async (error) => {
const originalRequest = error.config;
// Check if the error is due to an expired token
const is401 = error.response.status === 401;
const isExpired = error.response.data.code === 'ACCESS_TOKEN_EXPIRED';
const isRetry = originalRequest._retry;
if (is401 && isExpired && !isRetry) {
// If the error is due to an expired token and the request hasn't been retried yet
originalRequest._retry = true; // Mark this request as already tried
try {
// Attempt to refresh the token by calling the '/refresh-token' endpoint.
await client.post('/v1/auth/refresh-token');
// The browser will automatically handle the new token as it's stored in an HttpOnly cookie.
// Retry the original request. Axios will automatically include the refreshed token (stored in HttpOnly cookie) with this request.
return client(originalRequest);
} catch (refreshError) {
// If token refresh fails, handle accordingly (e.g., redirect to login)
console.log('Refresh token failed');
console.log(refreshError);
return Promise.reject(refreshError);
}
}
// For any other error, just return it
return Promise.reject(error);
};
client.interceptors.response.use(onFulfilled, onRejected);
1 Reply
flat-fuchsiaOP•2y ago
This works well, but now I want that when the refreshing fails, I am redirected to the login page. I thought that this code might do it:
But the error handler never executes, for some reason. What am I doing wrong?
No love for this question? 😦
'use client';
import { useRouter } from 'next/navigation';
import { LanguageProvider } from './LanguageContext';
import { SessionProvider } from './SessionContext';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const AppProviders = ({ children }) => {
const { push } = useRouter();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false, // Disable retries on queries
onError: (error) => {
console.log('query client error', error);
if (error?.response?.status === 401) {
push('/auth/login');
}
},
},
},
});
return (
<QueryClientProvider client={queryClient}>
<LanguageProvider>
<SessionProvider>{children}</SessionProvider>
</LanguageProvider>
</QueryClientProvider>
);
};
export default AppProviders;
'use client';
import { useRouter } from 'next/navigation';
import { LanguageProvider } from './LanguageContext';
import { SessionProvider } from './SessionContext';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const AppProviders = ({ children }) => {
const { push } = useRouter();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false, // Disable retries on queries
onError: (error) => {
console.log('query client error', error);
if (error?.response?.status === 401) {
push('/auth/login');
}
},
},
},
});
return (
<QueryClientProvider client={queryClient}>
<LanguageProvider>
<SessionProvider>{children}</SessionProvider>
</LanguageProvider>
</QueryClientProvider>
);
};
export default AppProviders;