Create an Authentication System with Node JS and MongoDB Part 2

5 months ago admin Nodejs

In the second part of this tutorial, we will create the routes, add the middleware and finally register and log in the users.


Create the JWT Secret

Inside the file 'config.js' let's add the JWT Secret we will use it later when creating the token.

                                                        
                                                                                                                        
export const JWT_SECRET = "ABCDEFJHIJKLMNOPQRSTUVWXYZ";

Create the middleware

Next, let's create a new folder 'middleware' Inside add a new file 'authMiddleware.js' Inside add the code below:

                                                            
                                                                                                                                
import jwt from "jsonwebtoken";
import { JWT_SECRET } from '../config.js';

export const auth = async (req, res, next) => {
    try {
        // get the token from the header
        const token = await req.headers.authorization.split(" ")[1];

        //check if the tokens matches 
        const decodedToken = await jwt.verify(token, JWT_SECRET);

        // retrieve the logged in user
        const user = await decodedToken;

        // pass the user to the route
        req.user = user;

        // move to the next
        next();
        
    } catch (error) {
        return res.status(401).json({
            error: "Unauthenticated",
        });
    }
};

Create the route

Inside the backend folder create a new folder 'routes' Inside create a new file 'userRouter.js' and add the code below inside.

                                                            
                                                                                                                                
import express from 'express';
import User from '../models/userModel.js';
import jwt from 'jsonwebtoken';
import { JWT_SECRET } from '../config.js';
import bcrypt from 'bcryptjs';
import { auth } from '../middleware/authMiddleware.js';


const userRouter = express.Router();

userRouter.post('/login', async (req, res) => {
    try {
        const { email, password } = req.body;
        if(!email || !password) {
            return res.status(422).send({
                error: "All the fields are required"
            });
        }else {
            const user = await User.findOne({email});
            if (user) {
                const passwordCheck = await bcrypt.compare(password, user.password);
                // check if password matches
                if(!passwordCheck) {
                    return res.status(400).send({
                        error: "Invalid email or password"
                    });
                }else {
                    //create the token
                    const token = jwt.sign({
                        userId: user._id                
                    }, JWT_SECRET , { expiresIn: '10d'});
        
                    return res.status(200).send({
                        user: {
                            _id: user._id,
                            username: user.username,
                            email: user.email
                        },
                        token
                    });
                }
            }else {
                return res.status(500).send({
                    error: "Invalid email or password"
                });
            }
        }
    } catch (error) {
        return res.status(500).send({
            error: error.message
        });
    }   
});

userRouter.post("/register", async (req, res) => {
    const { username, email, password } = req.body;
    if(!username || !email || !password) {
        return res.status(422).send({
            error: "All the fields are required"
        });
    }
    try {
        const exists = await User.findOne({email});
        //check if user already exists
        if (exists) {
            return res.status(422).send({
                error: "Email already taken",
            });
        }
        // hash the password
        const hashedPassword = await bcrypt.hash(password, 10);
        // create a new user instance and collect the data
        const user = new User({
            username: username,
            email: email,
            password: hashedPassword
        });
        // save the new user
        const createdUser = await user.save();
        if(createdUser) {
            return res.status(200).send({
                message: "User Created Successfully",
            });
        }else {
            return res.status(500).send({
                error: "Error creating user"
            });
        }
    } catch (error) {
        return res.status(500).send({
            error
        });
    }
});

// get logged in user
userRouter.get("/user", auth, async (req, res) => {
    const user = await User.findById(req.user.userId);
    return res.status(200).send({
        user
    });
});


export default userRouter;

Use the route

Finally, let's import and use the route inside the index.js file.

                                                            
                                                                                                                                
import { db } from "./config.js";
import express from "express";
import cors from "cors";
import mongoose from "mongoose";
import userRouter from './routes/userRouter.js';

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

app.use(cors());

app.use('/users', userRouter);

//connect to the database
mongoose.connect(db).then(() => {
    app.listen(3001, () => {
        console.log('App is running on port 3001');
    });
}).catch(error => console.log(error));