Files
kitchen-agent/routes/auth.js
2025-10-23 19:02:56 -04:00

118 lines
3.6 KiB
JavaScript

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;