const express = require('express'); const cookieParser = require('cookie-parser'); const path = require('path'); const app = express(); const PORT = process.env.PORT || 3000; const GATEKEEPER_PASSWORD = process.env.GATEKEEPER_PASSWORD || 'klz2026'; const AUTH_COOKIE_NAME = 'klz_gatekeeper_session'; app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); app.use(express.urlencoded({ extended: true })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); // ForwardAuth check endpoint app.get('/verify', (req, res) => { const session = req.cookies[AUTH_COOKIE_NAME]; if (session === GATEKEEPER_PASSWORD) { return res.status(200).send('OK'); } // Traefik will use this to redirect if requested const originalUrl = req.headers['x-forwarded-uri'] || '/'; const host = req.headers['x-forwarded-host'] || ''; const proto = req.headers['x-forwarded-proto'] || 'https'; // Redirect to login res.redirect(`${proto}://${host}/gatekeeper/login?redirect=${encodeURIComponent(originalUrl)}`); }); // Login page app.get('/gatekeeper/login', (req, res) => { res.render('login', { error: req.query.error ? 'Invalid password' : null, redirect: req.query.redirect || '/' }); }); // Handle login app.post('/gatekeeper/login', (req, res) => { const { password, redirect } = req.body; if (password === GATEKEEPER_PASSWORD) { res.cookie(AUTH_COOKIE_NAME, GATEKEEPER_PASSWORD, { httpOnly: true, secure: true, path: '/', maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days }); return res.redirect(redirect || '/'); } res.redirect(`/gatekeeper/login?error=1&redirect=${encodeURIComponent(redirect || '/')}`); }); app.listen(PORT, () => { console.log(`Gatekeeper listening on port ${PORT}`); });