Skip to main content

Authentication: Register & Login using JWT in Express & MYSQL

In the previous tutorial, i showed how to upload form data with file using Multer & MYSQL in Express. This tutorial teaches you how to do authentication in Express using JWT (JSON Web Token) and MYSQL database. 

Why we need authentication? The requirement is to allow APIs access to only authorized users. 

A visitor creates a user account using username, email, and password. We are going to use bcrypt package to create an encrypted version of the password and to verify the password againts MYSQL database. Execute the following command to install bcrypt.

npm i bcrypt

Once the account is created successfully, he/she can login to the system. The login information is verified on Express server. If the log in information is correct, valid token will be created and returned to a client app. The client app that received the token need to pass the token to the server to get permission to access the APIs. The token has to be verified before granting permissions. The information in the token can be verified and trusted because it is digitally signed. 

In Express, we use jsonwebtoken package to create, sign, and verify a token. Run the command below to install jsonwebtoken.

npm i jsonwebtoken

To create and verify a token, jsonwebtoken needs a secret key. Generally, a secret key is stored .env file. Thus, in the root folder of the Express app, create .env file and add a secret key as shown below.

JWT_KEY="secretOrKeyJWTRandom"

In Express, to read the secret key, we used dotenv package. Let install it.

npm i dotenv

Now we are ready to create routes to handle user registration and login. in the routes folder, create user.routes.js file:

require('dotenv').config();
var router = require('express').Router();
const bcrypt = require('bcrypt');
const KEY = process.env.JWT_KEY;
const jwt = require('jsonwebtoken');
const db = require("../db/models");

// handle user registration
router.post('/createuser', async function(req, res) {

    if(req.body){
         // Get post data
        const { body } = req;
        const { username, email, password } = body;
        // created encrypted password
        let password_encrypted= await bcrypt.hash(password, 10);
        // add new user to database
        await db.User.create({
          username:username,
          email:email,
          password:password_encrypted,

        }).then(newuser =>{ // return success result
          return res.status(200).json({
            message: 'success',
            data: newuser,
          });
        }).catch(err => { // return err result
          res.status(500).send({
            message:
              err.message || "Some error occurred while inserting new user"
          });
        });
       
   
    }
});

// handle user log in
router.post('/auth', async function(req, res) {

   // Get post data
   const { username, password } = req.body;
   /* Any how email or password is blank */
   if (!username|| !password) {
     return res.json({
       message: 'Request missing username or password',
     });
   }
   // Check user in database
   await db.User.findOne({
     where: { username: username},
     attributes: ['id','username', 'email', 'password'],
     limit: 1,
   }).then(user =>{
      if(!user)  return res.json({
        message: 'Invalid user!',
      });
       /* Define variables */
      const dataUser = user.toJSON();
      const userId = dataUser.id,
      userEmail = dataUser.email,
      userPassword = dataUser.password;

      /* Check and compare password */
      bcrypt.compare(password, userPassword).then(isMatch => {
        if (isMatch) {
          // User matched
          // Create JWT Payload */
          const payload = {
            id: userId,
            email: userEmail,
          };
          // Sign token
         
          const token = jwt.sign(payload, KEY, {
                  expiresIn: '72h'
          });
          res.json({ message: 'success', token:token });

        } else {
          res.json({ message: 'Password incorrect' });
        }
      });
 
   });
   
});

module.exports = router;
   

Then add the user.routes.js file to app.js.

....................
app.use('/api', require('./routes/user.routes'));
app.use('/api', require('./routes/product.routes'));
......................

Save the project and run node app.js to start Express server. Try create a new user using http://localhost:5000/api/crreateuser url. Then login to obtain a token using http://localhost:5000/api/auth url.

Protect APIs

To protect APIs or routes, you need a middleware to verify the submitted token. If the verification is successful, next handler method will be executed. Otherwise "unauthorized" error message will be returned to the client. 
In the root folder of the project, create utils folder and add verifyToken.js file to the folder.

utils/verifyToken.js
require('dotenv').config();
const jwt = require('jsonwebtoken');
const KEY = process.env.JWT_KEY;

const verifyToken = function(req, res, next) {

const bearerHeader = req.headers['authorization'];
  if (!bearerHeader) {
    res.status(401).send('Unauthorized: No token provided');
  } else {
    let token = bearerHeader.split(' ')[1];

    jwt.verify(token, KEY, function(err, decoded) {
      if (err) {
       
        res.status(401).send('Unauthorized: Invalid token');
      } else {
        req.email = decoded.username;
        next();
      }
    });
  }
}
module.exports = verifyToken;

To protect an API, you need to add the verifyToken middleware function to the handler method of the route. For example, to project routes to list products, add, and update product, update the product.routes.js file to include verifyToken middleware:

...................   
const verifyToken = require('../utils/verifyToken');

router.get("/products", verifyToken, function(req,res){.....}
router.post("/products", verifyToken, function(req,res){......}
router.put("/products", verifyToken, function(req,res){.....}

Comments

Popular posts from this blog

Get start with React

To start web development with React, i recommend you install Node. Node comes with NPM (package manager) helps you easy to add dependencies, create, start, and build your React apps. You can download and install NPM from its official web site: Download NPM . Another useful tool for coder is Visual Studio Code . On my Windows machine, i have installed Node version 16.10.0 with NPM 7.14.0. Now create a project folder and name it react_tutorials in Drive D: or other drive of your choice. Then open the folder in Visual Studio COde (VSC). From the VSC editor, select Terminal. In the terminal, enter the following command to create my-app app in the project folder created above. D:\react_tutorials>npm init react-app my-app After the my-app app is created successfully. You change to my-app folder (cd my-app) . Then You run " npm start " command to start your first react app on browser. React automatically starts on port 3000.

Why React?

React is one of the top UI development frameworks. It is very popular today among web developers around the globe. I love React because of the following things: - It is simple to learn and use. - It is JavaScript library. - It effectively applies changes to a web page without reloading the page while data changed. - It is easy to find problems or errors while you are coding.

React Express & MYSQL - Full Stack Product Admin Panel

In the earlier tutorials, you learnt to create React app , and API endpoints to do authentication with JWT, protect APIs, get and count rows of MYSQL database, and upload form data with files to the database in ExpressJs. In this tutorial, we continue to develop the React app to build a full stack product admin panel website that accesses ExpressJs API endpoints . The product admin panel app will have a left sidebar that allows a visitor easily to navigate different parts of the app. We use bootstrap to style the app. So run the following command to add bootstrap into the React app. my-app>npm install bootstrap Our form components are from reactstrap and icons from react-icons packages. Let execute the commands below to install reactstrap and react-icons. my-app>npm install reacstrap react-icons To setup the left sidebar in the app, we start by creating the components folder in src folder. To group sidebar files, add sidebar folder to the components folder. We have three sidebar...