import { Router } from 'express'; import jwt from 'jsonwebtoken'; import { config } from '../../config'; import { redisClient } from '../../server'; const router = Router(); function signTokens(user: { id: string; email: string; orgId: string; role: string }) { const accessToken = jwt.sign(user, config.JWT_SECRET, { expiresIn: config.JWT_ACCESS_EXPIRY }); const refreshToken = jwt.sign({ id: user.id }, config.JWT_REFRESH_SECRET, { expiresIn: config.JWT_REFRESH_EXPIRY }); return { accessToken, refreshToken }; } router.post('/register', async (req, res) => { const { email, name, password, orgName } = req.body; // TODO: hash password, create org + user in DB const user = { id: 'uuid-' + Date.now(), email, orgId: 'org-' + Date.now(), role: 'admin' }; const tokens = signTokens(user); await redisClient.set(`refresh:${user.id}`, tokens.refreshToken, { EX: 7 * 24 * 60 * 60 }); res.json({ data: { user, accessToken: tokens.accessToken }, meta: { refreshToken: tokens.refreshToken } }); }); router.post('/login', async (req, res) => { const { email, password } = req.body; // TODO: verify password against DB const user = { id: 'uuid-mock', email, orgId: 'org-mock', role: 'admin' }; const tokens = signTokens(user); await redisClient.set(`refresh:${user.id}`, tokens.refreshToken, { EX: 7 * 24 * 60 * 60 }); res.json({ data: { user, accessToken: tokens.accessToken }, meta: { refreshToken: tokens.refreshToken } }); }); router.post('/refresh', async (req, res) => { const { refreshToken } = req.body; try { const payload = jwt.verify(refreshToken, config.JWT_REFRESH_SECRET) as any; const stored = await redisClient.get(`refresh:${payload.id}`); if (!stored || stored !== refreshToken) throw new Error('Invalid refresh token'); // TODO: fetch user from DB const user = { id: payload.id, email: 'mock@example.com', orgId: 'org-mock', role: 'admin' }; const tokens = signTokens(user); await redisClient.set(`refresh:${user.id}`, tokens.refreshToken, { EX: 7 * 24 * 60 * 60 }); res.json({ data: { accessToken: tokens.accessToken }, meta: { refreshToken: tokens.refreshToken } }); } catch { res.status(401).json({ error: { message: 'Invalid refresh token', code: 'UNAUTHORIZED' } }); } }); router.post('/logout', async (req, res) => { const authHeader = req.headers.authorization; if (authHeader?.startsWith('Bearer ')) { try { const token = authHeader.slice(7); const payload = jwt.verify(token, config.JWT_SECRET) as any; await redisClient.del(`refresh:${payload.id}`); } catch { /* ignore */ } } res.json({ data: { success: true } }); }); export { router as authRouter };