From 972cf3ba45e4690a1114cd12eb66b944a9ace196 Mon Sep 17 00:00:00 2001 From: Joakim Olsson Date: Mon, 29 Dec 2025 13:14:46 +0100 Subject: [PATCH] feat(session-cleanup): implement session expiration cleanup adds a cleanup mechanism for expired sessions to prevent memory leaks by deleting sessions and challenges that exceed the defined TTL. Each session is assigned a creation timestamp, which is updated upon activity, and the cleanup process runs every minute to maintain optimal memory usage. --- app.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index bb8ff9b..b71f53b 100644 --- a/app.js +++ b/app.js @@ -29,6 +29,25 @@ const users = initialUsers(process.env.USERS_FILE || './users.json') const sessions = {} const challenges = {} +// Session TTL in milliseconds (5 minutes) +const SESSION_TTL_MS = 5 * 60 * 1000 + +// Periodically clean up old sessions to prevent memory leaks +setInterval(() => { + const now = Date.now() + let cleaned = 0 + for (const [key, session] of Object.entries(sessions)) { + if (session.createdAt && now - session.createdAt > SESSION_TTL_MS) { + delete sessions[key] + delete challenges[key] + cleaned++ + } + } + if (cleaned > 0) { + debug(`Cleaned up ${cleaned} expired sessions`) + } +}, 60000) // Run every minute + const corsOpts = (req, cb) => { cb(null, { origin: req.headers.origin }) } @@ -163,7 +182,8 @@ app.post('/code', (req, res) => { nonce: req.body.nonce, clientId: req.body.clientId, codeChallenge: req.body.codeChallenge, - customClaims: [claim] + customClaims: [claim], + createdAt: Date.now() } res.redirect( `${req.body.redirect}?code=${code}&state=${encodeURIComponent(state)}` @@ -185,7 +205,13 @@ app.get('/authorize', (req, res) => { session.nonce = nonce session.state = state session.codeChallenge = codeChallenge + session.createdAt = Date.now() // Refresh timestamp sessions[codeChallenge] = session + // Clean up old session entry if different key + if (code !== codeChallenge) { + delete sessions[code] + delete challenges[code] + } res.redirect(`${redirect}?code=${codeChallenge}&state=${state}`) return } @@ -197,6 +223,7 @@ app.get('/authorize', (req, res) => { session.nonce = nonce session.state = state session.codeChallenge = codeChallenge + session.createdAt = Date.now() // Refresh timestamp res.send(`