diff --git a/package-lock.json b/package-lock.json index ff3550f..d26a5e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "bcryptjs": "^2.4.3", + "cookie-parser": "^1.4.6", "dotenv": "^16.1.4", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", @@ -18,6 +19,7 @@ }, "devDependencies": { "@types/bcryptjs": "^2.4.2", + "@types/cookie-parser": "^1.4.3", "@types/express": "^4.17.17", "@types/jsonwebtoken": "^9.0.2" } @@ -47,6 +49,15 @@ "@types/node": "*" } }, + "node_modules/@types/cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -242,6 +253,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/package.json b/package.json index 434a22d..b995284 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "bcryptjs": "^2.4.3", + "cookie-parser": "^1.4.6", "dotenv": "^16.1.4", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", @@ -18,6 +19,7 @@ }, "devDependencies": { "@types/bcryptjs": "^2.4.2", + "@types/cookie-parser": "^1.4.3", "@types/express": "^4.17.17", "@types/jsonwebtoken": "^9.0.2" } diff --git a/src/controllers/UserController.ts b/src/controllers/UserController.ts index 60bb878..ef1614f 100644 --- a/src/controllers/UserController.ts +++ b/src/controllers/UserController.ts @@ -1,7 +1,10 @@ -import { Request, Response } from 'express'; +import express, { Request, Response } from 'express'; import bcrypt from 'bcryptjs'; import jwt from 'jsonwebtoken'; import { User, IUser } from '../models/User'; +import { clearJwtCookie, setJwtCookie } from '../middlewares/checkAuth'; + +const app = express(); export async function createUser(req: Request, res: Response) { try { @@ -33,18 +36,35 @@ export async function login(req: Request, res: Response) { } // Compare the provided password with the stored password - const isPasswordValid = await bcrypt.compare(password, user.password); - if (!isPasswordValid) { + const isPasswordCorrect = await bcrypt.compare(password, user.password); + if (!isPasswordCorrect) { return res.status(401).json({ error: 'Invalid email or password' }); } + const payload = { + userId: user._id + } // Generate a JWT - const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET as string); + const token = jwt.sign(payload, process.env.JWT_SECRET as string, { expiresIn: '1d' }); + + setJwtCookie(res, token); // Send the JWT as the response - res.json({ token }); + res.status(200).json({ + username: user.firstName + }); } catch (error) { console.error('Error during login:', error); res.status(500).json({ error: 'An error occurred during login' }); } +} + +export async function logout(req: Request, res: Response) { + try { + clearJwtCookie(res); + res.status(200).json({ message: 'Logout successful' }); + } catch (error) { + console.error('Error during logout:', error); + res.status(500).json({ error: 'An error occurred during logout' }); + } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 0766796..cd07542 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,9 @@ import express from 'express'; import mongoose from 'mongoose'; +import cookieParser from 'cookie-parser'; import userRouter from './routes/user'; -import ProductrRouter from './routes/product'; - -import { authenticateToken } from './middlewares/authMiddleware'; +import productRouter from './routes/product'; const env = require('dotenv').config().parsed; @@ -12,7 +11,7 @@ const app = express(); const PORT = 3000; app.use(express.json()); -app.use(authenticateToken); +app.use(cookieParser()) // Connect to MongoDB using Mongoose @@ -28,7 +27,7 @@ db.once('open', () => { // Routes app.use('/users', userRouter); -app.use('/products', ProductrRouter); +app.use('/products', productRouter); // Start server app.listen(PORT, () => { diff --git a/src/middlewares/authMiddleware.ts b/src/middlewares/authMiddleware.ts deleted file mode 100644 index dfa7e41..0000000 --- a/src/middlewares/authMiddleware.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Request, Response, NextFunction } from 'express'; -import jwt, { JwtPayload } from 'jsonwebtoken'; - -interface AuthenticatedRequest extends Request { - user?: JwtPayload | string; -} - -const exceptionRoutes: string[] = ['/users/login', '/users']; - -// Middleware function to authenticate requests -export function authenticateToken(req: AuthenticatedRequest, res: Response, next: NextFunction) { - const authHeader = req.headers['authorization']; - const token = authHeader && authHeader.split(' ')[1]; - - if(token) { - console.log('token', token); - } - - if (!token && exceptionRoutes.includes(req.route)) { - return res.sendStatus(401); // Unauthorized - } - - if (!exceptionRoutes.includes(req.route)) { - // Skip authentication for exception routes - return next(); - } - - jwt.verify(token as string, process.env.JWT_SECRET as string, (err, user) => { - if (err) { - return res.sendStatus(403); // Forbidden - } - - // Store the authenticated user in the request object - req.user = user as JwtPayload | string; - next(); - }); -} diff --git a/src/middlewares/checkAuth.ts b/src/middlewares/checkAuth.ts new file mode 100644 index 0000000..927e42b --- /dev/null +++ b/src/middlewares/checkAuth.ts @@ -0,0 +1,34 @@ +import express, { Request, Response, NextFunction } from 'express'; +import jwt, { JwtPayload } from 'jsonwebtoken'; +import cookieParser from 'cookie-parser'; + +interface AuthenticatedRequest extends Request { + userId?: string; +} + +// Middleware function to authenticate requests +export function authenticateToken(req: AuthenticatedRequest, res: Response, next: NextFunction) { + + const token = req.cookies.access_token; + if (!token) { + return res.status(401).json({ error: 'Unauthorized' }); + } + + const user_id = jwt.verify(token, process.env.JWT_SECRET as string, (err, decoded) => { + if (err) { + return res.status(401).json({ error: 'In Valid Token' }); + } + req.userId = decoded.userId; + next(); + }); +} + +// Set JWT as cookie in the response +export function setJwtCookie(res: Response, token: string) { + res.cookie('access_token', token, { httpOnly: true }); +} + +// Clear JWT cookie in the response +export function clearJwtCookie(res: Response) { + res.clearCookie('access_token'); +} diff --git a/src/routes/product.ts b/src/routes/product.ts index 2074475..20353c6 100644 --- a/src/routes/product.ts +++ b/src/routes/product.ts @@ -1,9 +1,10 @@ import express from 'express'; +import { authenticateToken } from '../middlewares/checkAuth'; -const ProductrRouter = express.Router(); +const productRouter = express.Router(); -ProductrRouter.post('/', (req, res) => { +productRouter.post('/', authenticateToken, (req, res) => { res.send('Create product'); }) -export default ProductrRouter; \ No newline at end of file +export default productRouter; \ No newline at end of file diff --git a/src/routes/user.ts b/src/routes/user.ts index de21658..729f56b 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -1,9 +1,10 @@ import express from 'express'; -import { createUser, login } from '../controllers/UserController'; +import { createUser, login, logout } from '../controllers/UserController'; const userRouter = express.Router(); userRouter.post('/', createUser); userRouter.post('/login', login); +userRouter.post('/logout', logout); export default userRouter; \ No newline at end of file