Adds access token refreshing.
This commit is contained in:
@@ -19,6 +19,34 @@ export function useClient() {
|
|||||||
|
|
||||||
api.interceptors.request.use(requestInterceptor);
|
api.interceptors.request.use(requestInterceptor);
|
||||||
|
|
||||||
|
// Add response interceptor for token refresh
|
||||||
|
api.interceptors.response.use(
|
||||||
|
(response) => response,
|
||||||
|
async (error) => {
|
||||||
|
const originalRequest = error.config;
|
||||||
|
|
||||||
|
// If error is 401 and we haven't tried to refresh the token yet
|
||||||
|
if (error.response?.status === 401 && !originalRequest._retry) {
|
||||||
|
originalRequest._retry = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Attempt to refresh the token
|
||||||
|
await authStore.refresh();
|
||||||
|
|
||||||
|
// Retry the original request with the new token
|
||||||
|
originalRequest.headers["Authorization"] = `Bearer ${authStore.accessToken}`;
|
||||||
|
return api(originalRequest);
|
||||||
|
} catch (refreshError) {
|
||||||
|
// If refresh fails, logout the user
|
||||||
|
await authStore.logout();
|
||||||
|
return Promise.reject(refreshError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,17 @@ function getClaimsFromToken(token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTokenExpired(token) {
|
||||||
|
if (!token) return true;
|
||||||
|
const claims = getClaimsFromToken(token);
|
||||||
|
if (!claims) return true;
|
||||||
|
|
||||||
|
// Check if token will expire in the next 5 minutes
|
||||||
|
const expirationTime = claims.exp * 1000; // Convert to milliseconds
|
||||||
|
const currentTime = Date.now();
|
||||||
|
return currentTime >= expirationTime - 5 * 60 * 1000; // 5 minutes before expiration
|
||||||
|
}
|
||||||
|
|
||||||
export const useAuthStore = defineStore(
|
export const useAuthStore = defineStore(
|
||||||
'auth',
|
'auth',
|
||||||
() => {
|
() => {
|
||||||
@@ -22,7 +33,7 @@ export const useAuthStore = defineStore(
|
|||||||
const accessToken = useSessionStorage('auth-accessToken', undefined)
|
const accessToken = useSessionStorage('auth-accessToken', undefined)
|
||||||
const refreshToken = useSessionStorage('auth-refreshToken', undefined)
|
const refreshToken = useSessionStorage('auth-refreshToken', undefined)
|
||||||
|
|
||||||
const isAuthenticated = computed(() => !!accessToken.value)
|
const isAuthenticated = computed(() => !!accessToken.value && !isTokenExpired(accessToken.value))
|
||||||
|
|
||||||
const userId = computed(() => {
|
const userId = computed(() => {
|
||||||
const claims = getClaimsFromToken(accessToken.value)
|
const claims = getClaimsFromToken(accessToken.value)
|
||||||
@@ -96,20 +107,33 @@ export const useAuthStore = defineStore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
|
if (!refreshToken.value) {
|
||||||
|
throw new Error('No refresh token available');
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await clientApi.post(
|
const response = await clientApi.post(
|
||||||
'api/users/refresh',
|
'api/users/refresh',
|
||||||
{
|
{
|
||||||
refreshToken: refreshToken
|
refreshToken: refreshToken.value
|
||||||
});
|
});
|
||||||
|
|
||||||
updateTokens({
|
updateTokens({
|
||||||
accessToken: response.accessToken,
|
accessToken: response.data.accessToken,
|
||||||
refreshToken: refreshToken
|
refreshToken: response.data.refreshToken
|
||||||
})
|
});
|
||||||
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error('Token refresh failed:', error);
|
||||||
cleanTokens()
|
cleanTokens();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to check if token needs refresh
|
||||||
|
async function ensureValidToken() {
|
||||||
|
if (isTokenExpired(accessToken.value)) {
|
||||||
|
await refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +145,8 @@ export const useAuthStore = defineStore(
|
|||||||
login,
|
login,
|
||||||
loginWithGoogle,
|
loginWithGoogle,
|
||||||
loginWithFacebook,
|
loginWithFacebook,
|
||||||
logout
|
logout,
|
||||||
|
refresh,
|
||||||
|
ensureValidToken
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user