DEV Community

Amaboh
Amaboh

Posted on

Protected routes for user login

When developing an application one of the most important features is a user signup and sign in page. For some of us NOdeJs die heart developers, one major issue is making a user sign in and not being able to go back to the home page and ensuring that only sign in users can have access to some routes such as the home page or dash board.
I'll illustrate below how to achieve this functionality using a middleware in NodeJs.

First, before we dive into some coding snippets, let illustrate the case in which we would be using this piece of code.
The project we're using to illustrate this is personal blog which allows anyone to sign up and write a personal or public journal. The main technologies used in this project are NodeJs, MongoDB, Express and dependencies include dotenv, express handlebars, passport, passoport google auth20, morgan, moments, method override and express session.

This is beginner friendly project but it's expected that youy already have a good understanding of Javascript and nodeJS. This is because we'll be diving straight to the area which involves protected routes.

App.js

app.use('/auth', require('./routes/auth'))  
Enter fullscreen mode Exit fullscreen mode

routes/auth.js

// @desc Auth with Google
// @route GET /auth/google

router.get('/google',    passport.authenticate('google', {scope: ['profile']}))


// @desc Google auth callback
// @route GET /auth/google/callback

router.get(
    '/google/callback', 
    passport.authenticate('google', {failureRedirect: '/'}),
    (req, res) => {
    res.redirect('/dashboard')
    }
)
Enter fullscreen mode Exit fullscreen mode

In the lines above we're using the google auth20 to authenticate users based on the google strategy defines in config/passport.js file (I'll leave a link to the code respository for reference).

However, the first line of code in the routes/auth.js, is used to implement the google auth strategy of signing up the user and return the user profile which is used in different part of the application with the User model to extract users information and store in the database (refer to Github repo).
While the second line fo code is implementing the passport google auth strategy of authenticating the user, if there's a failure, it would redirect the user to the home page else if it's successful. Then the user would redirected to the home page.

This is where our problem arises, how do we ensure that a sign in user can't have access to the home page which is the login page. More so, how do we also ensure that a non registered user can not have access to the dashboard. This is where the middleware comes in for protected routes. The code below is an implement of routes before protected routes which results to the problem of allowing non authenticated users having access to any routes.

routes/index.js
`
// @desc Login/Landiing page
// @route GET /
router.get('/',(req, res) => {
res.render('login', {
layout: 'login',
})
})

// @desc Dshboard
// @route GET /dashboard
router.get('/dashboard', async (req, res) => {
try {
const stories = await Story.find({user: req.user.id}).lean()
res.render('dashboard',{
name: req.user.firstName,
stories
})
} catch (error) {
console.error(error)
res.render(error/500)
}

})

`

In order to fix this problem, we have to create a create middle to ensure that only a signed in user has access to the dashboard and if a user is not signup he cannot return to the homepage signup screen.

Thus we would create a new folder with the name middleware and file with the name auth.js, with the following lines of code.

middleware/auth.js
`
module.exports = {
ensureAuth: function(req, res, next){
if (req.isAuthenticated()){
return next()
} else{
res.redirect('/')
}
},
ensureGuest: function(req, res, next){
if(req.isAuthenticated()){
res.redirect('/dashboard')
} else{
return next()
}
},

}

`

The first function named ensuredAuth is a middleware function which ensures that when a user is signed in and in the dashboard route, he cannot access the homepage '/ route. It does this by first checking that if the user authenticated with the implementation of the if function, the if the user is signed, meaning the user is authenticated, then it goes to the next else it request the user to sign in by redirecting the user to the HomePage. Thus, it is suitable to implement this middleware in the '/dashboard' route to prevent signed in users from going back to the homepage.

While the second function ensureGuest, is used to protecting registered non registered users from accessing the sign up page after signing in. Thus serving as a check mechanism to ensure that authenticated users cannot go to the sign up home page by redirecting them to the dashboard if the attempt to access the index '/' route.

So, let's see how this middleware is imported and implement in the index route.

middleware/index.js
`
const express = require('express')
const router = express.Router()
const Story = require('../models/Story')

const {ensureAuth, ensureGuest} = require('../middleware/auth')

/ @desc Login/Landiing page
// @route GET /

router.get('/', ensureGuest, (req, res) => {
res.render('login', {
layout: 'login',
})
})

// @desc Dshboard
// @route GET /dashboard

router.get('/dashboard', ensureAuth, async (req, res) => {
try {
const stories = await Story.find({user: req.user.id}).lean()
res.render('dashboard',{
name: req.user.firstName,
stories
})
} catch (error) {
console.error(error)
res.render(error/500)
}

})

module.exports = router
`

Thus from the code snippet above, we can see how the import the middleware by de-structuring, and how we implement the middleware function as seond arguments in the route.get function. This is how we implement a middleware function my friend, which ensures that only certain users have access to certain routes. Happy hacking my friends and check out the repo below for reference : https://github.com/amaboh/whisperApp

Top comments (0)