How to create a login system with Node.js and Express

How to Create a Login System with Node.js and Express

Creating a login system is a fundamental skill for any web developer. In this guide, we'll walk through the process of building a secure login system using Node.js and Express. This tutorial will cover everything from setting up your environment to implementing user authentication and error handling.

What is Node.js and Express?

Node.js is a JavaScript runtime built on Chrome's V8 engine that allows developers to execute JavaScript on the server side. It’s widely used for building scalable network applications due to its non-blocking, event-driven architecture.

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. It simplifies the development of server-side applications and APIs.

Use Cases for a Login System

A login system is essential for:

  • User Authentication: Ensure that only authorized users access certain resources.
  • Personalization: Customize user experience based on user profiles.
  • Data Security: Protect sensitive information from unauthorized access.

Prerequisites

Before we start coding, ensure you have the following installed:

  • Node.js: Download and install from Node.js official website.
  • npm: Node package manager, comes with Node.js.
  • A code editor (like Visual Studio Code).
  • Basic knowledge of JavaScript and Express.

Step 1: Setting Up Your Project

Create a new directory for your project and navigate into it using your terminal:

mkdir login-system
cd login-system

Initialize a new Node.js project:

npm init -y

Install necessary packages:

npm install express mongoose bcryptjs express-session connect-mongo dotenv
  • express: For creating the server.
  • mongoose: For interacting with MongoDB.
  • bcryptjs: For hashing passwords.
  • express-session: For managing user sessions.
  • connect-mongo: For storing sessions in MongoDB.
  • dotenv: For managing environment variables.

Step 2: Creating the Server

Create a file named server.js:

const express = require('express');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoStore = require('connect-mongo');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3000;

mongoose.connect(process.env.MONGODB_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
}).then(() => console.log("MongoDB connected"))
  .catch(err => console.log(err));

app.use(express.urlencoded({ extended: true }));
app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    store: MongoStore.create({ mongoUrl: process.env.MONGODB_URI }),
}));

app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Explanation

  • We import the required packages and configure the server.
  • We connect to a MongoDB database using Mongoose.
  • We set up session management with express-session and store sessions in MongoDB.

Step 3: Creating the User Model

Create a new folder named models and a file User.js inside it:

const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

const userSchema = new mongoose.Schema({
    username: { type: String, required: true, unique: true },
    password: { type: String, required: true },
});

userSchema.pre('save', async function(next) {
    if (!this.isModified('password')) return next();
    this.password = await bcrypt.hash(this.password, 10);
    next();
});

userSchema.methods.comparePassword = function(password) {
    return bcrypt.compare(password, this.password);
};

module.exports = mongoose.model('User', userSchema);

Explanation

  • We create a user schema with username and password fields.
  • We hash passwords before saving them to the database using bcryptjs.

Step 4: Implementing Registration and Login Routes

Create a folder named routes and a file auth.js inside it:

const express = require('express');
const User = require('../models/User');
const router = express.Router();

router.post('/register', async (req, res) => {
    try {
        const { username, password } = req.body;
        const newUser = new User({ username, password });
        await newUser.save();
        res.status(201).send('User registered successfully!');
    } catch (err) {
        res.status(400).send('Error registering user');
    }
});

router.post('/login', async (req, res) => {
    try {
        const { username, password } = req.body;
        const user = await User.findOne({ username });
        if (!user || !(await user.comparePassword(password))) {
            return res.status(401).send('Invalid credentials');
        }
        req.session.userId = user._id;
        res.send('Login successful!');
    } catch (err) {
        res.status(400).send('Error logging in');
    }
});

module.exports = router;

Explanation

  • Two routes are implemented: /register for user registration and /login for user authentication.
  • Passwords are validated, and sessions are created upon successful login.

Step 5: Integrating Routes into Your Server

In server.js, import and use the routes:

const authRoutes = require('./routes/auth');

app.use('/auth', authRoutes);

Step 6: Testing Your Login System

Run your server:

node server.js

You can test your login system using tools like Postman or Insomnia.

  • Register a user: Send a POST request to http://localhost:3000/auth/register with a JSON body: json { "username": "testuser", "password": "password123" }

  • Login: Send a POST request to http://localhost:3000/auth/login with: json { "username": "testuser", "password": "password123" }

Conclusion

Congratulations! You have successfully created a basic login system with Node.js and Express. This system can be expanded with features such as password recovery, email verification, and user roles.

By understanding the core components and flow of a login system, you can build secure, user-friendly applications. Remember to always keep security in mind, especially when handling user data. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.