feat(auth): Implemented Session Persistence

This commit is contained in:
dhinesh-m24
2026-01-29 12:39:45 +05:30
parent e214e32c17
commit 7133e59e57
10 changed files with 417 additions and 32 deletions

View File

@@ -13,6 +13,12 @@ import { getAuth } from "firebase/auth";
const auth = getAuth(app);
// Token refresh interval tracking
let tokenRefreshInterval: number | null = null;
// Constants for session management
const TOKEN_REFRESH_INTERVAL = 40 * 60 * 1000; // Refresh token every 40 minutes (Firebase ID tokens expire in 1 hour)
/**
* Initialize Firebase Auth persistence
* Ensures user session persists across page refreshes
@@ -20,11 +26,64 @@ const auth = getAuth(app);
export const initializeAuthPersistence = async () => {
try {
await setPersistence(auth, browserLocalPersistence);
console.log("Auth persistence initialized with localStorage");
} catch (error) {
console.error("Error setting auth persistence:", error);
}
};
/**
* Refresh the current user's ID token to maintain session validity
* Firebase automatically refreshes tokens, but we can force a refresh to ensure validity
* @returns Promise<boolean> - true if refresh successful, false otherwise
*/
export const refreshUserToken = async (): Promise<boolean> => {
try {
const currentUser = auth.currentUser;
if (currentUser) {
await currentUser.getIdTokenResult(true); // Force refresh
console.log("Token refreshed successfully");
return true;
}
return false;
} catch (error) {
console.error("Error refreshing token:", error);
return false;
}
};
/**
* Start automatic token refresh mechanism
* Refreshes token periodically to prevent unexpected logouts
*/
export const startTokenRefreshTimer = () => {
// Clear any existing interval
if (tokenRefreshInterval) {
clearInterval(tokenRefreshInterval);
}
// Set up auto-refresh interval
tokenRefreshInterval = window.setInterval(async () => {
const currentUser = auth.currentUser;
if (currentUser) {
await refreshUserToken();
} else {
// If no user, stop the refresh timer
stopTokenRefreshTimer();
}
}, TOKEN_REFRESH_INTERVAL);
};
/**
* Stop the automatic token refresh timer
*/
export const stopTokenRefreshTimer = () => {
if (tokenRefreshInterval) {
clearInterval(tokenRefreshInterval);
tokenRefreshInterval = null;
}
};
/**
* Login user with email and password
*/
@@ -48,12 +107,27 @@ export const loginWithEmail = async (email: string, password: string) => {
/**
* Sign out the current user
* Clears session data, local storage, and stops token refresh
*/
export const logout = async () => {
try {
// Stop token refresh interval
stopTokenRefreshTimer();
// Clear any session-related data from localStorage
localStorage.removeItem('lastActivityTime');
localStorage.removeItem('sessionStartTime');
// Sign out from Firebase
await signOut(auth);
// Clear any other app-specific session data if needed
sessionStorage.clear();
console.log("User logged out successfully");
return { success: true };
} catch (error) {
console.error("Error during logout:", error);
return { success: false, error: (error as Error).message };
}
};
@@ -87,10 +161,23 @@ export const resetPassword = async (code: string, newPassword: string) => {
/**
* Subscribe to auth state changes
* Sets up token refresh timer when user logs in, stops it when logs out
* Returns unsubscribe function
*/
export const subscribeToAuthState = (callback: (user: User | null) => void) => {
return onAuthStateChanged(auth, callback);
return onAuthStateChanged(auth, (user) => {
if (user) {
// User logged in - start token refresh
startTokenRefreshTimer();
// Update last activity time
localStorage.setItem('lastActivityTime', Date.now().toString());
localStorage.setItem('sessionStartTime', Date.now().toString());
} else {
// User logged out - stop token refresh
stopTokenRefreshTimer();
}
callback(user);
});
};
/**