Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 1x 1x 1x 3x 3x 1x 3x 1x 2x 1x 1x 1x | /**
* Axios Auth Interceptor
*
* Attaches JWT token to requests and handles 401 refresh flow.
*/
import axios from 'axios';
import { getAccessToken, getRefreshToken, setTokens, clearTokens } from './token-storage';
let isRefreshing = false;
let refreshSubscribers: ((token: string) => void)[] = [];
function onRefreshed(token: string) {
refreshSubscribers.forEach(cb => cb(token));
refreshSubscribers = [];
}
function addRefreshSubscriber(cb: (token: string) => void) {
refreshSubscribers.push(cb);
}
export function setupAuthInterceptors(): void {
// Request interceptor: attach token
axios.interceptors.request.use((config) => {
const token = getAccessToken();
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Response interceptor: handle 401 with token refresh
axios.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// Don't retry auth endpoints or already-retried requests
Eif (
!originalRequest ||
originalRequest._retry ||
originalRequest.url?.includes('/api/auth/')
) {
return Promise.reject(error);
}
if (error.response?.status === 401) {
if (isRefreshing) {
// Queue this request until refresh completes
return new Promise((resolve) => {
addRefreshSubscriber((token: string) => {
originalRequest.headers.Authorization = `Bearer ${token}`;
resolve(axios(originalRequest));
});
});
}
originalRequest._retry = true;
isRefreshing = true;
const refreshToken = getRefreshToken();
if (!refreshToken) {
clearTokens();
window.location.reload();
return Promise.reject(error);
}
try {
const response = await axios.post('/api/auth/refresh', { refreshToken });
const { token, refreshToken: newRefreshToken } = response.data;
setTokens(token, newRefreshToken);
isRefreshing = false;
onRefreshed(token);
originalRequest.headers.Authorization = `Bearer ${token}`;
return axios(originalRequest);
} catch {
isRefreshing = false;
refreshSubscribers = [];
clearTokens();
window.location.reload();
return Promise.reject(error);
}
}
return Promise.reject(error);
}
);
}
|