Create A Node JS Authentication API with JWT

PatientRent8401
6 min readJul 5, 2023

--

Before starting Creating our API we should be familiar with node js and how Api works plus familiarity about JWT else this might not be a relevant post for you

jwt

Let’s Start from the scratch

Installing Node js

install node js

Check your terminal whether Node js is installed or not

Run node -v in terminal

And if all above is correct we can just dive into creating our authentication API

create a node js project by typing this in the terminal

Now we’ll install some package’s

packages
npm i express jsonwebtoken mongoose nodemon

Now go to your package.json file and add this in your script line

 "scripts": {
"start":"nodemon run index"
},

Final Package json file

{
"name": "codespaces-blank",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start":"nodemon run index"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"mongoose": "^7.3.1",
"nodemon": "^2.0.22"
}
}

Also Make sure to create your atlas Account if using MongoDB (I prefer this)

You might see process.env.variable so you can just ignore that as this is what ill use to hide some private information of database :)

Project Structure

Project structure

Creating a basic express server and connecting it to the database

const express=require('express')
const mongoose=require("mongoose")
const dotenv=require('dotenv').config()
const app=express()
app.use(express.json())

mongoose.connect(process.env.DB_URI,{useNewUrlParser:true,useUnifiedTopology:true}).then((r)=>{
console.log("Connected to DB")
}).catch((e)=>{
console.log(e)
})



app.listen(3000,()=>{

})

That’s just a basic Server with no routes and stuffs currently going on

Now let’s create our Model first that we are going to use to store data in db

const express=require("express")
const router=express.Router()

router.get("/",(req,res)=>{
res.json("i work fine")
})
router.post("/login",(req,res)=>{

})
router.post("/register",(req,res)=>{})

module.exports=router

A small basic outline how the routes will be later as well

We’ll come back later to routes after defining our model as all the remaining code will be done there

Now User.js -> which is user model for storing username and password that’s all XD

const mongoose=require("mongoose")

const UserSchema=new mongoose.Schema({
username:{
type:String,
required:true,
},
password:{
type:String,
required:true,
min:8,
},

})

module.exports=mongoose.model("User",UserSchema)

This is our basic model to store username and password (ps: we’ll hash the password later)

alright our base is done now let’s move to route (Now the important stuffs begin)

but before going to Route.js let’s make express to use all our route’s by importing Route that we created in index.js

const express=require('express')
const mongoose=require("mongoose")
const dotenv=require('dotenv').config()
const Routes=require("./routes/Route")
const app=express()
app.use(express.json())
app.use(Routes)
mongoose.connect(process.env.DB_URI,{useNewUrlParser:true,useUnifiedTopology:true}).then((r)=>{
console.log("Connected to DB")
}).catch((e)=>{
console.log(e)
})



app.listen(3000,()=>{
console.log("server running on port 3000")
})

Okay so after doing this we will be able to check our api at “http://localhost:3000/”

I am using github codespaces so my url may differ but your’s will be http://localhost:3000

doing a get request on postman
routes->Route.js
routes->Route.js

If you don’t know what is postman you can find it on google or YouTube

Now let’s work first on our register route

First we need to install a package for hashing the password “bcrypt”

npm i bcrypt

First i’ll add the code then explain

router.post("/register",(req,res)=>{
const userexist=User.findOne({username:req.body.username})
if(userexist){
res.json("User already exists")
}
else{
const password=bcrypt.hash(req.body.password,10)
const user=new User({
username:req.body.username,
password:password
})
user.save().then((r)=>{
res.json(r)
}).catch((e)=>{
res.json(e)
})
}

})

so in the above route first we checked wheather is the user is already existing in our database , if he/she exist’s we will send a response saying user already exists

next if the user does not exist that means it’s a new user so we create a new user by requesting the value by “req.body.username” similarly for the password

but before inserting it into the database we need to hash the password so that user’s data is never at risk :) so now we use bcrypt package to hash the password by passing it salt gen of 10 (you can read the documentation of the bcypt library)

router.post("/register",async(req,res)=>{
const userexist=await User.findOne({username:req.body.username})
if(userexist){
res.json("User already exists")
}
else{
const password=await bcrypt.hash(req.body.password,10)
const user=new User({
username:req.body.username,
password:password
})ja
const userdata=await user.save()
res.send(userdata)
}

})
postman sending request to register endpoint
mongo atlas

Now let’s make Login

thought making login is pretty easy without using jwt

First we’ll check the username is correct or not then we’ll check wheather the password is correct but wait the password was hashed how will we be able to check that password with the hash as the hash look’s very weird text you can see in the above image

Though we will use bcrypt.compare to compare the hash with the password


router.post("/login",async(req,res)=>{
const user=await User.findOne({username:req.body.username})
if(user){
const validpassword=await bcrypt.compare(req.body.password,user.password)
if(validpassword){
res.json("Logged in")
}
else{
res.json("Invalid password")
}
}

})

This is a simple login but without JWT

Now let’s implement JWT

Photo by Raoul Droog on Unsplash

first i’ll add the code here

const jwt=require("jsonwebtoken")


router.post("/login",async(req,res)=>{
const user=await User.findOne({username:req.body.username})
if(user){
const validpassword=await bcrypt.compare(req.body.password,user.password)
if (!validpassword){
res.json("Invalid password")
}
const token=await jwt.sign({username:user.username},"enteryoursecret")
res.cookie("jwt",token,{httpOnly:true,maxAge:24*60*60*1000})
res.json("Logged in")
}

})

first import the jwt then we will add a token and sign it with our username you can use _id which is mostly used for this example i’ve used username , then provide your secret key which one of the most important thing so please keep it secure , i’ve just added some random thing for you to understand , then we will save the cookie which lifespan kept is 1day

after registering new user

After logging in you can see the cookie section , there will be a cookie named jwt that’s your JWT

ignore my first cookie that cookie is due to github codespace
ignore the first cookie as it of the github codespaces

well the second cookie is our is jwt

we’ll ill show you something bonus to verify the token

router.get("/isauth",async(req,res)=>{
const cookie=await req.cookies.jwt
const claims=await jwt.verify(cookie,process.env.SECRET_JWT)
if(!claims) return res.json("not authenticated")
const user=await User.findOne({username:claims.username})
const {password,...data}=await user.toJSON()
res.json(data)
})

router.get("/logout",(req,res)=>{
res.cookie("jwt","",{maxAge:0})
res.json("Logged out")
})

For logging out and verifying the token

/isauth is for verifying token

Though ill end here , Thank you for reading this and congrats if you were able to implement JWT

Check the repo if you want to try out (check second branch for email verification)

will make more stuffs like this soon

:)

--

--

No responses yet