diff --git a/login-system/dbServer.js b/login-system/dbServer.js index 036e997..39f7763 100644 --- a/login-system/dbServer.js +++ b/login-system/dbServer.js @@ -3,7 +3,7 @@ const path = require('path') const { upload, save, disp } = require(path.resolve(__dirname, '../file_upload/upload.js')); const {stk_signup,stk_signin}=require('../stakeholder/login') const {info,check} = require('../file_upload/form_db') -const { signup, signin } = require('./login'); +const { signup, signin, refreshAccessToken} = require('./login'); const rateLimiter=require('express-rate-limit') const { approve,uploadedpapers,displaydetail }= require('../stakeholder/stk_approval') const {display}=require('../backend/profile'); @@ -99,6 +99,9 @@ app.post("/login",signin) app.post("/stk_holder_signin",stk_signin) app.post('/fac_login',fac_login) //login for faculty +// refresh token +app.post("/refresh",refreshAccessToken) + // approval by stakeholder app.get('/approval',approve) diff --git a/login-system/login.js b/login-system/login.js index 0856228..2879d85 100644 --- a/login-system/login.js +++ b/login-system/login.js @@ -1,124 +1,133 @@ -const mysql = require('mysql') -const bcrypt = require('bcrypt') -const {generateAccessToken}=require('./token'); +const mysql = require('mysql'); +const bcrypt = require('bcrypt'); +const { generateAccessToken, generateRefreshToken, decodeRefreshToken } = require('./token'); const notify = require('./notification'); -const rateLimit = require('express-rate-limit') -require("dotenv").config() -const db = require('../config/mysql_connection') +const rateLimit = require('express-rate-limit'); +require("dotenv").config(); +const db = require('../config/mysql_connection'); - -// connecting database to the server +// Connecting database to the server db.getConnection((err, connection) => { if (err) throw err; - console.log("Database Connected Successfully") -}) + console.log("Database Connected Successfully"); +}); +// Validate password strength const validatePassword = (password) => { const RegexPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{7,}$/; - return RegexPassword.test(password) -} + return RegexPassword.test(password); +}; +// Rate limiting for signup const signupRateLimiter = rateLimit({ - windowMs : 60*60*1000, // 1 hr - max : 10, // max 10 attempts - message : "Too many signup attempts , please try again after an hour." -}) + windowMs: 60 * 60 * 1000, // 1 hour + max: 10, // max 10 attempts + message: "Too many signup attempts, please try again after an hour." +}); +// Rate limiting for signin const signinRateLimiter = rateLimit({ - windowMs : 60*60*1000, - max : 15, // max 15 attempts - message : "Too many login attempts, please try again after an hour." -}) + windowMs: 60 * 60 * 1000, // 1 hour + max: 15, // max 15 attempts + message: "Too many login attempts, please try again after an hour." +}); -const signup=async (req, res) => { - const username = req.body.name.trim() - const email = req.body.email.trim().toLowerCase() - const password = req.body.password.trim() +// Signup function +const signup = async (req, res) => { + const username = req.body.name.trim(); + const email = req.body.email.trim().toLowerCase(); + const password = req.body.password.trim(); - if(!validatePassword(password)){ + if (!validatePassword(password)) { return res.status(400).json({ - error : "Password Invalid ... Password must be atleast 7 character long and must contain atleast 1 uppercase & lowercase character , 1 number and 1 special character" - }) + error: "Password Invalid ... Password must be at least 7 characters long and must contain at least 1 uppercase & lowercase character, 1 number, and 1 special character." + }); } const hashpassword = await bcrypt.hash(req.body.password, 10); db.getConnection(async (err, connection) => { - if (err) throw (err) - const sqlSearch = "SELECT * FROM user_table WHERE email=? OR username=?"; - const search_query = mysql.format(sqlSearch, [email,username]) - - const sqlinsert = "INSERT INTO user_table VALUES (0,?,?,?)" - const insert_query = mysql.format(sqlinsert, [username, email, hashpassword]) + if (err) throw (err); + const sqlSearch = "SELECT * FROM user_table WHERE email=? OR username=?"; + const search_query = mysql.format(sqlSearch, [email, username]); + + const sqlInsert = "INSERT INTO user_table VALUES (0,?,?,?)"; + const insert_query = mysql.format(sqlInsert, [username, email, hashpassword]); + await connection.query(search_query, async (err, result) => { - if (err) throw (err) - console.log("search results",result.length) + if (err) throw (err); + console.log("search results", result.length); if (result.length != 0) { - connection.release() - - if(result[0].email === email){ - console.log("A User with Entered Email already exists") - res.status(404).send( - "Email Already in Use" - ) - }else if(result[0].username === username){ - console.log("A User with Entered Username already exists") - res.status(404).send( - "Username Already in Use" - ) + connection.release(); + + if (result[0].email === email) { + console.log("A User with Entered Email already exists"); + res.status(404).send("Email Already in Use"); + } else if (result[0].username === username) { + console.log("A User with Entered Username already exists"); + res.status(404).send("Username Already in Use"); } - } - else { + } else { await connection.query(insert_query, async (err, result) => { connection.release(); - if (err) throw (err) - console.log("Created a new User") - const sub='Signup-Research Nexas ' - // const content=`Account created successfully with username ${result[0].username} in Research Nexas` - // notify(req,res,result[0].email,sub,content); + if (err) throw (err); + console.log("Created a new User"); + const sub = 'Signup-Research Nexas'; + // const content = `Account created successfully with username ${result[0].username} in Research Nexas`; + // notify(req, res, result[0].email, sub, content); res.sendStatus(201); - }) + }); } - }) - }) + }); + }); } -// login backend -const signin=(req, res) => { - const email = req.body.email.trim() +// Signin function +const signin = async (req, res) => { + const email = req.body.email.trim(); const password = req.body.password.trim(); db.getConnection(async (err, connection) => { - if (err) throw (err) - const sqlSearch = "Select * from user_table where email=?" - const search_query = mysql.format(sqlSearch, [email]) + if (err) throw (err); + const sqlSearch = "SELECT * FROM user_table WHERE email=?"; + const search_query = mysql.format(sqlSearch, [email]); await connection.query(search_query, async (err, result) => { - if (err) throw (err) + if (err) throw (err); if (result.length == 0) { - console.log("User does not exist") - res.sendStatus(404) - } - else { - const hashpassword = result[0].password + console.log("User does not exist"); + return res.sendStatus(404); + } else { + const hashpassword = result[0].password; if (await bcrypt.compare(password, hashpassword)) { - console.log("Login Successful") - const token = generateAccessToken({ user: result[0].userid }); - console.log(token) - res.json({ accessToken: token }) - const sub='Log in-Research Nexas ' - // const content=`Login successfully to the account with username ${result[0].username}` - // notify(req,res,result[0].email,sub,content); - } - else { - res.status(401).send("password incorrect") + console.log("Login Successful"); + const accessToken = generateAccessToken({ user: result[0].userid }); + const refreshToken = generateRefreshToken({ user: result[0].userid }); // Generate refresh token + console.log(accessToken, refreshToken); + res.json({ accessToken, refreshToken }); // Send both tokens + } else { + res.status(401).send("Password incorrect"); } } - connection.release() - }) - }) + connection.release(); + }); + }); +} + +// Refresh token function +const refreshAccessToken = (req, res) => { + const refreshToken = req.body.refreshToken; // Assume the refresh token is sent in the request body + if (!refreshToken) return res.sendStatus(401); // Unauthorized if refresh token is not present + + const decoded = decodeRefreshToken(refreshToken); + if (!decoded) return res.sendStatus(403); // Forbidden if refresh token is invalid + + // Generate new access token + const newAccessToken = generateAccessToken({ user: decoded.user }); + res.json({ accessToken: newAccessToken }); } -// exporting signup,signin funtion -module.exports={ - signup : [signupRateLimiter,signup], - signin : [signinRateLimiter,signin] -} \ No newline at end of file +// Exporting signup, signin, refresh token, and logout functions +module.exports = { + signup: [signupRateLimiter, signup], + signin: [signinRateLimiter, signin], + refreshAccessToken, +}; diff --git a/login-system/token.js b/login-system/token.js index de5466a..269f192 100644 --- a/login-system/token.js +++ b/login-system/token.js @@ -1,55 +1,83 @@ -require("dotenv").config() -const jwt = require("jsonwebtoken") -const crypto=require('crypto'); -const ACCESS_TOKEN = process.env.ACCESS_TOKEN_SECRET - -// check for valid access token -if(!ACCESS_TOKEN){ - throw new Error("Missing ACCESS_TOKEN_SECRET in environment variables."); +require("dotenv").config(); +const jwt = require("jsonwebtoken"); +const crypto = require('crypto'); +const ACCESS_TOKEN = process.env.ACCESS_TOKEN_SECRET; +const REFRESH_TOKEN = process.env.REFRESH_TOKEN_SECRET; // Add this line + +// Check for valid secrets +if (!ACCESS_TOKEN || !REFRESH_TOKEN) { + throw new Error("Missing ACCESS_TOKEN_SECRET or REFRESH_TOKEN_SECRET in environment variables."); } -// function for generating access token -function generateAccessToken(user,expireTime = "20m") { - try{ - const token = jwt.sign(user,ACCESS_TOKEN,{expiresIn : expireTime}); - return token; - }catch(err){ + +// Function for generating access token +function generateAccessToken(user, expireTime = "20m") { + try { + const token = jwt.sign(user, ACCESS_TOKEN, { expiresIn: expireTime }); + return token; + } catch (err) { console.log({ - Message : "Error While Generating The Token", - Error : err.message - }) + Message: "Error While Generating The Access Token", + Error: err.message + }); return null; - } + } } -// function for decoding the token -function decodeAccessToken(AuthHeader){ - if(!AuthHeader){ - console.log("Authorization header is missing"); - return null; - } - - const token = AuthHeader.split(" ")[1]; - if(!token){ - console.log("Token is missing"); - return null; - } - try{ - - const decodedToken = jwt.verify(token,ACCESS_TOKEN) +// Function for generating refresh token +function generateRefreshToken(user) { + try { + const token = jwt.sign(user, REFRESH_TOKEN, { expiresIn: "7d" }); // Valid for 7 days + return token; + } catch (err) { + console.log({ + Message: "Error While Generating The Refresh Token", + Error: err.message + }); + return null; + } +} + +// Function for decoding the token +function decodeAccessToken(AuthHeader) { + if (!AuthHeader) { + console.log("Authorization header is missing"); + return null; + } + + const token = AuthHeader.split(" ")[1]; + if (!token) { + console.log("Token is missing"); + return null; + } + try { + const decodedToken = jwt.verify(token, ACCESS_TOKEN); + return decodedToken; + } catch (err) { + console.log({ + Message: "Error decoding access token:", + Error: err.message + }); + return null; + } +} + +// Function for decoding the refresh token +function decodeRefreshToken(token) { + try { + const decodedToken = jwt.verify(token, REFRESH_TOKEN); return decodedToken; - - }catch(err){ + } catch (err) { console.log({ - Message : "Error decoding access token:", - Error : err.message - }) - return null + Message: "Error decoding refresh token:", + Error: err.message + }); + return null; } } -// generating registration token for faculties +// Generating registration token for faculties function registrationToken(email) { return crypto.createHash('sha256').update(email).digest('hex'); - } +} -module.exports={ generateAccessToken, decodeAccessToken ,registrationToken} +module.exports = { generateAccessToken, decodeAccessToken, generateRefreshToken, decodeRefreshToken, registrationToken };