« Previous Tutorial Next Tutorial »

When last we left off, we’d gotten Mongoose installed and built a simple data model, our User object, which we’ll be tying into our authentication system. We’re going to do some groundwork today in that area. We want to be careful here, because authentication is probably the thing you least want to screw up when building an app. An API bug that allows a user to accidentally double-add an album to their list is a problem. An API bug that allows a malicious user to obtain someone else’s login and nuke their account is a catastrophe!

That’s why we’re not going to home-roll this thing. It makes very little sense in the current era to build an entire authentication system up from scratch when so many of the various traps, problems, and gotchas that come with that endeavor have already been solved, repeatedly, by thousands of other developers. We’re going to use an existing module called Passport, and it’s going to help us keep things secure.

We won’t actually be able to create a user or log in just yet, because we haven’t built the API endpoints, but before we get to that point we’ll need to get Passport installed and integrated into our app. After that, in a separate tutorial, we’ll build the endpoints and test them. Later, when we start building our front-end, we’ll create login and register components in React.

So, let’s get going. We’re going to need a couple of different dependencies, so instead of yarn adding each of them, let’s edit package.json, add them there, and then do one yarn to install them. Your package.json should currently look like this:

{
  "name": "musiclist",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.18.2",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "ejs": "~2.5.7",
    "express": "~4.15.5",
    "mongoose": "5.0.4",
    "morgan": "~1.9.0",
    "serve-favicon": "~2.4.5"
  }
}

We want to add four total lines to that. The first goes under the “express” line (it’s good practice to keep things in alphabetical order). Here it is:

"express-session": "1.10.1",

This is a companion module that’ll help us manage user sessions across page and API requests. Now add three more modules under the “morgan” line Here they are:

"passport": "0.3.2",
"passport-local": "1.0.0",
"passport-local-mongoose": "4.0.0",

These three lines install Passport, which handles authentication of requests; Passport Local, which helps tie that authentication into Express; and Passport Local Mongoose, which simplifies talking to our database when logging in with a username and password.

OK, save the file and then open a terminal or command prompt. CD to your musiclist directory and type:

yarn

That’s it. Hit enter, and Yarn will run through your package.json and install any packages that it hasn’t already installed. That means the four we just added. Excellent. Now let’s tie them into Express. Open up /app.js and just below the line where we require mongoose (line 7, to be specific), add the following code:

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

This is bringing in Passport and also a “Strategy” constructor from Passport-Local, which is an approach for connecting Express to our authentication setup. Now find the big block of app.use lines starting on line 24. Right under the cookie parser bit on line 29, add the following:

app.use(require('express-session')({
  secret: 'any random string can go here',
  resave: false,
  saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());

These lines tell our app to use the Express Session middleware (with some configuration options), along with Passport, including Passport’s session management, which will partner up with Express Session. You probably noticed that “secret” line – seems important, right? It is. Your “secret” is used to create a hash with which session requests are “signed” so that the server knows they’re coming from the right place – ie: not a malicious, third-party attacker. Keeping such secrets in your github repo, even a private one, is a bad idea and before we go live I'll get you set up to avoid such problems. For now, it’s OK.

All right, find line 40, our API route, and underneath it add this code:

// Configure Passport
const User = require('./models/user');
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

Hey, look at that … we’re using our User model! However, in order for our user model to be, uh, used, we need to change it a bit. We’re done with app.js so save that file and open /models/user.js, then add the following code after the top two lines:

const passportLocalMongoose = require('passport-local-mongoose');

And the following after our model definition:

User.plugin(passportLocalMongoose);

Finally, remove this line entirely:

  password: string,

I know we just added it in the last tutorial, but we don't need it. I mistakenly thought Passport required it. My bad!

Giving us a file which looks like this:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');

const User = new Schema({
  username: String,
  firstName: String,
  lastName: String
});

User.plugin(passportLocalMongoose);

module.exports = mongoose.model('User', User);

All right, we’re done. Sort of. We’ve tied Passport into our app, but of course we haven’t actually done anything with it yet. That’ll require building out our API, and before that we need to talk about testing. We’ll do that in the next tutorial. For now, though, let’s check and make sure nothing’s broken. Head back to your terminal, and type:

Nodemon Yarn Start

Assuming your server starts with no errors, refresh localhost:3000 to make sure we still have our “Welcome to MusicList” text (and our goofy random number).

Whoops, no, we don’t. Well, maybe you do, but many of us don’t. Why? Because we don’t have MongoDB running, and we now have active database connections being made by our code, so when our app can’t connect to the server, it crashes and burns. Open a new command prompt or terminal window and start MongoDB up real quick (you can refer to our MongoDB tutorial for a reminder on how to do that, if you need it). Now, Nodemon won’t automatically restart our server here because we didn’t change code, but we can force it to restart by just typing “rs” in the terminal window.

Once restarted, refresh your MusicList page again, and this time it should display without crashing the server, which is always a plus. Awesome! You’re all set. See you in the next tutorial.

« Previous Tutorial Next Tutorial »