Introduction

Welcome to our lesson on User Authentication! Today, we'll learn how to add user authentication to our To-Do List application using Express.js and MongoDB. This is important because it ensures that only registered users can access their personalized task lists, making our app more secure and user-friendly.

What You'll Learn

In this lesson, you'll learn:

  • What user authentication is and why it's important.
  • How to create a user model in MongoDB.
  • How to handle user registration and login using Express.js.
  • How to hash passwords to enhance security.

Now that we know what we're about to learn, let's understand user authentication in more detail.

Introduction to User Authentication

User authentication is the process of verifying the identity of a user when they access an application. It's like checking someone's ID before allowing them to enter a building.

Imagine your To-Do List app is like a personal diary. You want to make sure that only you can see and add tasks to it. That's where user authentication comes in — it makes sure that only registered users with the correct credentials can access their data.

Step 1: Setting Up the Environment

First, let's set up our environment to handle user authentication. We need to:

  1. Install necessary libraries (Express.js, MongoDB, bcrypt).
  2. Connect to the MongoDB database.
  3. Set up an Express.js server.

Ensure you have Node.js and MongoDB installed on your machine.

To install the necessary libraries, run the following commands:

npm install express mongoose bcrypt

Here's the code to set up the environment:

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

const app = express();
const PORT = 3000;

// Connect to MongoDB
mongoose.connect('mongodb://127.0.0.1:27017/todo-app', {
  useNewUrlParser: true,
  useUnifiedTopology: true
}).catch(error => console.log('Error connecting to MongoDB:', error));

app.use(express.json()); // Replace bodyParser with express built-in middleware

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

Potential error: If there is an issue with the database connection, an error message will be logged.

Step 2: Creating a User Model

Next, we’ll create a User model in MongoDB. This model will define the structure of our user data.

// Define a schema and model for Users
const userSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  password: { type: String, required: true }
});

const User = mongoose.model('User', userSchema);

Here, we define a userSchema with username and password fields. Both fields are required, and username must be unique. This ensures that each user has a unique identifier and a secure password.

Step 3: Registering a New User
Step 4: Logging In a User

Finally, we’ll add functionality for users to log in. We'll create an endpoint /login that will check if the provided credentials are correct.

When a user tries to log in, we need to:

  1. Find the user by their username.
  2. Compare the provided password with the stored hashed password.

Here’s the code for the login endpoint:

// Route to handle user login
app.post('/login', async (req, res) => {
  const { username, password } = req.body;

  try {
    const user = await User.findOne({ username });
    if (!user) return res.status(401).json({ message: 'Invalid credentials' });

    // Compare the hashed password with the stored hashed password
    const isPasswordCorrect = await bcrypt.compare(password, user.password);
    if (!isPasswordCorrect) return res.status(401).json({ message: 'Invalid credentials' });

    res.json({ message: 'Login successful' });
  } catch (error) {
    // The try-catch block is used for handling potential errors that might occur during login.
    res.status(500).json({ message: 'Failed to log in', error: error.message });
  }
});

In this code, we look for the user in our database by their username. If the user exists, we compare the provided password with the stored hashed password using bcrypt. If they match, the user is successfully logged in; otherwise, we return an error message.

Please note that the try-catch block is specifically used to handle potential errors that might occur during the database query or password comparison, such as when the database connection is lost or the bcrypt.compare function fails.

Conclusion

In this lesson, we learned what user authentication is and why it’s important. We set up our environment, created a user model, and added functionality for user registration and login. We also learned about password hashing using bcrypt to enhance security.

Get ready to dive into the exercises and build your skills!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal