JWT In Plain English
Published: 2022-04-15 10:21:31

---
title: JWT In Plain English
published: true
description: 
tags: 
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0orkv3kc0rrpk8a6yxim.jpg
---
TLDR;
1. Install json web token `npm i jsonwebtoken`
2. Require 
3. Generate token
4. Sign the json web token with the users id, secret and expiration time
5. Check the token in Postman, Database, and [jwt.io](https://jwt.io/) 
6. Build a route to protect and create the logic
7. Create middleware to verify the token for the current user
8. Place middleware into the desired route to protect

## What is a json web token?
A secure way to access protected routes through authenticating users and sharing information.
The issuer uses a secret to sign the JWT. The receiver will verify the signature to make sure the token hasn’t been altered after it was signed by the issuer. 

## Context
I am building a MERN (MongoDB, Express, React, Node) app that will have a user register as a new user or login if the user already exists. The user's information gets stored in the MongoDB database via Express and Node on the Backend. I am utilizing the MVC (Model-view-controller) pattern for separation of concerns, see the link for more info on [MVC] (https://www.freecodecamp.org/news/the-model-view-controller-pattern-mvc-architecture-and-frameworks-explained/).

 
Versions
- node v16.13.1 
- bcryptjs v^2.4.3,
- express v^4.17.3,
- express-async-handler v^1.2.0,
- jsonwebtoken v^8.5.1,
- mongoose v^6.2.10

Drilling down further in this demo will only need to focus on the
`userController.js`, `authMiddleware.js`, and `userRoutes.js` see the file structure below:
###### client also known as view
```
client
backend
   |config
   |-controller        
         |-userController.js
   |-middleware
         |-authMiddleware.js
   |models
   |-routes
         |-userRoutes.js
   |server
.env
.gitignore
package-lock.json
package.json
```
Once you have created a user in your database you will need login typically with a password and email.  I use [bcryptjs](https://www.npmjs.com/package/bcryptjs) to salt my users password from plaintext to a hashed password and confirmed this on [Postman](https://www.postman.com/) and in the database [MongoDB](https://www.mongodb.com/). Now you are ready to create the json web token. 


-----------------------
## Set up the json web token
## Step 1
### Install

In your cli run `npm i jsonwebtoken` check if it's in your package.json `"jsonwebtoken": "^8.5.1"`

-----------------------

## Step 2
### Require
In your controller folder, open a file with the users routes logic. I called mine `userController.js` bring in `const jwt = require ('jsonwebtoken')`
See my code:

### backend>controllers>userController.js

```javascript
userContoller.js

// Simple middleware for handling exceptions inside of async express routes and passing them to your express error handlers. Need to wrap entire function
const asyncHandler = require('express-async-handler');

// Use bcrypt to hash the password
const bcrypt = require('bcryptjs');

// Bring in the user model
const User = require('../models/userModel');

// Bring in jsonwebtoken
const jwt = require ('jsonwebtoken')
```
-----------------------
## Step 3
### Generate A Token
Generate a token and pass the users id. The generateToken function will return a .sign method
```javascript
userContoller.js

const generateToken = (id)=> {
return jwt.sign({})
}
```
-----------------------
## Step 4
### Sign The Token
The returned .sing method will take in 3 arguments
- users id, an object
- secret (can be anything and should be hidden in your .env)
- expiration time, an option object

```javascript
userContoller.js

const generateToken = (id)=> {
return jwt.sign({id},process.env.JWT_SECRET,{expiresIn:'4d'})
}
```
-----------------------
## Step 5 
Put It Together
The token needs to be generated with the users id. In my user collection in MonogDB this would be `user._id` and must be signed. In the register and login route there will be a `res.json({})` that gets returned and in the object will have `token:generateToken(user._id)`

### backend>controllers>userController.js
```javascript
userContoller.js

const registerUser=()=> {
code logic...
res.status(200).json({
  // user in mongodb stores id as _id
  _id: user._id,
  name: user.name,
  email: user.email,
  token:generateToken(user._id)
  });
}

const loginUser=()=> {
code logic...
res.status(200).json({
  // user in mongodb stores id as _id
  _id: user._id,
  name: user.name,
  email: user.email,
  token:generateToken(user._id)
  });
}
```
The generate function
### backend>controllers>userController
```javascript
userContoller.js

// GENERATE TOKEN
const generateToken = (id) => {
  return jwt.sign({ id }, process.env.JWT_SECRET, {
    expiresIn: '4d'
  });
};
```

-----------------------
## Step 6
Check For Confirmation
I deleted my test user from my database and registered a new user with Postman to manually verify the token was passed http://localhost:5000/api/users
![Postman](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z81yl60qp7ghzbllnd84.png)
Inside the token is the users id. Manually verify it, copy and paste your token into [jwt.io](https://jwt.io/) the field on the left and on the right you will see the payload
![jwt.io](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xi81n1ced5iirho9ddo6.png)
 
The payload circled in red should match the _id in Postman and the _id in your database.

![MongoDB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1ko8qul9u0homohu4mc.png)

## Halfway Home
Now that we created a token how do we use it? The protected route functionality can be achieved in several ways.
Here's how I would do it: build a route, create the logic, create middleware, bring the middleware into the route to protect. 
 
- Build a route I want to protect called `router.get('/me', getUser);` in the routes folder in `userRoutes.js`, later we will come back to this file and add the middleware.

### backend>routes>userRoutes.js
```javascript
userRoutes.js

const express = require('express');
const router = express.Router();

// bring logic from the controllers folder
const { registerUser, loginUser, getUser } = require('../controllers/userController');

// example: router.method(path, logic)
router.post('/', registerUser);
router.get('/login', loginUser);

// protected route, will add protect middleware last
router.get('/me', getUser);

module.exports = router;
```
- Create getUser logic in the controllers like this

### backend>controllers>userController.js
```javascript
userController.js

const asyncHandler = require('express-async-handler');
const bcrypt = require('bcryptjs');
const User = require('../models/userModel');
const jwt = require('jsonwebtoken');

const registerUser=()=> {
code logic...
}

const loginUser=()=> {
code logic...
}

const getUser = asyncHandler(async (req, res) => {
  const user = {
    id: req.user._id,
    email: req.user.email,
    name: req.user.name
  };
  res.status(200).json(user);
});

const generateToken = (id) => {
  return jwt.sign({ id }, process.env.JWT_SECRET, {
    expiresIn: '4d'
  });
};

module.exports = {
  loginUser,
  registerUser,
  getUser
};
```
- Add a piece of middleware called `authMiddleware.js` with a function called `protect` to verify the token will get passed into the headers and return only the specific user info for that token. 

###  backend>middleware>authMiddleware.js

```javascript
authMiddleware.js
// *MIDDLEWARE FOR PROTECTED ROUTES
const jwt = require('jsonwebtoken');
const asyncHandler= require('express-async-handler');
const User = require('../models/userModel');

const protect= asyncHandler(async(req, res, next)=> {
    let token;

// Bearer token
// Check for token in the headers for authorization and Bearer token
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')){
try {
    // Get the token from the header
    // it comes back as "Bearer token" must split at space
    // split will return[Bearer token] and need the second item
    token= req.headers.authorization.split(' ')[1]

    // Verify the token value has not changed and the secret is the same
    const decoded = jwt.verify(token, process.env.JWT_SECRET)

    // Return the user from the user id in the token minus the password
    req.user =await User.findById(decoded.id).select('-password');

next()

} catch (error) {
console.log(error);
res.status(401)
throw new Error('Not Authorized')
}
}

//  If there is no token in the first place
if(!token){
    res.status(401)
    throw new Error('Not Authorized')
}

})
module.exports = {protect}
```
- Lastly bring the protect function middleware into the `userRoutes.js`.

### backend>routes>userRoutes.js
```javascript
userRoutes.js

const express = require('express');
const router = express.Router();

// Bring logic from the controllers folder
const { registerUser, loginUser, getUser } = require('../controllers/userController');

// Bring in middleware to protect routes
const {protect}= require('../middleware/authMiddleware');

// example: router.method(path, logic)
router.post('/', registerUser);
router.get('/login', loginUser);

// protected route
router.get('/me',protect, getUser);

module.exports = router;
```
Finally check the protected route through Postman to verify it's protected. You'll want to use the Auth tab and paste your token in from your login route
![Bearer token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xesl0b6q9ln8g3fgqjyo.png)
 

### We are finished here!

Thank you for your time. 

#### Happy Coding!

## Links :link:
[json web token](https://www.npmjs.com/package/jsonwebtoken)
[jwt.io](https://jwt.io/)
[MVC](https://www.freecodecamp.org/news/the-model-view-controller-pattern-mvc-architecture-and-frameworks-explained/)
[Postman](https://www.postman.com/)
[Express-Async-Handler](https://github.com/Abazhenov/express-async-handler)
[bcryptjs](https://www.npmjs.com/package/bcryptjs)
[MongoDB](https://www.mongodb.com/)
[Node](https://nodejs.org/en/)

## Social :heart:
[Twitter](https://twitter.com/GregoriosPetro1)
[Linkedin](https://www.linkedin.com/in/greg-petropoulos/)
[Portfolio](https://gregpetropoulos.dev/)
[Github](https://github.com/GregPetropoulos)