From b5dbcfc13a63c88bc43f8446908d31be4967a90d Mon Sep 17 00:00:00 2001 From: Gopal-001 <64918520+Gopal-001@users.noreply.github.com> Date: Fri, 29 Nov 2024 17:36:31 +0530 Subject: [PATCH] feat: validate loginId to be a valid id generated from whisper (#729) Co-authored-by: _sameer Co-authored-by: Dunsin <78784850+Dun-sin@users.noreply.github.com> --- client/src/context/AuthContext.jsx | 9 +++++---- client/src/lib/utils.js | 13 +++++++++++++ server/controllers/userController.js | 4 ++-- server/utils/helper.js | 17 +++++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/client/src/context/AuthContext.jsx b/client/src/context/AuthContext.jsx index f0c61a74..f742b37c 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, @@ -23,10 +24,10 @@ const initializeAuthState = (defaultState) => { 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..392ee168 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); + } +}; 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..dffa4f64 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; @@ -18,7 +19,23 @@ function generateObjectId() { return crypto.randomBytes(12).toString('hex'); } +const validateUserID = (req, res, next) => { + const { id } = req.body; + const userIDPattern = /^[a-z0-9]{12}$/; + + // 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.' + }); + } + + // If id is valid, proceed to the next middleware + next(); +} + module.exports = { emailValidator, generateObjectId, + validateUserID, };