mirror of
https://github.com/R0m1k3/Regisflow.git
synced 2026-10-11 17:29:48 +02:00
Implement automatic logout after inactivity and improve authentication
Adds session timeout functionality using `useSessionTimeout` hook and updates session maxAge to 15 minutes in server routes. Replit-Commit-Author: Agent Replit-Commit-Session-Id: dec54137-d5a2-4406-8ad4-5f2f9fb110bf Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/56f97713-69fd-41d1-b933-ff4440458da0.jpg
This commit is contained in:
1 parent
0db1bffa94
commit
f828278efa
3 files changed
+116
-1
No files matched your search
@@ -3,11 +3,15 @@ import { queryClient } from "./lib/queryClient";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
import { useSessionTimeout } from "@/hooks/useSessionTimeout";
|
||||
import Login from "@/pages/Login";
|
||||
import Dashboard from "@/pages/Dashboard";
|
||||
|
||||
function AppContent() {
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
|
||||
// Initialize session timeout management
|
||||
useSessionTimeout();
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import { useEffect, useRef, useCallback } from 'react';
|
||||
import { useAuth } from './useAuth';
|
||||
|
||||
const SESSION_TIMEOUT_MS = 15 * 60 * 1000; // 15 minutes
|
||||
const WARNING_TIME_MS = 2 * 60 * 1000; // 2 minutes before timeout
|
||||
|
||||
export function useSessionTimeout() {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const warningTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const lastActivityRef = useRef<number>(Date.now());
|
||||
|
||||
const logout = useCallback(() => {
|
||||
// Redirect to logout endpoint which will handle the logout process
|
||||
window.location.href = '/api/auth/logout';
|
||||
}, []);
|
||||
|
||||
const showWarning = useCallback(() => {
|
||||
// Show a warning that session will expire soon
|
||||
const remainingTime = Math.ceil((SESSION_TIMEOUT_MS - (Date.now() - lastActivityRef.current)) / 1000 / 60);
|
||||
if (confirm(`Votre session va expirer dans ${remainingTime} minute(s). Voulez-vous rester connecté ?`)) {
|
||||
// User wants to stay logged in, reset the timer
|
||||
resetTimer();
|
||||
} else {
|
||||
// User chose to logout or didn't respond
|
||||
logout();
|
||||
}
|
||||
}, [logout]);
|
||||
|
||||
const resetTimer = useCallback(() => {
|
||||
if (!isAuthenticated) return;
|
||||
|
||||
lastActivityRef.current = Date.now();
|
||||
|
||||
// Clear existing timeouts
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
if (warningTimeoutRef.current) {
|
||||
clearTimeout(warningTimeoutRef.current);
|
||||
}
|
||||
|
||||
// Set warning timeout (2 minutes before expiration)
|
||||
warningTimeoutRef.current = setTimeout(showWarning, SESSION_TIMEOUT_MS - WARNING_TIME_MS);
|
||||
|
||||
// Set logout timeout
|
||||
timeoutRef.current = setTimeout(logout, SESSION_TIMEOUT_MS);
|
||||
}, [isAuthenticated, logout, showWarning]);
|
||||
|
||||
const handleActivity = useCallback(() => {
|
||||
resetTimer();
|
||||
}, [resetTimer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) {
|
||||
// Clear timeouts if user is not authenticated
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
if (warningTimeoutRef.current) {
|
||||
clearTimeout(warningTimeoutRef.current);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the timer when component mounts or user becomes authenticated
|
||||
resetTimer();
|
||||
|
||||
// Activity events to monitor
|
||||
const events = [
|
||||
'mousedown',
|
||||
'mousemove',
|
||||
'keypress',
|
||||
'scroll',
|
||||
'touchstart',
|
||||
'click'
|
||||
];
|
||||
|
||||
// Add event listeners for user activity
|
||||
events.forEach(event => {
|
||||
document.addEventListener(event, handleActivity, true);
|
||||
});
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
if (warningTimeoutRef.current) {
|
||||
clearTimeout(warningTimeoutRef.current);
|
||||
}
|
||||
events.forEach(event => {
|
||||
document.removeEventListener(event, handleActivity, true);
|
||||
});
|
||||
};
|
||||
}, [isAuthenticated, handleActivity, resetTimer]);
|
||||
|
||||
return {
|
||||
resetTimer,
|
||||
timeRemaining: () => Math.max(0, SESSION_TIMEOUT_MS - (Date.now() - lastActivityRef.current))
|
||||
};
|
||||
}
|
||||
+10
-1
@@ -61,7 +61,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
saveUninitialized: false,
|
||||
cookie: {
|
||||
secure: false, // Set to true in production with HTTPS
|
||||
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
||||
maxAge: 15 * 60 * 1000 // 15 minutes
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -96,6 +96,15 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/auth/logout', (req, res) => {
|
||||
req.session.destroy((err) => {
|
||||
if (err) {
|
||||
console.error('Logout error:', err);
|
||||
}
|
||||
res.redirect('/');
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/auth/logout', (req, res) => {
|
||||
req.session.destroy((err) => {
|
||||
if (err) {
|
||||
|
||||
Reference in new issue
Block a user