Demystifying Token-Based Authentication: A Deep Dive into the JWT Workflow

Guardians of Access: Demystifying JWTs in the Realm of Authentication

Demystifying Token-Based Authentication: A Deep Dive into the JWT Workflow

Hey Folks! hope you all are doing extremely well, today we are gonna learn about the workflow of a Token Based Authentication, (specifically JWT).

In the ever-evolving landscape of web security, authentication plays a pivotal role in safeguarding user data and ensuring secure communication between clients and servers. One of the most widely adopted methods for achieving this is through Token-based authentication, with JSON Web Tokens (JWT) emerging as a frontrunner.

Now, Time for the Take Off, Are You Ready? 3...2...1 and here we go🚀

What is Token-Based Authentication?🤔

Token-based authentication revolves around the use of tokens to verify the identity of a user. Unlike traditional methods that rely on sessions and cookies, token-based authentication offers a stateless solution, making it highly scalable and suitable for modern web development.

Why JWT ?

JSON Web Tokens, or JWTs, have become synonymous with token-based authentication. They are compact, URL-safe, and self-contained, carrying information in a structured format that can be easily verified. Understanding the JWT workflow is crucial for anyone involved in building secure, modern applications.

Now, Let's begin with our actual discussion of comprehending the Workflow of Token Based Authentication.

The JWT Workflow🚀

  1. A person goes on to your website and sees two input fields let's say (email & password), he fills that in and clicks on the Login Button.

  2. As soon as the login button is clicked, a request is made to the backend server. The Backend server first converts the password provided by the person in the hashed format, (because in the databases, usually, passwords are not straightforwardly saved, it is converted into some gibberish (hashed) and then saved there), after conversion it checks if the credentials sent by the person resides in the database or not.

  3. If there exists, the backend will create a JWT (JSON Web Token) made using a secret key along with some JSON data of the user like its ID & email (.sign method provided by jsonwebtokens are used), and returns it to the client (the front end).

     var token=jwt.sign({username:username},secretKey)
         return res.json({
             token
         })
    
  4. When the client gets this JWT, it stores this token in the browser's local storage, somewhat like localstorage.set("token",jwtReceived).

  5. This token gets stored in the localstorage for a very long time, let us say up till the time the user doesn't log out.

  6. Now, with any subsequent request, that will go on from the front-end by the person, (let's say he clicked on the Profile button) to the backend servers, the frontend has ensured that with every request it is sending the token in the headers, you might have seen something like Authorization: Bearer token in the request headers.

  7. In this way, the person doesn't always need to send the email and password to backend servers for identity purposes.

  8. Just send this JWT token and the backend can just verify using jwt.verify(<token-received>,<secret-key>) that is token correct or not ?

    If it is, the backend lets the person access a set of resources, that he is privileged to.

     try{
         jwt.verify(<token-received>,<secret-key>);
         res.json(
             {"data":userData}          //if the user is authenticated, we will show him data of all the users
         )
     }
     catch(error){
         res.json({"error":"Invalid Token"})
     }
    
  9. If the verification fails, the backend blocks this person from accessing the resources.

This was all, let us summarize this all by writing some code so that it gets right into our head right!

We are simply creating 3 routes first will be /signup route, second will be /signin route and the third will be /userProfile which will return the data of the logged-in user also the one who is authenticated has this privilege.. Hope you got what I'm trying to build!

Let us Write the code now!

const express=require('express')
const jwt=require('jsonwebtoken')
const cors=require('cors')
const bcrypt=require('bcryptjs')
const { mongoose } = require('mongoose')
const User=require('./models/User')            //our User database
const salt=bcrypt.genSaltSync()
const secretKey="hello123@#42421"

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

mongoose.connect('mongodb+srv://<username>:<password>@cluster0.lgrhctg.mongodb.net/?retryWrites=true&w=majority')

app.post('/signup',async (req,res)=>{
    const {name,email,password}=req.body

    try{
        const userInfo=await User.create({
            name:name,
            email:email,
            password: bcrypt.hashSync(password,salt)
        })
        res.status(200).json({'status':"User Registered Successfully!"})
    }
    catch(e){
        res.status(400).json({'status':"Something Went Wrong!"})
    }
})

app.post('/signin',async(req,res)=>{
    const {email,password}=req.body;
    const userInfo=await User.findOne({email})
    if(!userInfo.email){
        res.status(400).json({'err':"User Doesn't Exist!"})
    }

    const passCheck=bcrypt.compareSync(password,userInfo.password)          //.compareSync functn of bcypt will return false if pwd doesn't match
    if(passCheck){
        const token=jwt.sign({email, id:userInfo._id }, secretKey, {}, (err,token)=>{
            if (err) throw err

            res.json({
                token
            })
        })
    }

    else{                              //means password isn't correct, so login will be failed!
        res.status(400).json({'err':"Invalid Password: Please Try Again!"})
    }
}) 

app.get('/userProfile',(req,res)=>{
    const token=req.headers.authorization

    try{
        const decodedData=jwt.verify(token,secretKey)           //will return true/false depending verification is correct or not.

        res.json({
               "data":decodedData
          })
    }
    catch(error){
        return res.status(403).json({
            msg:"Invalid token" 
        })
    }
})

app.listen(3000,()=>{
    console.log("Server Running on PORT 3000");
})

As we sign off on this JWT adventure, may your tokens always be valid, your keys forever secure, and your users consistently delighted with the seamless dance of authentication😁😉

With That Set, let us End Up Here!, I hope that I was able to add some knowledge and value to your learnings through this blog!
Still Doubtful ?🤔🤷‍♂️ Comments are always open. I will be Glad to help!

👉Do Consider Subscribing to The Newsletter, so that you never miss an update from us!

#LearningInPublic #Authentication #jsonwebtokens

#HappyLearningFolks!

Did you find this article valuable?

Support Prakhar Sinha by becoming a sponsor. Any amount is appreciated!