One of the most important parts of any application is security and the way we handle authentication and authorization. This is especially true when building APIs, where we need to ensure that only authenticated and authorized users can access certain data and functionality. In this chapter, we'll explore how to build a basic REST API with NodeJS and ExpressJS, with a focus on authentication and authorization.
Authentication
Authentication is the process of verifying a user's identity. In other words, it's how we confirm that a user is who they say they are. There are several ways to do this, but one of the most common is through the use of usernames and passwords.
To implement authentication in our API, we first need to install some dependencies. We will use the 'bcrypt' package to hash user passwords and the 'jsonwebtoken' package to generate authentication tokens.
$ npm install bcrypt jsonwebtoken
With the dependencies installed, we can start implementing authentication. First, let's create a route for user registration. In this route, we will hash the user's password before storing it in the database.
const express = require('express'); const bcrypt = require('bcrypt'); const User = require('../models/User'); const router = express.Router(); router.post('/register', async (req, res) => { const hashedPassword = await bcrypt.hash(req.body.password, 10); const user = new User({ username: req.body.username, password: hashedPassword }); await user.save(); res.status(201).send({ message: 'User registered successfully' }); });
Now, let's create a route for users to login. In this route, we are going to check if the provided password matches the password stored in the database. If the password is correct, we'll generate an authentication token and send it to the user.
const jwt = require('jsonwebtoken'); router.post('/login', async (req, res) => { const user = await User.findOne({ username: req.body.username }); if (!user || !await bcrypt.compare(req.body.password, user.password)) { return res.status(401).send({ message: 'Invalid username or password' }); } const token = jwt.sign({ id: user._id }, 'your_jwt_secret'); res.send({ token }); });
Authorization
Authorization is the process of verifying that a user has permission to perform a specific action. In other words, it's how we determine what a user can and cannot do. There are several ways to do this, but one of the most common is through the use of authentication tokens.
Let's create a middleware to verify the user's authentication token. If the token is valid, we'll store the userid in the request object and call the next function. If the token is not valid, we will return a response with status 401 (Unauthorized).
const jwt = require('jsonwebtoken'); const authenticate = (req, res, next) => { const token = req.headers.authorization; if (!token) { return res.status(401).send({ message: 'No token provided' }); } jwt.verify(token, 'your_jwt_secret', (err, decoded) => { if (err) { return res.status(401).send({ message: 'Invalid token' }); } req.userId = decoded.id; next(); }); };
Now, we can use this middleware on any route that requires authentication. For example, we can create a route to get authenticated user details.
router.get('/me', authenticate, async (req, res) => { const user = await User.findById(req.userId); res.send(user); });
With that, we're done creating a basic REST API with NodeJS and ExpressJS, with authentication and authorization. Remember, security is a crucial aspect of any application and should be taken seriously from the very beginning of development.