Node.js Basics — Add Authentication to an Express App with Passport

John Au-Yeung - Jan 22 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Node.js is a popular runtime platform to create programs that run on it.

It lets us run JavaScript outside the browser.

In this article, we’ll look at how to start using Node.js to create programs.

Authentication

In the real world, many HTTP requests can only be made when the user is authenticated.

We can do this easily in a Node.js app.

To make our lives easier, we use the Express web framework to create our HTTP server instead of using the built-in http module.

We also need passport and passport-local to let us add authentication and the body-parser package to parse request bodies.

To install all the packages, we run:

npm install express body-parser passport passport-local
Enter fullscreen mode Exit fullscreen mode

Then we can write the following code to add authentication with passport :

const express = require('express');
const bodyParser = require('body-parser');
const Passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const users = {
  foo: {
    username: 'foo',
    password: 'bar',
    id: 1
  },
  bar: {
    username: 'bar',
    password: 'foo',
    id: 2
  }
}

const localStrategy = new LocalStrategy({
    usernameField: 'username',
    passwordField: 'password'
  },
  function(username, password, done) {
    user = users[username];
    if (user === undefined) {
      return done(null, false, {
        message: 'Invalid user'
      });
    }
    if (user.password !== password) {
      return done(null, false, {
        message: 'Invalid password'
      });
    }
    done(null, user);
  })

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));

app.use(express.static('public'));
app.use(Passport.initialize());
Passport.use('local', localStrategy);

app.get('/', (req, res) => {
  res.sendFile('public/index.html');
});

app.post(
  '/login',
  Passport.authenticate('local', {
    session: false
  }),
  function(request, response) {
    response.send('User Id ' + request.user.id);
  }
);

app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

We require the passport and passport-local packages.

Then we use the LocalStrategy constructor to create our authentication mechanism.

The userField and passwordField are set to the properties of the objects in the users object so that we can get the properties for the username and password.

Then in the function we passed into the 2nd argument of LocalStrategy , we check the user and check the password.

The done fucntion is called to let us return the response message we want depending on the validity of the username or password.

The last done call is run when both the username and password are valid.

Then we call Passport.use to create the 'local' authentication strategy so that we can use the code above with the Passport.authenticate function.

Then we can get the data for the authenticated user with the request.user property.

The data is obtained from calling:

done(null, user);
Enter fullscreen mode Exit fullscreen mode

Now when we make a POST request to the /login route with the request body:

{
    "username": "foo",
    "password": "bar"
}
Enter fullscreen mode Exit fullscreen mode

Then we get:

User Id 1
Enter fullscreen mode Exit fullscreen mode

returned from the server.

If we have a username and password combination that isn’t in the users object, then we get an Unauthorized response body and a 401 status code.

Conclusion

To make adding authentication to our code easier, we can use Passport to let us add the middleware to add basic authentication easier.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .