mirror of
https://github.com/R0m1k3/Regisflow.git
synced 2026-10-23 15:18:17 +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 { Toaster } from "@/components/ui/toaster";
|
||||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||||
import { useAuth } from "@/hooks/useAuth";
|
import { useAuth } from "@/hooks/useAuth";
|
||||||
|
import { useSessionTimeout } from "@/hooks/useSessionTimeout";
|
||||||
import Login from "@/pages/Login";
|
import Login from "@/pages/Login";
|
||||||
import Dashboard from "@/pages/Dashboard";
|
import Dashboard from "@/pages/Dashboard";
|
||||||
|
|
||||||
function AppContent() {
|
function AppContent() {
|
||||||
const { isAuthenticated, isLoading } = useAuth();
|
const { isAuthenticated, isLoading } = useAuth();
|
||||||
|
|
||||||
|
// Initialize session timeout management
|
||||||
|
useSessionTimeout();
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
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,
|
saveUninitialized: false,
|
||||||
cookie: {
|
cookie: {
|
||||||
secure: false, // Set to true in production with HTTPS
|
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) => {
|
app.post('/api/auth/logout', (req, res) => {
|
||||||
req.session.destroy((err) => {
|
req.session.destroy((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
Reference in new issue
Block a user