DEV Community

Bernice Waweru
Bernice Waweru

Posted on

Secure User Sign In Node Using JWT

This post will focus on user login in after they have registered.
You can find the post on user registration here.
In the previous section, we created the server, connected to MongoDB and also created the user model.
Here we will build up on the login logic.

Create login.js inside the routes folder.
Inside this file we will create the login endpoint which will:

  • Receive user details from client request.
  • Validate the details provided.
  • Check if the user exists in the database.
  • Authenticate the user by comparing the details provided and those in the database.
  • Return a Json Web Token to the client which will be used to authenticate the user in future requests.

The token is returned as a cookie.

Explore more on Json Web Tokens and how to use them here.

require('dotenv').config()
const { User, validate } = require('../models/user')
const bcrypt = require('bcrypt')
const express = require('express')
const jwt = require('jsonwebtoken')
const router = express.Router()
const SECRET = process.env.SECRET
const jwtExpirySeconds = 300

const loginRouter = router.post('/login', async (req, res) => {
    const { error } = validate(req.body)
    if (error) {
        return res.status(401).send(error.details[0].message)
    } else {
        try {
            let user = await User.findOne({ email: req.body.email })
            if (!user) {
                return res.status(400).json({ message: 'Incorrect email or password.' })
            }
            const correctPassword = await bcrypt.compare(req.body.password, user.password)
            if (!correctPassword) {
                return res.status(400).json({ message: 'Incorrect email or password.' })
            }
            const token = jwt.sign({ id: user._id }, SECRET)
            res.cookie(
                "token", token, {
                httpOnly: true,
                secure: process.env.NODE_ENV !== 'development',
                sameSite: "strict",
                maxAge: jwtExpirySeconds * 1000
            })
            res.json({ message: 'Successfully logged in' })

        } catch (err) {
            return res.status(400).json({ message: err.message })
        }
    }
})

module.exports = loginRouter
Enter fullscreen mode Exit fullscreen mode

Let us understand what happens with the Json Web Tokens.
You need to set a SECRET on the .env file which will be used to sign the token

Ensure the SECRET is not easily predictable because it can be used to exploit the JWT tokens. Here is an example

After generating the JWT token we set it in the cookie which will be sent to the client.

Add the following changes to index.js

const loginRouter = require('./routes/login')
app.use('/api', loginRouter)
Enter fullscreen mode Exit fullscreen mode

This ensure the application calls the loginRouter callback function when the application receives requests that match the specified route(api/login) and method(post).

Run the application using node index.js

Server start up
Test on Postman using a user you have previously registered.
Successful login
On the the cookies tab the HttpOnly flag is set to true and the secure flag is set to false because this is still in development.
When in production we can set this flag to true.

Cookie data
Code repo
Happy coding!!

References

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly β€” using the tools and languages you already love!

Learn More

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay