how to implement login auth in node.js

Authenticationnode.jsLogin

Authentication Problem Overview


I have this node server running :

var server=http.createServer(function(request, responsehttp) {
	if (request.method == 'POST') {
		var body = '';
		request.on('data', function (data) {
			body += data;
		});
		request.on('end', function () {
			var POST = qs.parse(body);
			processquery(POST, request, responsehttp);
		});
	} else {
		var url_parts = url.parse(request.url, true);
		var query = url_parts.query;
		console.log(query);
		processquery(query, request, responsehttp);
	}
});

I want to add login form for this server .so when user is authenticated then it will show .

   function processquery(query, request, responsehttp){
	var returnResult = function (data){
		responsehttp.end(JSON.stringify(data));
	};
	
	if (!query.command) {
		fileprocess(request, responsehttp);
	}
	responsehttp.writeHead(200, {"Content-Type": "application/json"});
	switch(query.command) {
	    case 'logout':
		    logout(query, returnResult);
		    break;
	    case 'login':
		    login(query, returnResult);
		    break;
    }    
}

in process query function returning the files to client if any command is not given , so i can send the login command from client to server , but what server should do when it recieve the login command with username password , how it should hand the login request and return the login sucess or failure, for writing this part i need help .

what i tried .

function login(request, callback) {
	if(request.username==users[request.username] && request.password==users[request.username].password) {
		users[request.username].auth=true;
		var data = {result:'success','message':'login successful'};
		callback(data);
	} else {
		var data = {result:'error','message':'login incorrect'};
		callback(data);
	}
}

Please suggest how can i add session in this i tried adding , request variable in login function and tried setting request.session variable it says request.session is undefined .

Please suggest how can i write this login module which can maintain login authentication properly for every user .

Authentication Solutions


Solution 1 - Authentication

Here's how I do it with Express.js:

  1. Check if the user is authenticated: I have a middleware function named CheckAuth which I use on every route that needs the user to be authenticated:

    function checkAuth(req, res, next) { if (!req.session.user_id) { res.send('You are not authorized to view this page'); } else { next(); } }

I use this function in my routes like this:

app.get('/my_secret_page', checkAuth, function (req, res) {
  res.send('if you are viewing this page it means you are logged in');
});

2) The login route:

app.post('/login', function (req, res) {
  var post = req.body;
  if (post.user === 'john' && post.password === 'johnspassword') {
    req.session.user_id = johns_user_id_here;
    res.redirect('/my_secret_page');
  } else {
    res.send('Bad user/pass');
  }
});

3) The logout route:

app.get('/logout', function (req, res) {
  delete req.session.user_id;
  res.redirect('/login');
});      

If you want to learn more about Express.js check their site here: expressjs.com/en/guide/routing.html If there's need for more complex stuff, checkout everyauth (it has a lot of auth methods available, for facebook, twitter etc; good tutorial on it here).

Solution 2 - Authentication

Actually this is not really the answer of the question, but this is a better way to do it.

I suggest you to use connect/express as http server, since they save you a lot of time. You obviously don't want to reinvent the wheel. In your case session management is much easier with connect/express.

Beside that for authentication I suggest you to use everyauth. Which supports a lot of authentication strategies. Awesome for rapid development.

All this can be easily down with some copy pasting from their documentation!

Solution 3 - Authentication

To add to Farid's pseudo-answer,

Consider using Passport.js over everyauth.

The answers to this question provide some insight to the differences.


There are plenty of benefits to offloading your user authentication to Google, Facebook or another website. If your application's requirements are such that you could use Passport as your sole authentication provider or alongside traditional login, it can make the experience easier for your users.

Solution 4 - Authentication

@alessioalex answer is a perfect demo for fresh node user. But anyway, it's hard to write checkAuth middleware into all routes except login, so it's better to move the checkAuth from every route to one entry with app.use. For example:

function checkAuth(req, res, next) {
  // if logined or it's login request, then go next route
  if (isLogin || (req.path === '/login' && req.method === 'POST')) {
    next()
  } else {
    res.send('Not logged in yet.')
  }
}

app.use('/', checkAuth)

Solution 5 - Authentication

I tried this answer and it didn't work for me. I am also a newbie on web development and took classes where i used mlab but i prefer parse which is why i had to look for the most suitable solution. Here is my own current solution using parse on expressJS.

1)Check if the user is authenticated: I have a middleware function named isLogginIn which I use on every route that needs the user to be authenticated:

 function isLoggedIn(req, res, next) {
 var currentUser = Parse.User.current();
 if (currentUser) {
     next()
 } else {
     res.send("you are not authorised");
 }
}

I use this function in my routes like this:

  app.get('/my_secret_page', isLoggedIn, function (req, res) 
  {
    res.send('if you are viewing this page it means you are logged in');
  });

2) The Login Route:

  // handling login logic
  app.post('/login', function(req, res) {
  Parse.User.enableUnsafeCurrentUser();
  Parse.User.logIn(req.body.username, req.body.password).then(function(user) {
    res.redirect('/books');
  }, function(error) {
    res.render('login', { flash: error.message });
  });
});

3) The logout route:

 // logic route
  app.get("/logout", function(req, res){
   Parse.User.logOut().then(() => {
    var currentUser = Parse.User.current();  // this will now be null
    });
        res.redirect('/login');
   });

This worked very well for me and i made complete reference to the documentation here https://docs.parseplatform.org/js/guide/#users

Thanks to @alessioalex for his answer. I have only updated with the latest practices.

Solution 6 - Authentication

======authorization====== MIDDLEWARE

const jwt = require('../helpers/jwt')
const User = require('../models/user')

module.exports = {
  authentication: function(req, res, next) {
    try {
      const user = jwt.verifyToken(req.headers.token, process.env.JWT_KEY)
      User.findOne({ email: user.email }).then(result => {
        if (result) {
          req.body.user = result
          req.params.user = result
          next()
        } else {
          throw new Error('User not found')
        }
      })
    } catch (error) {
      console.log('langsung dia masuk sini')

      next(error)
    }
  },

  adminOnly: function(req, res, next) {
    let loginUser = req.body.user
    if (loginUser && loginUser.role === 'admin') {
      next()
    } else {
      next(new Error('Not Authorized'))
    }
  }
}

====error handler==== MIDDLEWARE
const errorHelper = require('../helpers/errorHandling')

module.exports = function(err, req, res, next) {
  //   console.log(err)
  let errorToSend = errorHelper(err)
  // console.log(errorToSend)
  res.status(errorToSend.statusCode).json(errorToSend)
}


====error handling==== HELPER
var nodeError = ["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]
var mongooseError = ["MongooseError","DisconnectedError","DivergentArrayError","MissingSchemaError","DocumentNotFoundError","MissingSchemaError","ObjectExpectedError","ObjectParameterError","OverwriteModelError","ParallelSaveError","StrictModeError","VersionError"]
var mongooseErrorFromClient = ["CastError","ValidatorError","ValidationError"];
var jwtError = ["TokenExpiredError","JsonWebTokenError","NotBeforeError"]

function nodeErrorMessage(message){
    switch(message){
        case "Token is undefined":{
            return 403;
        }
        case "User not found":{
            return 403;
        }
        case "Not Authorized":{
            return 401;
        }
        case "Email is Invalid!":{
            return 400;
        }
        case "Password is Invalid!":{
            return 400;
        }
        case "Incorrect password for register as admin":{
            return 400;
        }
        case "Item id not found":{
            return 400;
        }
        case "Email or Password is invalid": {
            return 400
        }
        default :{
            return 500;
        }
    }
}

module.exports = function(errorObject){
    // console.log("===ERROR OBJECT===")
    // console.log(errorObject)
    // console.log("===ERROR STACK===")
    // console.log(errorObject.stack);

    let statusCode = 500;  
    let returnObj = {
        error : errorObject
    }
    if(jwtError.includes(errorObject.name)){
        statusCode = 403;
        returnObj.message = "Token is Invalid"
        returnObj.source = "jwt"
    }
    else if(nodeError.includes(errorObject.name)){
        returnObj.error = JSON.parse(JSON.stringify(errorObject, ["message", "arguments", "type", "name"]))
        returnObj.source = "node";
        statusCode = nodeErrorMessage(errorObject.message);
        returnObj.message = errorObject.message;
    }else if(mongooseError.includes(errorObject.name)){
        returnObj.source = "database"
        returnObj.message = "Error from server"
    }else if(mongooseErrorFromClient.includes(errorObject.name)){
        returnObj.source = "database";
        errorObject.message ? returnObj.message = errorObject.message : returnObj.message = "Bad Request"
        statusCode = 400;
    }else{
        returnObj.source = "unknown error";
        returnObj.message = "Something error";
    }
    returnObj.statusCode = statusCode;
    
    return returnObj;


}


===jwt====
const jwt = require('jsonwebtoken')

function generateToken(payload) {
    let token = jwt.sign(payload, process.env.JWT_KEY)
    return token
}

function verifyToken(token) {
    let payload = jwt.verify(token, process.env.JWT_KEY)
    return payload
}

module.exports = {
    generateToken, verifyToken
}

===router index===
const express = require('express')
const router = express.Router()

// router.get('/', )
router.use('/users', require('./users'))
router.use('/products', require('./product'))
router.use('/transactions', require('./transaction'))

module.exports = router

====router user ====
const express = require('express')
const router = express.Router()
const User = require('../controllers/userController')
const auth = require('../middlewares/auth')

/* GET users listing. */
router.post('/register', User.register)
router.post('/login', User.login)
router.get('/', auth.authentication, User.getUser)
router.post('/logout', auth.authentication, User.logout)
module.exports = router


====app====
require('dotenv').config()
const express = require('express')
const cookieParser = require('cookie-parser')
const logger = require('morgan')
const cors = require('cors')
const indexRouter = require('./routes/index')
const errorHandler = require('./middlewares/errorHandler')
const mongoose = require('mongoose')
const app = express()

mongoose.connect(process.env.DB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useCreateIndex: true,
  useFindAndModify: false
})

app.use(cors())
app.use(logger('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())

app.use('/', indexRouter)
app.use(errorHandler)

module.exports = app

Solution 7 - Authentication

Why not disecting a bare minimum authentication module?

SweetAuth

A lightweight, zero-configuration user authentication module which doesn't depend on a database.

https://www.npmjs.com/package/sweet-auth

It's simple as:

app.get('/private-page', (req, res) => {

    if (req.user.isAuthorized) {
        // user is logged in! send the requested page
        // you can access req.user.email
    }
    else {
        // user not logged in. redirect to login page
    }
})

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionXMenView Question on Stackoverflow
Solution 1 - AuthenticationalessioalexView Answer on Stackoverflow
Solution 2 - AuthenticationFarid Nouri NeshatView Answer on Stackoverflow
Solution 3 - AuthenticationLuke WillisView Answer on Stackoverflow
Solution 4 - AuthenticationafacatView Answer on Stackoverflow
Solution 5 - AuthenticationfelixView Answer on Stackoverflow
Solution 6 - Authenticationsemua bisaView Answer on Stackoverflow
Solution 7 - AuthenticationNaveenView Answer on Stackoverflow