import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; const AUTH_HOST = process.env.AUTH_HOST ?? 'https://account.rokojori.com'; const JWT_SECRET = process.env.JWT_SECRET ?? ''; export interface JwtUser { userId: string; email: string; roles: string[]; products: string[]; settings: Record; } declare global { namespace Express { interface Request { user?: JwtUser; } } } function extractToken( req: Request ): string | undefined { const cookie = req.cookies?.accessToken as string | undefined; if ( cookie ) return cookie; const header = req.headers.authorization; if ( header?.startsWith( 'Bearer ' ) ) return header.slice( 7 ); return undefined; } function isApiRequest( req: Request ): boolean { return req.path.startsWith( '/api/' ); } export function jwtMiddleware( req: Request, res: Response, next: NextFunction ): void { const token = extractToken( req ); if ( !token ) { next(); return; } try { req.user = jwt.verify( token, JWT_SECRET ) as JwtUser; next(); } catch ( err: unknown ) { if ( err instanceof jwt.TokenExpiredError && !isApiRequest( req ) ) { const redirect = encodeURIComponent( req.protocol + '://' + req.get( 'host' ) + req.originalUrl ); res.redirect( `${AUTH_HOST}/api/auth/refresh-session?redirect=${redirect}` ); } else { next(); } } } export function requireAuth( req: Request, res: Response, next: NextFunction ): void { if ( !req.user ) { res.status( 401 ).json( { error: 'Not authenticated' } ); return; } next(); }