How to implement authentication in a Node.js app

How to Implement Authentication in a Node.js App

Authentication is a fundamental aspect of web applications, ensuring that users can securely log in and access their data. In this article, we will explore how to implement authentication in a Node.js app. You’ll learn about definitions, use cases, and actionable insights, with clear code examples and step-by-step instructions to help you navigate the process.

What is Authentication?

Authentication is the process of verifying the identity of a user or system. It typically involves a user providing credentials—such as a username and password—that the system checks against stored data. Successful authentication allows users to access their accounts and perform actions based on their permissions.

Use Cases for Authentication

  1. User Registration and Login: Allow users to create accounts and log in to access personalized content.
  2. Secure APIs: Protect sensitive API endpoints with authentication to prevent unauthorized access.
  3. Role-Based Access Control: Implement different access levels for users based on their roles within the application.

Choosing the Right Authentication Method

There are several methods of authentication, each with its advantages:

  • Session-Based Authentication: Uses server-side sessions to keep track of logged-in users.
  • Token-Based Authentication: Uses tokens (like JSON Web Tokens) for stateless authentication, which is well-suited for APIs and mobile apps.
  • OAuth: Allows users to authenticate using third-party services (e.g., Google, Facebook).

For this guide, we’ll focus on token-based authentication using JSON Web Tokens (JWT), which is ideal for modern web applications.

Setting Up Your Node.js Environment

Before we implement authentication, let’s set up a basic Node.js application. Ensure you have Node.js and npm installed on your system.

  1. Create a new directory for your project and navigate to it:

bash mkdir node-auth-example cd node-auth-example

  1. Initialize a new Node.js project:

bash npm init -y

  1. Install necessary packages:

bash npm install express jsonwebtoken bcryptjs body-parser mongoose dotenv

  • Express: Web framework for Node.js.
  • jsonwebtoken: Library for creating and verifying JWTs.
  • bcryptjs: Library for hashing passwords.
  • body-parser: Middleware to handle incoming request bodies.
  • mongoose: ODM for MongoDB.
  • dotenv: For managing environment variables.

Creating the Application Structure

Let’s create a basic file structure:

node-auth-example/
│
├── .env
├── app.js
└── models/
    └── User.js

Setting Up the User Model

In models/User.js, we will define our User model using Mongoose:

const mongoose = require('mongoose');

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

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

Configuring the Express Server

In app.js, set up the Express server and connect to MongoDB:

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const User = require('./models/User');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
require('dotenv').config();

const app = express();
app.use(bodyParser.json());

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

User Registration Endpoint

Let’s add a route for user registration:

app.post('/register', async (req, res) => {
    const { username, password } = req.body;

    // Hash the password
    const hashedPassword = await bcrypt.hash(password, 10);

    const newUser = new User({ username, password: hashedPassword });

    try {
        await newUser.save();
        res.status(201).send('User registered successfully');
    } catch (error) {
        res.status(400).send('Error registering user');
    }
});

User Login Endpoint

Next, add a login route that generates a JWT token:

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

    const user = await User.findOne({ username });
    if (!user) return res.status(400).send('User not found');

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) return res.status(400).send('Invalid credentials');

    const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
    res.json({ token });
});

Middleware for Protected Routes

To protect certain routes, let’s create a middleware function:

const authenticateToken = (req, res, next) => {
    const token = req.headers['authorization'] && req.headers['authorization'].split(' ')[1];
    if (!token) return res.sendStatus(401);

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
        if (err) return res.sendStatus(403);
        req.user = user;
        next();
    });
};

Creating a Protected Route

Now, let’s add a protected route that only authenticated users can access:

app.get('/protected', authenticateToken, (req, res) => {
    res.send('This is a protected route!');
});

Running Your Application

To run your application, make sure to set your environment variables in the .env file:

MONGO_URI=mongodb://localhost:27017/node-auth-example
JWT_SECRET=your_jwt_secret

Now, start your server:

node app.js

You can test your registration and login endpoints using tools like Postman or curl.

Conclusion

Implementing authentication in a Node.js application is a critical step towards securing user data and ensuring a seamless user experience. By utilizing JWT for token-based authentication, you can easily manage user sessions and protect sensitive routes.

Key Takeaways

  • Use bcrypt to securely hash passwords.
  • Implement JWT for stateless authentication.
  • Protect sensitive routes with middleware.

With this guide, you should have a solid foundation for implementing authentication in your Node.js app. Continue to expand upon this by adding features like password recovery, email verification, and role-based access controls to enhance your application’s security and functionality. 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.