Harden web session handling and production config

This commit is contained in:
2026-04-07 19:48:48 -05:00
parent 890f3fff2b
commit 0292b2e85a
9 changed files with 96 additions and 20 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ export const register = (data) => client.post('/auth/register', data, {
},
});
export const login = (data) => client.post('/auth/login', data);
export const logout = (refreshToken) => client.post('/auth/logout', { refreshToken });
export const logout = () => client.post('/auth/logout', {});
export const getMe = () => client.get('/auth/me');
export const verifyEmail = (token) => client.get(`/auth/verify/${token}`);
export const changePassword = (data) => client.patch('/auth/change-password', data);
+5 -6
View File
@@ -5,6 +5,7 @@ const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:4000';
const client = axios.create({
baseURL: API_URL,
headers: { 'Content-Type': 'application/json' },
withCredentials: true,
});
client.interceptors.request.use((config) => {
@@ -19,18 +20,16 @@ client.interceptors.response.use(
const original = error.config;
if (error.response?.status === 401 && !original._retry) {
original._retry = true;
const refreshToken = localStorage.getItem('refreshToken');
if (refreshToken) {
const hadAccessToken = Boolean(localStorage.getItem('accessToken'));
if (hadAccessToken) {
try {
const { data } = await axios.post(`${API_URL}/auth/refresh`, { refreshToken });
const { accessToken, refreshToken: newRefresh } = data.data;
const { data } = await axios.post(`${API_URL}/auth/refresh`, {}, { withCredentials: true });
const { accessToken } = data.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', newRefresh);
original.headers.Authorization = `Bearer ${accessToken}`;
return client(original);
} catch {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
window.location.href = '/login';
}
}
+2 -6
View File
@@ -15,7 +15,6 @@ export function AuthProvider({ children }) {
.then(({ data }) => setUser(data.data.user))
.catch(() => {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
})
.finally(() => setLoading(false));
} else {
@@ -25,18 +24,15 @@ export function AuthProvider({ children }) {
const login = useCallback(async (email, password) => {
const { data } = await apiLogin({ email, password });
const { accessToken, refreshToken, user: userData } = data.data;
const { accessToken, user: userData } = data.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', refreshToken);
setUser(userData);
return userData;
}, []);
const logout = useCallback(async () => {
const refreshToken = localStorage.getItem('refreshToken');
try { await apiLogout(refreshToken); } catch { /* ignore */ }
try { await apiLogout(); } catch { /* ignore */ }
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
setUser(null);
}, []);