-
+
+
+
+
+ {/* Logo/Brand Section */}
+
+
+
Royal Enfield
+
Approval Portal
+
+
+ {/* Main Loader Card */}
+
+ {/* Status Icon */}
+
+ {authStep === 'error' ? (
+
+ ) : authStep === 'complete' ? (
+
+ ) : (
+
+
+ {/* Outer rotating ring */}
+
+
+
+ )}
+
+
+ {/* Loading Message */}
+
+
+ {authStep === 'complete' ? 'Welcome Back!' : authStep === 'error' ? 'Authentication Error' : 'Authenticating'}
+
+
{getLoadingMessage()}
+
+
+ {/* Progress Steps */}
+ {authStep !== 'error' && authStep !== 'complete' && (
+
+
+
+
Validating credentials
+
+
+
+
Loading your profile
+
+
+
+
Setting up your session
+
+
+ )}
+
+ {/* Error Message */}
+ {authStep === 'error' && error && (
+
+
{error.message || 'An error occurred during authentication'}
+
+
+ )}
+
+ {/* Animated Progress Bar */}
+ {authStep !== 'error' && authStep !== 'complete' && (
+
+ )}
+
+
+ {/* Footer Text */}
+
+ {authStep === 'complete' ? 'Redirecting to dashboard...' : 'Please wait while we secure your session'}
+
+
+
+ {/* Animated Background Elements */}
+
);
}
-
diff --git a/src/pages/Auth/AuthenticatedApp.tsx b/src/pages/Auth/AuthenticatedApp.tsx
index 1f8f3e8..7418511 100644
--- a/src/pages/Auth/AuthenticatedApp.tsx
+++ b/src/pages/Auth/AuthenticatedApp.tsx
@@ -9,6 +9,9 @@ export function AuthenticatedApp() {
const { isAuthenticated, isLoading, error, user, logout } = useAuth();
const [showDebugInfo, setShowDebugInfo] = useState(false);
+ // Check if we're on callback route (after all hooks are called)
+ const isCallbackRoute = typeof window !== 'undefined' && window.location.pathname === '/login/callback';
+
const handleLogout = async () => {
console.log('🔵 ========================================');
console.log('🔵 AuthenticatedApp.handleLogout - CALLED');
@@ -70,6 +73,11 @@ export function AuthenticatedApp() {
}
}, [isAuthenticated, isLoading, error, user]);
+ // Always show callback loader when on callback route (after all hooks)
+ if (isCallbackRoute) {
+ return
;
+ }
+
// Show loading state while checking authentication
if (isLoading) {
console.log('Auth0 is still loading...');
diff --git a/src/services/authApi.ts b/src/services/authApi.ts
index ca9ebc0..4526ee8 100644
--- a/src/services/authApi.ts
+++ b/src/services/authApi.ts
@@ -86,6 +86,7 @@ export interface TokenExchangeResponse {
};
accessToken: string;
refreshToken: string;
+ idToken?: string; // ID token from Okta for logout
}
export interface RefreshTokenResponse {
@@ -154,6 +155,11 @@ export async function exchangeCodeForTokens(
TokenManager.setAccessToken(result.accessToken);
TokenManager.setRefreshToken(result.refreshToken);
TokenManager.setUserData(result.user);
+ // Store id_token if available (needed for proper Okta logout)
+ if (result.idToken) {
+ TokenManager.setIdToken(result.idToken);
+ console.log('✅ ID token stored for logout');
+ }
console.log('✅ Tokens stored successfully');
} else {
console.warn('⚠️ Tokens missing in response', { result });
diff --git a/src/utils/tokenManager.ts b/src/utils/tokenManager.ts
index 4d5d11d..910b4f7 100644
--- a/src/utils/tokenManager.ts
+++ b/src/utils/tokenManager.ts
@@ -5,6 +5,7 @@
const ACCESS_TOKEN_KEY = 'accessToken';
const REFRESH_TOKEN_KEY = 'refreshToken';
+const ID_TOKEN_KEY = 'idToken';
const USER_DATA_KEY = 'userData';
/**
@@ -49,7 +50,7 @@ export const cookieUtils = {
* Attempts to clear cookies with different paths and domains
*/
clearAll(): void {
- const cookieNames = [ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY, USER_DATA_KEY];
+ const cookieNames = [ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY, ID_TOKEN_KEY, USER_DATA_KEY];
cookieNames.forEach(name => {
// Remove with default path
@@ -119,6 +120,27 @@ export class TokenManager {
return localStorage.getItem(REFRESH_TOKEN_KEY);
}
+ /**
+ * Store ID token (from Okta)
+ */
+ static setIdToken(token: string): void {
+ localStorage.setItem(ID_TOKEN_KEY, token);
+ if (this.isLocalhost()) {
+ cookieUtils.set(ID_TOKEN_KEY, token, 1); // 1 day
+ }
+ }
+
+ /**
+ * Get ID token
+ */
+ static getIdToken(): string | null {
+ if (this.isLocalhost()) {
+ // Try cookie first, then localStorage
+ return cookieUtils.get(ID_TOKEN_KEY) || localStorage.getItem(ID_TOKEN_KEY);
+ }
+ return localStorage.getItem(ID_TOKEN_KEY);
+ }
+
/**
* Store user data
*/
@@ -164,6 +186,7 @@ export class TokenManager {
const authKeys = [
ACCESS_TOKEN_KEY,
REFRESH_TOKEN_KEY,
+ ID_TOKEN_KEY,
USER_DATA_KEY,
'oktaToken',
'authToken',
@@ -172,6 +195,7 @@ export class TokenManager {
'access_token',
'refresh_token',
'id_token',
+ 'idToken',
'token',
'accessToken',
'refreshToken',