Node Express CRUD with Mongoose,JWT authentication,authorization
Tags: node, express, javascript, jwt
Published: 2021-08-23 11:58:13

Here we will make a CRUD with REST API along with its authentication.Express.js is unopinionated means everyone can have their own way of doing things which is quite different from a strict framework.
If you are using VS code and type **Cntrl+`** to open the terminal and write `npm init -y` 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsqyqz7nlcftd448x8n0.png)
It will create a pacakge.json file for you on the left hand side
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxmywl17d2nvglcbl80f.png)
At first you need to install express and mongoose. 
`npm install express` && `npm install mongoose`
If you go to `package.json file` you can see 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7g40gopk2o5gxvujk2h.png)
In our depencies you have got your express and mongoose installed to check whether a package has been installed go package.json. These are pretty basic stuffs but will help a begiiner a lot.
you will create a file called app.js
in `app.js`
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uvsj25yauf5f6d1o4z34.png)
These are the thigs you will initially write in app.js file here you will initialize express 
go to terminal type `node app.js`
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n6ku54nye20prmfuub75.png)
 Now we can see that the server is initialized on port 5000. The port can be anything 5000,6000,8000.
But the problem is we need to run it each and every single time when there is any change. As a result we need to install `nodemon`
`npm install nodemon` Then if we go to our package.json file we will see 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgfms0u28j1kc7epqpkl.png)
noe if we want to use nodemon we can use the scripts in package.json file 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0g6bgilh4yodb2kn8yo3.png)
Now we can go to your terminal and run npm start 

  ![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zaehj5pf7swua69k0af1.png)
Now you dont need to run node app.js nodemon will restart everytime there is a change
**Connection with MongoDB through mongoose**
If you dont have MongoDb installed on your system please install it first. Here you creating a new database we will use Robo3t here 
if you go to Robo 3t you can see 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o92gail1fk4twbkknmi3.png)
If you click connect you can see 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3eop7w48mutq63w349vx.png)
 
 It will look something like this 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dut4scjy6tx1tsyk1p73.png)
 
From here you will see a modal like this you will named your databse and see create
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhormcaxbsnjyf2zagug.png)

 If you have done everything correctly you will see name of the databse you have created on the left 


We can use .env files for that we need to install a new package 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4f93b8864ok7bt106pgy.png)

 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2h88xzpdwkm3ey8iyq0p.png)
  
If everything is alright we can now we can see it running
 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mx1jfj27fg5n0xgcaudb.png)
We can install `npm install dotenv` to keep database name in an env file 
In .env file 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxwq30dv1u7auib2x5hr.png)
 In app.js file
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzam0my54eey1gjxczp6.png)
 
**This is not mandatory but a good practice** 
**Router**
Let us get the router fixed we need to create a new file called router.js you can set all routes inside app.js but its better to have a separate route file now if we create router.js 



![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dbnp5zkmizzv60d5kxrg.png)
 
 In app.js 
`const allRouter=require('./routes')`
`app.use('/',allRouter);`

Now we need 2 parts 1 is the model and other is the controller
In Model part there will be the database and controller part will have the logic
 
Create a new folder model/Post.js
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu3912y160pu1eexqm7v.png)
here we see we can that we want to add two fields to posts collection title and description 
 
**CRUD part**
**CREATE**
In routes.js 
Import PostsController
`const PostsController=require("./controller/Posts")`;
*Post route*
`router.post('/posts/create',PostsController.createPost);`
Import Post Model on top
in controller/Posts.js
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upqn6kobuy8xunb7yy4p.png)
**Test in Postman**
Make sure in headers Content type is set to application/json
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxhgv5q38xk37d322zvm.png)
Testing post request
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3h4upp7zeaxqmm85ctdl.png)
 
We can clearly see its successfull giving us a status code of 200
 
**READ**
In router.js
`router.get('/posts',PostsController.getPost)`
![getpostimage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bjrozo57f7t9txlhh4pj.png)
 
In controller/Posts.js

**Postman test** 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofha44j6ood3lcqkrskg.png)
If we also check in Robo 3T 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5fzoi1wpmzm22r3qnbi0.png)
  
Now we can say that it has been successfully inserted onto database.
 ** READING A SINGLE POST**
In router.js
`router.get('/posts/:id',PostsController.findSinglePost)`
In controller/Posts.js
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tt9nmp2evadnv739hzu.png)
 
**Test in Postman**
Here you can get id from databse using Robo3T or just by using get requests to get all posts 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3jymmxuurq698mkvr85n.png)
 Now we see from where we can get the id and get a single post
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gd5wsyub3dvgki21s2ys.png)

 **UPDATE**
In router.js
`//Updating a single post
router.put('/posts/:id',PostsController.updatePost);`
In controller/Posts.js 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y7lvltczmf7og9s48rr9.png)
**Testing in postman**
The same way we get id like shown with getting id of a single post 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwhvbl40i9rqj9d1rine.png)
 **DELETE**
In router.js
`//Delete a post
router.delete('/posts/:id',PostsController.deletePost);`
In controller/Posts.js
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2ewfpa06hfdrxqs1l8m.png)
**Testing in postman**
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jek14e5gkc1fqlhh275t.png)
We will get the individual post and delete 
**While Updating you most likely will get an warning**
![Mongo Db update warning](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoeb2r7s2kstfkp5ib72.png)
For resolving the warning go to app.js
`useFindAndModify: false` 
![Mongo Update warning resolved](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zrhrs8syngc5utotirdh.png)

**API Authentication,authorization with JWT**
 Now we will do authentication using email and password only. Remember **JWT** is used for authorization not authentication 
Create a new model in **model/User.js**
**IN User.js**
In this case 
![model user](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4b08fhmti6xmnlmfbpk.png)
 Here we are including email,password and token.

In controller folder we will create a new file called `Auth.js`
We need to import User model at the top 
![User Model](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omubbild6dt59dwl43jz.png)
 
In **router.js**
//signup route
`router.post('/signup',AuthController.signup)` we need to import AuthController at the top
 `const AuthController=require("./controller/Auth")`
  In `controller/Auth.js`
We need to install a package called [bcyrpt](https://www.npmjs.com/package/bcrypt)
Signup method in Auth.js
![signuprevised](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/juxvp6aop5waywh2i618.png)
 
 Here is signup we need to use bcrypt to hash the password as we all know passwords cant be stored in plain text
**Testing in Postman**
![signuproute](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuly9dg8t18ct92l91ak.png)
 As we see the password is hashed and status is ok 
**Signin Route**
In **router.js**
`router.post('/signin',AuthController.signin);`
![signin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhlreuzp407paz4b6jzy.png)
In signin route after checking credentials a token needs to be generated.**Remember Token is for authorization not authentication**. We set the secret key on top the secret key can be set in .env file remember the secret key must be secret.
**Testing in Postman**
![signinroutetesting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2lr79uhkexcrznf16ky.png)

**Authorization**
We will use a pacakge named [express-jwt](https://www.npmjs.com/package/express-jwt) for installing `npm install express-jwt`.
**Creating a middleware**
A middleware can be termed as something between a request and response.If we want to protect any route that users who only have token can enter those routers.
in `controller/Auth.js`
![signedIn middleware](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9ljk1a7tv1pw1b0w1k3.png)
 **Route test with middleware** 
`In router.js` on top 
`const {isSignedIn}=require("./controller/Auth");`
**Route with isSignedIn**
`router.get('/testauthroute',isSignedIn,(req,res)=>{
     res.send("A protected route")
    res.json(req.auth)
})`

**Testing in Postman**
![testuthroute](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oi9qwi4l2tv83lkf1g6o.png)
Here if we try to access this route without token we get this error 401 forbidden means without token you cant access this route.
![test with token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ot2kiri4ocrhr1c43zwf.png)
 
Here we need to go to header part of the token include **Authorization** in header.In value of authorization header we need to write Bearer give a space before the token and then copy and paste the token ![authorization value](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yriols97fielj5k7d74o.png)
If you go to [jwt](https://jwt.io/) and test your jwt you will see you get all your info
![jwt](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s6hrs9kwognn8a6u4zxl.png). Here header is the type which is JWT the signature is the token and payload is the email and id.So that's all for this blog. Hopefully you will be able to grasp the concepts of Node,Express,Jwt,authentication,authorization here.