1- import express , { Application } from 'express' ;
1+ // import express, { Application } from 'express';
2+ // import cors from 'cors';
3+ // import morgan from 'morgan';
4+ // import bodyParser from 'body-parser';
5+ // import healthRoutes from './routes/healthRoutes';
6+
7+ // const app: Application = express();
8+
9+
10+ // // Middleware setup
11+ // app.use(cors());
12+ // app.use(morgan('dev'));
13+ // app.use(bodyParser.json());
14+ // app.use(bodyParser.urlencoded({ extended: true }));
15+
16+
17+ // // API Routes
18+ // app.use('/api/health', healthRoutes);
19+
20+ // export default app;
21+
22+ import express , { Application , Request , Response } from 'express' ;
223import cors from 'cors' ;
324import morgan from 'morgan' ;
425import bodyParser from 'body-parser' ;
526import healthRoutes from './routes/healthRoutes' ;
627
28+ // 1. Imports needed for JWT/Auth
29+ import bcrypt from "bcryptjs" ;
30+ import cookieParser from "cookie-parser" ;
31+ import { signAccessToken , signRefreshToken , verifyRefreshToken } from "./controllers/auth" ;
32+ import { authenticate , AuthRequest } from "./middleware/authMiddleware" ;
33+
734const app : Application = express ( ) ;
835
936
@@ -12,9 +39,107 @@ app.use(cors());
1239app . use ( morgan ( 'dev' ) ) ;
1340app . use ( bodyParser . json ( ) ) ;
1441app . use ( bodyParser . urlencoded ( { extended : true } ) ) ;
42+ // 2. Middleware needed for Auth
43+ app . use ( cookieParser ( ) ) ;
44+
45+
46+ // 3. User Interface and Mock Data
47+ interface User {
48+ id : string ;
49+ username : string ;
50+ passwordHash : string ;
51+ role : string ;
52+ }
53+
54+ const users : User [ ] = [
55+ { id : "1" , username : "alice" , passwordHash : bcrypt . hashSync ( "password" , 8 ) , role : "admin" } ,
56+ ] ;
57+
58+ const refreshTokens = new Map < string , string > ( )
59+
60+
61+ // 4. Authentication API Routes
62+ app . post ( "/login" , async ( req : Request , res : Response ) => {
63+ const { username, password } = req . body ;
64+ const user = users . find ( ( u ) => u . username === username ) ;
65+ if ( ! user ) return res . status ( 401 ) . json ( { error : "Invalid credentials" } ) ;
66+
67+ const match = await bcrypt . compare ( password , user . passwordHash ) ;
68+ if ( ! match ) return res . status ( 401 ) . json ( { error : "Invalid credentials" } ) ;
69+
70+ const payload = { sub : user . id , username : user . username , role : user . role } ;
71+ const accessToken = signAccessToken ( payload ) ;
72+ const refreshToken = signRefreshToken ( payload ) ;
73+
74+ refreshTokens . set ( user . id , refreshToken ) ;
75+
76+ res . cookie ( "refreshToken" , refreshToken , {
77+ httpOnly : true ,
78+ sameSite : "strict" ,
79+ secure : process . env . NODE_ENV === "production" ,
80+ maxAge : 7 * 24 * 60 * 60 * 1000 ,
81+ } ) ;
82+
83+ res . json ( { accessToken } ) ;
84+ } ) ;
85+
86+ app . post ( "/refresh" , ( req : Request , res : Response ) => {
87+ const token = req . cookies ?. refreshToken || req . body . refreshToken ;
88+
89+ if ( ! token ) {
90+ return res . status ( 401 ) . json ( { error : "Refresh token is missing" } ) ;
91+ }
92+
93+ try {
94+ const payload = verifyRefreshToken ( token ) ;
95+ const storedToken = refreshTokens . get ( payload . sub ) ;
96+
97+ if ( ! storedToken ) {
98+ return res . status ( 401 ) . json ( { error : "Session not found or already logged out" } ) ;
99+ }
100+
101+ if ( storedToken !== token ) {
102+ return res . status ( 401 ) . json ( { error : "Token used is not the latest valid token" } ) ;
103+ }
104+
105+ const cleanPayload = {
106+ sub : payload . sub ,
107+ username : payload . username ,
108+ role : payload . role
109+ } ;
110+
111+ const newAccess = signAccessToken ( cleanPayload ) ;
112+ const newRefresh = signRefreshToken ( cleanPayload ) ;
113+
114+ refreshTokens . set ( cleanPayload . sub , newRefresh ) ;
115+
116+ res . cookie ( "refreshToken" , newRefresh , {
117+ httpOnly : true ,
118+ sameSite : "strict" ,
119+ secure : process . env . NODE_ENV === "production" ,
120+ maxAge : 7 * 24 * 60 * 60 * 1000 ,
121+ } ) ;
122+
123+ res . json ( { accessToken : newAccess } ) ;
124+
125+ } catch ( error ) {
126+ console . error ( "Refresh token verification failed:" , error ) ;
127+ res . status ( 401 ) . json ( { error : "Refresh token is expired or invalid" } ) ;
128+ }
129+ } ) ;
130+
131+ app . post ( "/logout" , authenticate , ( req : AuthRequest , res : Response ) => {
132+ // req.user is guaranteed to exist by the 'authenticate' middleware
133+ refreshTokens . delete ( req . user ! . sub ) ;
134+ res . clearCookie ( "refreshToken" ) ;
135+ res . status ( 204 ) . send ( ) ;
136+ } ) ;
15137
138+ app . get ( "/protected" , authenticate , ( req : AuthRequest , res : Response ) => {
139+ res . json ( { message : "Protected route accessed" , user : req . user } ) ;
140+ } ) ;
16141
17- // API Routes
142+ // Existing API Routes
18143app . use ( '/api/health' , healthRoutes ) ;
19144
20145export default app ;
0 commit comments