feat(auth): Implemented Session Persistence
This commit is contained in:
@@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user