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:
@@ -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}`, {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user