Initial Commit
This commit is contained in:
@@ -28,35 +28,102 @@ export const Auth0Provider: React.FC<Auth0ProviderProps> = ({ children }) => {
|
||||
domain={domain}
|
||||
clientId={clientId}
|
||||
authorizationParams={{
|
||||
redirect_uri: window.location.origin,
|
||||
redirect_uri: window.location.hostname === "admin.motovaultpro.com" ? "https://admin.motovaultpro.com/callback" : window.location.origin + "/callback",
|
||||
audience: audience,
|
||||
}}
|
||||
onRedirectCallback={onRedirectCallback}
|
||||
cacheLocation="localstorage"
|
||||
useRefreshTokens={true}
|
||||
>
|
||||
<TokenInjector>{children}</TokenInjector>
|
||||
</BaseAuth0Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Component to inject token into API client
|
||||
// Component to inject token into API client with mobile support
|
||||
const TokenInjector: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const { getAccessTokenSilently, isAuthenticated } = useAuth0();
|
||||
const [retryCount, setRetryCount] = React.useState(0);
|
||||
|
||||
// Helper function to get token with retry logic for mobile devices
|
||||
const getTokenWithRetry = async (maxRetries = 3, delayMs = 500): Promise<string | null> => {
|
||||
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||
try {
|
||||
// Progressive fallback strategy for mobile compatibility
|
||||
let tokenOptions;
|
||||
if (attempt === 0) {
|
||||
// First attempt: try cache first
|
||||
tokenOptions = { timeoutInSeconds: 15, cacheMode: 'on' as const };
|
||||
} else if (attempt === 1) {
|
||||
// Second attempt: force refresh
|
||||
tokenOptions = { timeoutInSeconds: 20, cacheMode: 'off' as const };
|
||||
} else {
|
||||
// Final attempt: default behavior with longer timeout
|
||||
tokenOptions = { timeoutInSeconds: 30 };
|
||||
}
|
||||
|
||||
const token = await getAccessTokenSilently(tokenOptions);
|
||||
console.log(`Token acquired successfully on attempt ${attempt + 1}`);
|
||||
return token;
|
||||
} catch (error: any) {
|
||||
console.warn(`Token acquisition attempt ${attempt + 1} failed:`, error.message || error);
|
||||
|
||||
// On mobile, Auth0 might need more time - wait and retry
|
||||
if (attempt < maxRetries - 1) {
|
||||
const delay = delayMs * Math.pow(2, attempt); // Exponential backoff
|
||||
console.log(`Waiting ${delay}ms before retry...`);
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
}
|
||||
console.error('All token acquisition attempts failed');
|
||||
return null;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
let interceptorId: number | undefined;
|
||||
|
||||
if (isAuthenticated) {
|
||||
// Add token to all API requests
|
||||
// Pre-warm token cache for mobile devices with delay
|
||||
const initializeToken = async () => {
|
||||
// Give Auth0 a moment to fully initialize on mobile
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
try {
|
||||
const token = await getTokenWithRetry();
|
||||
if (token) {
|
||||
console.log('Token pre-warming successful');
|
||||
setRetryCount(0);
|
||||
} else {
|
||||
console.error('Failed to acquire token after retries - will retry on API calls');
|
||||
setRetryCount(prev => prev + 1);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Token initialization failed:', error);
|
||||
setRetryCount(prev => prev + 1);
|
||||
}
|
||||
};
|
||||
|
||||
initializeToken();
|
||||
|
||||
// Add token to all API requests with enhanced error handling
|
||||
interceptorId = apiClient.interceptors.request.use(async (config) => {
|
||||
try {
|
||||
const token = await getAccessTokenSilently();
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
} catch (error) {
|
||||
console.error('Failed to get access token:', error);
|
||||
const token = await getTokenWithRetry();
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
} else {
|
||||
console.error('No token available for request to:', config.url);
|
||||
// Allow request to proceed - backend will return 401 if needed
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Failed to get access token for request:', error.message || error);
|
||||
// Allow request to proceed - backend will return 401 if needed
|
||||
}
|
||||
return config;
|
||||
});
|
||||
} else {
|
||||
setRetryCount(0);
|
||||
}
|
||||
|
||||
// Cleanup function to remove interceptor
|
||||
@@ -65,7 +132,7 @@ const TokenInjector: React.FC<{ children: React.ReactNode }> = ({ children }) =>
|
||||
apiClient.interceptors.request.eject(interceptorId);
|
||||
}
|
||||
};
|
||||
}, [isAuthenticated, getAccessTokenSilently]);
|
||||
}, [isAuthenticated, getAccessTokenSilently, retryCount]);
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
Reference in New Issue
Block a user