Part 8: Implementing Authentication and Authorization in Node.js
Tags: node, webdev, javascript, learning
Published: 2024-07-17 12:09:30

Security is a critical aspect of web development, and understanding how to implement authentication and authorization is essential for any developer. In this part of our Node.js series, we will explore how to secure your application by implementing a simple authentication system. We'll use JSON Web Tokens (JWT) for authentication and middleware for authorization.

please subscribe to my [YouTube channel](https://www.youtube.com/@DevDivewithDipak?sub_confirmation=1
) to support my channel and get more web development tutorials.

#### Understanding Authentication and Authorization

- **Authentication**: The process of verifying the identity of a user. Typically, this involves checking a username and password.
- **Authorization**: The process of determining if a user has permission to perform a certain action or access certain resources.

#### Setting Up the Project

Let's start by setting up a new Express project. If you haven’t already, initialize a new project and install the necessary dependencies:

```bash
npm init -y
npm install express bcryptjs jsonwebtoken body-parser mongoose
```

#### Connecting to MongoDB

First, we need to connect our application to MongoDB. If you need a refresher on connecting to MongoDB, refer to Part 7 of this series.

**database.js**
```javascript
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/auth_demo', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useCreateIndex: true
});

const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log('Connected to MongoDB');
});

module.exports = mongoose;
```

#### Defining User Model

We need a user model to store user information, including hashed passwords.

**userModel.js**
```javascript
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') || this.isNew) {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt);
  }
  next();
});

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

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

module.exports = User;
```

#### Setting Up Express Server

Next, set up the Express server and create routes for user registration and login.

**app.js**
```javascript
const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const User = require('./userModel');
const mongoose = require('./database');

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

const JWT_SECRET = 'your_jwt_secret';

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

// User Login
app.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 username or password');
    }
    const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '1h' });
    res.send({ token });
  } catch (err) {
    res.status(400).send('Error logging in');
  }
});

// Middleware to Protect Routes
const authMiddleware = (req, res, next) => {
  const token = req.headers['authorization'];
  if (!token) {
    return res.status(401).send('Access denied. No token provided.');
  }
  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    res.status(401).send('Invalid token');
  }
};

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

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

#### Testing the Application

1. **Register a User**:
   - Send a POST request to `/register` with a JSON body containing `username` and `password`.

2. **Login a User**:
   - Send a POST request to `/login` with the same credentials.
   - If successful, you will receive a JWT token.

3. **Access a Protected Route**:
   - Send a GET request to `/protected` with the token in the `Authorization` header.

#### Conclusion

By implementing authentication and authorization, you can protect your application’s routes and ensure that only authenticated users can access certain resources. In the next part of our series, we will delve into building RESTful APIs using Express and best practices for structuring your application.

Stay tuned for more advanced Node.js development techniques!

---

*Follow me for more tutorials and tips on web development. Feel free to leave comments or questions below!*

### Follow and Subscribe:
- **Website**: [Dipak Ahirav] (https://www.dipakahirav.com)
- **Email**: dipaksahirav@gmail.com
- **YouTube**: [devDive with Dipak](https://www.youtube.com/@DevDivewithDipak?sub_confirmation=1
)
- **LinkedIn**: [Dipak Ahirav](https://www.linkedin.com/in/dipak-ahirav-606bba128)