I am following a tutorial which is titled "Building a Secure User Registration and Login API with Express.js ,MongoDB and JWT"
It uses express bcryptjs jsonwebtoken mongoose
to build a simple web server with register/login functionality.
The problem arise when I send a multitude of requests to /api/register
. Server creates many users with same credentials.
Server
// Importing required modules
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
// Creating an Express application instance
const app = express();
const PORT = 3000;
// Connect to MongoDB database
mongoose.connect('mongodb://localhost:27017/mydatabase')
.then(() => {
console.log('Connected to MongoDB');
})
.catch((error) => {
console.error('Error connecting to MongoDB:', error);
});
// Define a schema for the User collection
const userSchema = new mongoose.Schema({
username: String,
email: String,
password: String
});
// Create a User model based on the schema
const User = mongoose.model('User', userSchema);
// Middleware to parse JSON bodies
app.use(express.json());
// Route to register a new user
app.post('/api/register', async (req, res) => {
try {
// Check if the email already exists
const existingUser = await User.findOne({email: req.body.email});
if (existingUser) {
return res.status(400).json({error: 'Email already exists'});
}
// Hash the password
const hashedPassword = await bcrypt.hash(req.body.password, 10);
// Create a new user
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: hashedPassword
});
await newUser.save();
console.log(newUser)
res.status(201).json({message: 'User registered successfully'});
} catch (error) {
console.log('Internal server error')
res.status(500).json({error: 'Internal server error'});
}
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Client
(() => {
const send = () => fetch('http://127.0.0.1:3000/api/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"username": "testuser", "email": "test@example.com", "password": "testpassword"
})
}).then()
for (let i = 0; i < 10; i++) send()
})()
Output
{
username: 'testuser',
email: 'test@example.com',
password: '$2a$10$5Jo01CQ797EuMrujH49Of.OmFY4n6yIX.4VgU8FOEhXRmr.CxHnRy',
_id: new ObjectId('668cf24a08fa6ed9fbf442d5'),
__v: 0
}
...9 more users created
This is a common issue with asynchronous operations. It is like 10 people asked at the same time if there is a chair available. All 10 of them gets the save answer yes but only one of them can sit on it.
In order to solve this, you should validation to the model
const userSchema = new mongoose.Schema({
username: { type: String, unique: true },
email: { type: String, unique: true },
password: String,
});