Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(backend): resolve issues in auth API endpoints, JWT strategy, and MongoDB connection #873

Merged
38 changes: 30 additions & 8 deletions backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,42 @@ const authRouter = require('./router/authRoute.js');
const databaseconnect = require('./config/databaseConfig.js');
const cookieParser = require('cookie-parser');
const cors = require('cors');
const csrf = require('csurf');
const rateLimit = require('express-rate-limit');

// connect to db
// Initialize CSRF Protection
const csrfProtect = csrf({ cookie: true });

// Define a rate limiter
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.',
});

// Connect to DB
databaseconnect();

app.use(express.json()); // Built-in middleware
app.use(cookieParser()); // Third-party middleware
// Middleware
app.use(express.json());
app.use(cookieParser());
app.use(cors({ origin: [process.env.CLIENT_URL], credentials: true }));

app.use(cors({ origin: [process.env.CLIENT_URL], credentials: true })); //Third-party middleware
// Expose CSRF token to client
app.get('/csrf-token', csrfProtect, (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});

// Auth router
app.use('/auth', authRouter);
// Auth routes
app.use('/api/auth', csrfProtect, limiter, authRouter);

app.use('/', (req, res) => {
res.status(200).json({ data: 'JWTauth server ;)' });
// Global error handler
app.use((err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN') {
res.status(403).json({ error: 'Invalid CSRF token' });
} else {
res.status(500).json({ error: 'Something went wrong' });
}
});

module.exports = app;
5 changes: 0 additions & 5 deletions backend/backendcode.ev

This file was deleted.

82 changes: 48 additions & 34 deletions backend/controller/authController.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const userModel = require("../model/userSchema.js");
const bcrypt = require("bcrypt");
const userModel = require('../model/userSchema.js');
const bcrypt = require('bcrypt');

const emailValidator = require("email-validator");
const emailValidator = require('email-validator');

/******************************************************
* @SIGNUP
Expand All @@ -14,12 +14,12 @@ const emailValidator = require("email-validator");

const signUp = async (req, res, next) => {
const { name, email, password, confirmPassword } = req.body;
console.log(name , email,password,confirmPassword)
// console.log(name, email, password, confirmPassword);
/// every field is required
if (!name || !email || !password || !confirmPassword) {
return res.status(400).json({
success: false,
message: "Every field is required"
message: 'Every field is required',
});
}

Expand All @@ -28,7 +28,7 @@ console.log(name , email,password,confirmPassword)
if (!validEmail) {
return res.status(400).json({
success: false,
message: "Please provide a valid email address 📩"
message: 'Please provide a valid email address 📩',
});
}

Expand All @@ -37,7 +37,7 @@ console.log(name , email,password,confirmPassword)
if (password !== confirmPassword) {
return res.status(400).json({
success: false,
message: "password and confirm Password does not match ❌"
message: 'password and confirm Password does not match ❌',
});
}

Expand All @@ -48,19 +48,20 @@ console.log(name , email,password,confirmPassword)
const result = await userInfo.save();
return res.status(200).json({
success: true,
data: result
message: 'Registered successfully',
data: result,
});
} catch (error) {
/// send the message of the email is not unique.
if (error.code === 11000) {
return res.status(400).json({
success: false,
message: `Account already exist with the provided email ${email} 😒`
message: `Account already exist with the provided email ${email} 😒`,
});
}

return res.status(400).json({
message: error.message
message: error.message,
});
}
};
Expand All @@ -76,30 +77,30 @@ console.log(name , email,password,confirmPassword)

const signIn = async (req, res, next) => {
const { email, password } = req.body;
console.log(email,password)
// console.log(email,password)

// send response with error message if email or password is missing
if (!email || !password) {
return res.status(400).json({
success: false,
message: "email and password are required"
message: 'email and password are required',
});
}

try {
// check user exist or not
const user = await userModel
.findOne({
email
email,
})
.select("+password");
.select('+password');

// If user is null or the password is incorrect return response with error message
if (!user || !(await bcrypt.compare(password, user.password))) {
// bcrypt.compare returns boolean value
return res.status(400).json({
success: false,
message: "invalid credentials"
message: 'invalid credentials',
});
}

Expand All @@ -108,25 +109,26 @@ const signIn = async (req, res, next) => {
user.password = undefined;

const cookieOption = {
secure:true,
secure: true,
maxAge: 24 * 60 * 60 * 1000, //24hr
httpOnly: true // not able to modify the cookie in client side
httpOnly: true, // not able to modify the cookie in client side
};

res.cookie("token", token, cookieOption);
res.cookie('token', token, cookieOption);
res.status(200).json({
success: true,
data: user
message: 'Login successful',
data: user,
token,
});
} catch (error) {
return res.status(400).json({
success: false,
message: error.message
message: error.message,
});
}
};


/******************************************************
* @LOGOUT
* @route /api/auth/logout
Expand All @@ -139,19 +141,22 @@ const logout = async (req, res, next) => {
try {
const cookieOption = {
expires: new Date(Date.now()), // current expiry date
httpOnly: true // not able to modify the cookie in client side
httpOnly: true, // cookie cannot be modified in client-side JS
secure: process.env.NODE_ENV === 'production', // secure cookie if in production
sameSite: 'None', // allows cross-site cookie sharing if needed
};

// return response with cookie without token
res.cookie("token", null, cookieOption);
res.status(200).json({
// Remove the token from the cookie by setting it to null
res.cookie('token', null, cookieOption);

return res.status(200).json({
success: true,
message: "Logged Out"
message: 'Logged out successfully',
});
} catch (error) {
res.stats(400).json({
res.status(400).json({
success: false,
message: error.message
message: error.message,
});
}
};
Expand All @@ -165,26 +170,35 @@ const logout = async (req, res, next) => {
******************************************************/

const getUser = async (req, res, next) => {
const userId = req.user.id;
try {
// Assuming that `req.user.id` has been set in the jwtAuth middleware
const userId = req.user.id;

// Find the user by ID from the database (ensure you're using the correct model)
const user = await userModel.findById(userId);

if (!user) {
return res.status(404).json({
success: false,
message: 'User not found',
});
}

return res.status(200).json({
success: true,
data: user
data: user,
});
} catch (error) {
return res.status(400).json({
success: false,
message: error.message
message: error.message,
});
}
};

module.exports = {
signUp,
signIn,

getUser,

logout
logout,
};
27 changes: 17 additions & 10 deletions backend/middleware/jwtAuth.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
const JWT = require("jsonwebtoken");
const JWT = require('jsonwebtoken');

// router level middleware function
// Middleware to check for a valid JWT token
const jwtAuth = (req, res, next) => {

// get cookie token(jwt token generated using json.sign()) form the request
const token = ( req.cookies?.token) || null;
// Check if the token is in the cookies or the Authorization header
const token = req.cookies?.token || req.headers?.authorization?.split(' ')[1]; // Bearer <token>

// return response if there is no token(jwt token attached with cookie)
if (!token) {
return res.status(400).json({ success: false, message: "NOT authorized" });
return res.status(400).json({
success: false,
message: 'Not authorized, no token provided',
});
}

// verify the token
try {
// Verify the token using the secret key
const payload = JWT.verify(token, process.env.SECRET);

// Attach the payload data to the request object (i.e., user data)
req.user = { id: payload.id, email: payload.email };

next();
} catch (error) {
return res.status(400).json({ success: false, message: error.message });
return res.status(400).json({
success: false,
message: 'Token verification failed: ' + error.message,
});
}
next();
};

module.exports = jwtAuth;
2 changes: 2 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
"bcrypt": "^5.1.1",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"csurf": "^1.11.0",
"dotenv": "^16.4.5",
"email-validator": "^2.0.4",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.9.3",
"nodemon": "^3.1.5"
Expand Down
18 changes: 8 additions & 10 deletions backend/router/authRoute.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
const express = require("express");
const express = require('express');
const authRouter = express.Router();
const jwtAuth = require("../middleware/jwtAuth.js");
const jwtAuth = require('../middleware/jwtAuth.js');

const {
signUp,
signIn,
forgotPassword,
resetPassword,
getUser,
logout
} = require("../controller/authController.js");
logout,
} = require('../controller/authController.js');

authRouter.post("/signup", signUp);
authRouter.post("/signin", signIn);


authRouter.get("/user", jwtAuth, getUser);
authRouter.get("/logout", jwtAuth, logout);
authRouter.post('/signup', signUp);
authRouter.post('/signin', signIn);
authRouter.post('/logout', jwtAuth, logout);
Fixed Show fixed Hide fixed
authRouter.get('/user', jwtAuth, getUser);
Fixed Show fixed Hide fixed

Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
module.exports = authRouter;
Loading