File size: 2,689 Bytes
4a2c34e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 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 };
|