From 63b6a7e1e3d97dfdd455bd00a85fe0e186110470 Mon Sep 17 00:00:00 2001 From: _sameer Date: Fri, 29 Nov 2024 12:45:19 +0530 Subject: [PATCH 1/5] feat: added custom validation for loginId/userId when tried to auto login --- client/src/context/AuthContext.jsx | 10 +++++----- client/src/lib/utils.js | 13 +++++++++++++ server/controllers/userController.js | 4 ++-- server/utils/helper.js | 17 +++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/client/src/context/AuthContext.jsx b/client/src/context/AuthContext.jsx index f0c61a74..3592fec3 100644 --- a/client/src/context/AuthContext.jsx +++ b/client/src/context/AuthContext.jsx @@ -2,6 +2,7 @@ import { createContext, useContext, useMemo, useReducer } from 'react'; import PropTypes from 'prop-types'; import authReducer, { initialState } from './reducers/authReducer'; +import { validateUserID } from 'src/lib/utils'; const AuthContext = createContext({ ...initialState, @@ -22,11 +23,10 @@ const initializeAuthState = (defaultState) => { if (!persistedState) { return defaultState; } - - /** - * TODO: Validate loginId to be a valid uuid using the uuid - * library from npm - */ + if (!validateUserID(persistedState.loginId, persistedState.loginType)) { + // User is trying to hack app by manipulating localStorage + throw new Error('Invalid loginId! :('); + } if (!persistedState.loginId && persistedState.isLoggedIn === true) { // User is trying to hack app by manipulating localStorage throw new Error('Gotcha! :D'); diff --git a/client/src/lib/utils.js b/client/src/lib/utils.js index ed40abe2..d7a34407 100644 --- a/client/src/lib/utils.js +++ b/client/src/lib/utils.js @@ -46,3 +46,16 @@ export const decrypt = (encryptedText) => { return originalText; }; + +export const validateUserID = (userID, userType) => { + const userIDPattern = /^[a-z0-9]{12}$/; + const userHexIdPattern = /^[a-f0-9]{24}$/; + + if (userType === 'email') { + // user id validation for hex pattern of email login + return userHexIdPattern.test(userID); + } else { + // user id validation for anonymous login + return userIDPattern.test(userID); + } + } \ No newline at end of file diff --git a/server/controllers/userController.js b/server/controllers/userController.js index d29bc640..fa2b52bc 100644 --- a/server/controllers/userController.js +++ b/server/controllers/userController.js @@ -9,7 +9,7 @@ const storage = multer.memoryStorage(); const imageUpload = multer({ storage: storage }); const User = require('../models/UserModel'); -const { emailValidator, generateObjectId } = require('../utils/helper'); +const { emailValidator, generateObjectId, validateUserID } = require('../utils/helper'); const { isUserBlocked, blockUser } = require('../utils/lib.js'); const { @@ -169,7 +169,7 @@ const blockUserHandler = async (req, res) => { } } -UserRouter.route('/login').post(emailValidator, loginUser); +UserRouter.route('/login').post(emailValidator, validateUserID, loginUser); UserRouter.route('/profile').post( imageUpload.single('profileImage'), emailValidator, diff --git a/server/utils/helper.js b/server/utils/helper.js index bf9b84e6..fe20531d 100644 --- a/server/utils/helper.js +++ b/server/utils/helper.js @@ -18,7 +18,24 @@ function generateObjectId() { return crypto.randomBytes(12).toString('hex'); } +const validateUserID = (req, res, next) => { + const {id} = req.body; + const userIDPattern = /^[a-z0-9]{12}$/; + const userHexIdPattern = /^[a-f0-9]{24}$/; + + if(id !== undefined && (typeof id !== 'string' || (!userIDPattern.test(id) && !userHexIdPattern.test(id)))){ + //if id of type string is coming it'll be via the email validation or the anonymous validation + return res.status(NOT_ACCEPTABLE).json({ + message: 'Invalid login Id.' + }); + }else{ + // if id is not there or the id is valid move ahead + next(); + } +} + module.exports = { emailValidator, generateObjectId, + validateUserID, }; From 0a41e75503964cf974e4eb0373a48965cd4ae119 Mon Sep 17 00:00:00 2001 From: _sameer Date: Fri, 29 Nov 2024 14:04:24 +0530 Subject: [PATCH 2/5] fix: no need to add email hexId validation bcz we are not calling that case --- server/utils/helper.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/utils/helper.js b/server/utils/helper.js index fe20531d..a32275dc 100644 --- a/server/utils/helper.js +++ b/server/utils/helper.js @@ -21,10 +21,9 @@ function generateObjectId() { const validateUserID = (req, res, next) => { const {id} = req.body; const userIDPattern = /^[a-z0-9]{12}$/; - const userHexIdPattern = /^[a-f0-9]{24}$/; - if(id !== undefined && (typeof id !== 'string' || (!userIDPattern.test(id) && !userHexIdPattern.test(id)))){ - //if id of type string is coming it'll be via the email validation or the anonymous validation + if(id !== undefined && (typeof id !== 'string' || !userIDPattern.test(id))){ + //if id of type string is coming it'll be via the anonymous validation return res.status(NOT_ACCEPTABLE).json({ message: 'Invalid login Id.' }); From 527511dcbc62fcca3550652f2d63bb42676afdb3 Mon Sep 17 00:00:00 2001 From: _sameer Date: Fri, 29 Nov 2024 14:11:44 +0530 Subject: [PATCH 3/5] refactor: minor refactoring change --- client/src/lib/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/lib/utils.js b/client/src/lib/utils.js index d7a34407..f95c0559 100644 --- a/client/src/lib/utils.js +++ b/client/src/lib/utils.js @@ -58,4 +58,4 @@ export const validateUserID = (userID, userType) => { // user id validation for anonymous login return userIDPattern.test(userID); } - } \ No newline at end of file +}; \ No newline at end of file From 996a278cff7c25353b9dd6fd110e168ab5bd3bd0 Mon Sep 17 00:00:00 2001 From: _sameer Date: Fri, 29 Nov 2024 14:29:42 +0530 Subject: [PATCH 4/5] refactor: added minor import --- server/utils/helper.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/utils/helper.js b/server/utils/helper.js index a32275dc..b3142340 100644 --- a/server/utils/helper.js +++ b/server/utils/helper.js @@ -1,4 +1,5 @@ const crypto = require('crypto'); +const { NOT_ACCEPTABLE } = require('../httpStatusCodes'); // Defining separate email validation middleware const validator = require('validator').default; From 308b6065a2edc443fe79e28b8c55d7163d822298 Mon Sep 17 00:00:00 2001 From: Dunsin <78784850+Dun-sin@users.noreply.github.com> Date: Fri, 29 Nov 2024 13:00:26 +0100 Subject: [PATCH 5/5] Apply suggestions from code review --- client/src/context/AuthContext.jsx | 1 + client/src/lib/utils.js | 2 +- server/utils/helper.js | 16 ++++++++-------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/client/src/context/AuthContext.jsx b/client/src/context/AuthContext.jsx index 3592fec3..f742b37c 100644 --- a/client/src/context/AuthContext.jsx +++ b/client/src/context/AuthContext.jsx @@ -23,6 +23,7 @@ const initializeAuthState = (defaultState) => { if (!persistedState) { return defaultState; } + if (!validateUserID(persistedState.loginId, persistedState.loginType)) { // User is trying to hack app by manipulating localStorage throw new Error('Invalid loginId! :('); diff --git a/client/src/lib/utils.js b/client/src/lib/utils.js index f95c0559..392ee168 100644 --- a/client/src/lib/utils.js +++ b/client/src/lib/utils.js @@ -58,4 +58,4 @@ export const validateUserID = (userID, userType) => { // user id validation for anonymous login return userIDPattern.test(userID); } -}; \ No newline at end of file +}; diff --git a/server/utils/helper.js b/server/utils/helper.js index b3142340..dffa4f64 100644 --- a/server/utils/helper.js +++ b/server/utils/helper.js @@ -20,18 +20,18 @@ function generateObjectId() { } const validateUserID = (req, res, next) => { - const {id} = req.body; - const userIDPattern = /^[a-z0-9]{12}$/; + const { id } = req.body; + const userIDPattern = /^[a-z0-9]{12}$/; - if(id !== undefined && (typeof id !== 'string' || !userIDPattern.test(id))){ - //if id of type string is coming it'll be via the anonymous validation - return res.status(NOT_ACCEPTABLE).json({ + // If id is required and not present or invalid, reject the request + if (!id || typeof id !== 'string' || !userIDPattern.test(id)) { + return res.status(406).json({ message: 'Invalid login Id.' }); - }else{ - // if id is not there or the id is valid move ahead - next(); } + + // If id is valid, proceed to the next middleware + next(); } module.exports = {