Add refresh token functionality and improve login response handling

- Introduced RefreshTokenView to allow users to refresh their access tokens using a valid refresh token.
- Enhanced LoginView to ensure correct user/account loading and improved error handling during user serialization.
- Updated API response structure to include access and refresh token expiration times.
- Adjusted frontend API handling to support both new and legacy token response formats.
This commit is contained in:
IGNY8 VPS (Salman)
2025-11-16 21:06:22 +00:00
parent 1531f41226
commit fc6dd5623a
8 changed files with 155 additions and 33 deletions

View File

@@ -194,13 +194,14 @@ export async function fetchAPI(endpoint: string, options?: RequestInit & { timeo
if (refreshResponse.ok) {
const refreshData = await refreshResponse.json();
if (refreshData.success && refreshData.access) {
const accessToken = refreshData.data?.access || refreshData.access;
if (refreshData.success && accessToken) {
// Update token in store
try {
const authStorage = localStorage.getItem('auth-storage');
if (authStorage) {
const parsed = JSON.parse(authStorage);
parsed.state.token = refreshData.access;
parsed.state.token = accessToken;
localStorage.setItem('auth-storage', JSON.stringify(parsed));
}
} catch (e) {
@@ -210,7 +211,7 @@ export async function fetchAPI(endpoint: string, options?: RequestInit & { timeo
// Retry original request with new token
const newHeaders = {
...headers,
'Authorization': `Bearer ${refreshData.access}`,
'Authorization': `Bearer ${accessToken}`,
};
const retryResponse = await fetch(`${API_BASE_URL}${endpoint}`, {

View File

@@ -60,14 +60,17 @@ export const useAuthStore = create<AuthState>()(
const data = await response.json();
if (!response.ok || !data.success) {
throw new Error(data.message || 'Login failed');
throw new Error(data.error || data.message || 'Login failed');
}
// Store user and JWT tokens
// Store user and JWT tokens (handle both old and new API formats)
const responseData = data.data || data;
// Support both formats: new (access/refresh at top level) and old (tokens.access/refresh)
const tokens = responseData.tokens || {};
set({
user: data.user,
token: data.tokens?.access || null,
refreshToken: data.tokens?.refresh || null,
user: responseData.user || data.user,
token: responseData.access || tokens.access || data.access || null,
refreshToken: responseData.refresh || tokens.refresh || data.refresh || null,
isAuthenticated: true,
loading: false
});
@@ -119,8 +122,8 @@ export const useAuthStore = create<AuthState>()(
// Store user and JWT tokens
set({
user: data.user,
token: data.tokens?.access || null,
refreshToken: data.tokens?.refresh || null,
token: data.data?.access || data.access || null,
refreshToken: data.data?.refresh || data.refresh || null,
isAuthenticated: true,
loading: false
});
@@ -168,8 +171,8 @@ export const useAuthStore = create<AuthState>()(
throw new Error(data.message || 'Token refresh failed');
}
// Update access token
set({ token: data.access });
// Update access token (API returns access at top level of data)
set({ token: data.data?.access || data.access });
// Also refresh user data to get latest account/plan information
// This ensures account/plan changes are reflected immediately