[authentication] how to implement login auth in node.js

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 .

This question is related to authentication node.js login

The answer is


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.


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
    }
})

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.


@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)

_x000D_
_x000D_
======authorization====== MIDDLEWARE_x000D_
_x000D_
const jwt = require('../helpers/jwt')_x000D_
const User = require('../models/user')_x000D_
_x000D_
module.exports = {_x000D_
  authentication: function(req, res, next) {_x000D_
    try {_x000D_
      const user = jwt.verifyToken(req.headers.token, process.env.JWT_KEY)_x000D_
      User.findOne({ email: user.email }).then(result => {_x000D_
        if (result) {_x000D_
          req.body.user = result_x000D_
          req.params.user = result_x000D_
          next()_x000D_
        } else {_x000D_
          throw new Error('User not found')_x000D_
        }_x000D_
      })_x000D_
    } catch (error) {_x000D_
      console.log('langsung dia masuk sini')_x000D_
_x000D_
      next(error)_x000D_
    }_x000D_
  },_x000D_
_x000D_
  adminOnly: function(req, res, next) {_x000D_
    let loginUser = req.body.user_x000D_
    if (loginUser && loginUser.role === 'admin') {_x000D_
      next()_x000D_
    } else {_x000D_
      next(new Error('Not Authorized'))_x000D_
    }_x000D_
  }_x000D_
}_x000D_
_x000D_
====error handler==== MIDDLEWARE_x000D_
const errorHelper = require('../helpers/errorHandling')_x000D_
_x000D_
module.exports = function(err, req, res, next) {_x000D_
  //   console.log(err)_x000D_
  let errorToSend = errorHelper(err)_x000D_
  // console.log(errorToSend)_x000D_
  res.status(errorToSend.statusCode).json(errorToSend)_x000D_
}_x000D_
_x000D_
_x000D_
====error handling==== HELPER_x000D_
var nodeError = ["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]_x000D_
var mongooseError = ["MongooseError","DisconnectedError","DivergentArrayError","MissingSchemaError","DocumentNotFoundError","MissingSchemaError","ObjectExpectedError","ObjectParameterError","OverwriteModelError","ParallelSaveError","StrictModeError","VersionError"]_x000D_
var mongooseErrorFromClient = ["CastError","ValidatorError","ValidationError"];_x000D_
var jwtError = ["TokenExpiredError","JsonWebTokenError","NotBeforeError"]_x000D_
_x000D_
function nodeErrorMessage(message){_x000D_
    switch(message){_x000D_
        case "Token is undefined":{_x000D_
            return 403;_x000D_
        }_x000D_
        case "User not found":{_x000D_
            return 403;_x000D_
        }_x000D_
        case "Not Authorized":{_x000D_
            return 401;_x000D_
        }_x000D_
        case "Email is Invalid!":{_x000D_
            return 400;_x000D_
        }_x000D_
        case "Password is Invalid!":{_x000D_
            return 400;_x000D_
        }_x000D_
        case "Incorrect password for register as admin":{_x000D_
            return 400;_x000D_
        }_x000D_
        case "Item id not found":{_x000D_
            return 400;_x000D_
        }_x000D_
        case "Email or Password is invalid": {_x000D_
            return 400_x000D_
        }_x000D_
        default :{_x000D_
            return 500;_x000D_
        }_x000D_
    }_x000D_
}_x000D_
_x000D_
module.exports = function(errorObject){_x000D_
    // console.log("===ERROR OBJECT===")_x000D_
    // console.log(errorObject)_x000D_
    // console.log("===ERROR STACK===")_x000D_
    // console.log(errorObject.stack);_x000D_
_x000D_
    let statusCode = 500;  _x000D_
    let returnObj = {_x000D_
        error : errorObject_x000D_
    }_x000D_
    if(jwtError.includes(errorObject.name)){_x000D_
        statusCode = 403;_x000D_
        returnObj.message = "Token is Invalid"_x000D_
        returnObj.source = "jwt"_x000D_
    }_x000D_
    else if(nodeError.includes(errorObject.name)){_x000D_
        returnObj.error = JSON.parse(JSON.stringify(errorObject, ["message", "arguments", "type", "name"]))_x000D_
        returnObj.source = "node";_x000D_
        statusCode = nodeErrorMessage(errorObject.message);_x000D_
        returnObj.message = errorObject.message;_x000D_
    }else if(mongooseError.includes(errorObject.name)){_x000D_
        returnObj.source = "database"_x000D_
        returnObj.message = "Error from server"_x000D_
    }else if(mongooseErrorFromClient.includes(errorObject.name)){_x000D_
        returnObj.source = "database";_x000D_
        errorObject.message ? returnObj.message = errorObject.message : returnObj.message = "Bad Request"_x000D_
        statusCode = 400;_x000D_
    }else{_x000D_
        returnObj.source = "unknown error";_x000D_
        returnObj.message = "Something error";_x000D_
    }_x000D_
    returnObj.statusCode = statusCode;_x000D_
    _x000D_
    return returnObj;_x000D_
_x000D_
_x000D_
}_x000D_
_x000D_
_x000D_
===jwt====_x000D_
const jwt = require('jsonwebtoken')_x000D_
_x000D_
function generateToken(payload) {_x000D_
    let token = jwt.sign(payload, process.env.JWT_KEY)_x000D_
    return token_x000D_
}_x000D_
_x000D_
function verifyToken(token) {_x000D_
    let payload = jwt.verify(token, process.env.JWT_KEY)_x000D_
    return payload_x000D_
}_x000D_
_x000D_
module.exports = {_x000D_
    generateToken, verifyToken_x000D_
}_x000D_
_x000D_
===router index===_x000D_
const express = require('express')_x000D_
const router = express.Router()_x000D_
_x000D_
// router.get('/', )_x000D_
router.use('/users', require('./users'))_x000D_
router.use('/products', require('./product'))_x000D_
router.use('/transactions', require('./transaction'))_x000D_
_x000D_
module.exports = router_x000D_
_x000D_
====router user ====_x000D_
const express = require('express')_x000D_
const router = express.Router()_x000D_
const User = require('../controllers/userController')_x000D_
const auth = require('../middlewares/auth')_x000D_
_x000D_
/* GET users listing. */_x000D_
router.post('/register', User.register)_x000D_
router.post('/login', User.login)_x000D_
router.get('/', auth.authentication, User.getUser)_x000D_
router.post('/logout', auth.authentication, User.logout)_x000D_
module.exports = router_x000D_
_x000D_
_x000D_
====app====_x000D_
require('dotenv').config()_x000D_
const express = require('express')_x000D_
const cookieParser = require('cookie-parser')_x000D_
const logger = require('morgan')_x000D_
const cors = require('cors')_x000D_
const indexRouter = require('./routes/index')_x000D_
const errorHandler = require('./middlewares/errorHandler')_x000D_
const mongoose = require('mongoose')_x000D_
const app = express()_x000D_
_x000D_
mongoose.connect(process.env.DB_URI, {_x000D_
  useNewUrlParser: true,_x000D_
  useUnifiedTopology: true,_x000D_
  useCreateIndex: true,_x000D_
  useFindAndModify: false_x000D_
})_x000D_
_x000D_
app.use(cors())_x000D_
app.use(logger('dev'))_x000D_
app.use(express.json())_x000D_
app.use(express.urlencoded({ extended: false }))_x000D_
app.use(cookieParser())_x000D_
_x000D_
app.use('/', indexRouter)_x000D_
app.use(errorHandler)_x000D_
_x000D_
module.exports = app
_x000D_
_x000D_
_x000D_


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!


Examples related to authentication

Set cookies for cross origin requests How Spring Security Filter Chain works What are the main differences between JWT and OAuth authentication? http post - how to send Authorization header? ASP.NET Core Web API Authentication Token based authentication in Web API without any user interface Custom Authentication in ASP.Net-Core Basic Authentication Using JavaScript Adding ASP.NET MVC5 Identity Authentication to an existing project LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1

Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`

Examples related to login

How to center a component in Material-UI and make it responsive? SQLSTATE[HY000] [1698] Access denied for user 'root'@'localhost' Angular redirect to login page Swift add icon/image in UITextField SQL Server : login success but "The database [dbName] is not accessible. (ObjectExplorer)" vagrant login as root by default Node.js https pem error: routines:PEM_read_bio:no start line EditText underline below text property Given URL is not allowed by the Application configuration Facebook application error how to get login option for phpmyadmin in xampp