const config = require('../config'); const apiClient = require('../api-client'); async function authRoutes(fastify, options) { // Root route - redirect based on signed session cookie validity fastify.get('/', async (req, reply) => { try { const raw = req.cookies && req.cookies.kitchen_session; if (raw) { const { valid, value } = req.unsignCookie(raw || ''); if (valid) { const token = config.get('authToken'); const expiry = config.get('tokenExpiry'); if (token && !apiClient.isTokenExpired(expiry) && value === token) { return reply.redirect('/dashboard'); } } } } catch (_) {} return reply.redirect('/login'); }); // Login page fastify.get('/login', async (req, reply) => { try { const raw = req.cookies && req.cookies.kitchen_session; if (raw) { const { valid, value } = req.unsignCookie(raw || ''); if (valid) { const token = config.get('authToken'); const expiry = config.get('tokenExpiry'); if (token && !apiClient.isTokenExpired(expiry) && value === token) { return reply.redirect('/dashboard'); } } } } catch (_) {} return reply.view('login', { error: req.query.error || null, recaptchaSiteKey: process.env.RECAPTCHA_SITE_KEY || '' }); }); // Login handler fastify.post('/auth/login', async (req, reply) => { const { login, password, 'g-recaptcha-response': recaptchaToken } = req.body; // Validate inputs if (!login || !password) { return reply.view('login', { error: 'Please provide email and password', recaptchaSiteKey: process.env.RECAPTCHA_SITE_KEY || '' }); } if (!recaptchaToken) { return reply.view('login', { error: 'reCAPTCHA verification required', recaptchaSiteKey: process.env.RECAPTCHA_SITE_KEY || '' }); } try { // Call API to authenticate const result = await apiClient.login(login, password, recaptchaToken); if (result.error) { return reply.view('login', { error: result.message || 'Login failed', recaptchaSiteKey: process.env.RECAPTCHA_SITE_KEY || '' }); } // Store auth token and expiration config.set('authToken', result.token); config.set('tokenExpiry', result.expirationDate); config.set('userEmail', login); // Set signed cookie for session; secure only on HTTPS const isHttps = (req.protocol === 'https') || ((req.headers['x-forwarded-proto'] || '').toString().toLowerCase() === 'https'); reply.setCookie('kitchen_session', result.token, { signed: true, httpOnly: true, secure: isHttps, sameSite: 'strict', maxAge: 30 * 24 * 60 * 60, path: '/' }); return reply.redirect('/dashboard'); } catch (error) { console.error('Login error:', error.message); return reply.view('login', { error: 'An error occurred during login. Please try again.', recaptchaSiteKey: process.env.RECAPTCHA_SITE_KEY || '' }); } }); // Logout handler fastify.post('/auth/logout', async (req, reply) => { // Allow multiple sessions: only clear the browser cookie reply.clearCookie('kitchen_session'); return reply.redirect('/login'); }); fastify.get('/auth/logout', async (req, reply) => { // Allow multiple sessions: only clear the browser cookie reply.clearCookie('kitchen_session'); return reply.redirect('/login'); }); } module.exports = authRoutes;