Basics of Authentication using Passport and JWT with Sequelize and MySQL Database

Hello there, welcome to my first medium post.

It so happened that I was looking for resources to guide me as a beginner with NodeJS, how I can implement JWT to authenticate a user using MySQL database with Sequelize. So after surfing the internet for a while, I was able to come across some useful resources like this and a bunch of others, I’m still new to back-end, so it was a bit stressful to combine all the pieces together.

I thought I should put together all these pieces, to help someone who is also struggling with it or would soon start to look for it just like I was.

Before we dive in, let’s explain what each of these technologies are.

Passport is authentication middleware for Node.js. extremely flexible and modular.

JSON Web Token (JWT) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

Sequelize is a promise-based Object Relational Mapping for Node.js.

Disclaimer: This post is introduction and is focused at someone that just want to see how these technologies work together.

You need to have Node.js installed on your computer and also Postman or any tool that can be used to test requests. All steps that would be shown here were performed on Windows OS.

We are going to create a simple project, very simple, just to see how to use the mentioned technologies together.

Let’s create our project directory

mkdir express-jwt-sequelize-mysql

That’s a funny name right?

Then

cd express-jwt-sequelize-mysql

Let’s get our package.json with default values,

npm init –y

Let’s set up our express server, to do that, we need to install some dependencies,

npm install --save express body-parser

By now, package.json should look like this:

Let’s create a file, index.js, with the following content to get the app running and run a simple page.

// index.jsconst express = require('express');
const bodyParser = require('body-parser');
const app = express();// parse application/json
app.use(bodyParser.json());
//parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// add a basic route
app.get('/', function(req, res) {
res.json({ message: 'Express is up!' });
});
// start the app
app.listen(3000, function() {
console.log(‘Express is running on port 3000’);
});

To start the app, we run the following on the command prompt,

node index.js

Actually, for development, I would recommend we use nodemon, this would always restart our app as soon as we make any change(s) to the file(s), so let’s install it and save it as a dev dependency.

npm install nodemon --save-dev

After then, we can run the app like so:

nodemon index.js

We can test our app using Postman by sending a GET request to http://localhost:3000. We also do this using our browser.

The result should look like so:

Image for post
Image for post

After then, we can now create our database and connect it to the app using Sequelize ORM.

Firstly, create a database, let’s call it users_db.

Then we can go ahead and install the some dependencies to facilitate connection to the database,

npm install --save sequelize mysql2

And then connect to the database

// parse application/jsonapp.use(bodyParser.json());//parse application/x-www-form-urlencodedapp.use(bodyParser.urlencoded({ extended: true }));const Sequelize = require(‘sequelize’);// initialize an instance of Sequelizeconst sequelize = new Sequelize({
database: ‘users_db’,
username: ‘root’,
password: ‘’,
dialect: ‘mysql’,
});
// check the databse connectionsequelize
.authenticate()
.then(() => console.log(‘Connection has been established successfully.’))
.catch(err => console.error(‘Unable to connect to the database:’, err));

If everything went well, when you check your console, you should see a message like “Connection has been established successfully.”

We then need to create a simple model for user, let’s modify our index.js file by adding the following after the code for database connection.

// create user modelconst User = sequelize.define(‘user’, {
name: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
},
});
// create table with user modelUser.sync()
.then(() => console.log(‘Oh yeah! User table created successfully’))
.catch(err => console.log(‘BTW, did you enter wrong database credentials?’));

By now, if the app is still running, we’ll see the message “Oh yeah! User table created successfully” on the console.

Now, let’s create some helper functions to help us retrieve/submit data to/from the database.

// create some helper functions to work on the databaseconst createUser = async ({ name, password }) => { 
return await User.create({ name, password });
};
const getAllUsers = async () => {
return await User.findAll();
};
const getUser = async obj => {
return await User.findOne({
where: obj,
});
};

At this point, we can add some more routes, so we can be able to add users to our table and also be able to fetch users list. Let’s add the routes first, and then test them with Postman.

// get all usersapp.get(‘/users’, function(req, res) {
getAllUsers().then(user => res.json(user));
});
// register route
app.post(‘/register’, function(req, res, next) {
const { name, password } = req.body;
createUser({ name, password }).then(user =>
res.json({ user, msg: ‘account created successfully’ })
);
});

Then we can test the register route, I’ll advise you encrypt your password before saving it to the database, you can do this using bcrypt or any other similar tools. That wasn’t shown here because the post was meant to be an introductory one but you can check that on your own. So, sending POST request to localhost:3000/register with body content of type raw JSON as shown below, notice the message indicating that the account has been created successfully.

Image for post
Image for post

And also GET request using users route like shown below, we can see that the user’s details are returned.

Image for post
Image for post

Authentication using Passport.js and JSON Web Tokens

Now, let’s setup our authentication using passport, we start by installing the necessary dependencies,

npm install passport jsonwebtoken passport-jwt --save

Then we can require the installed modules, let’s modify the top of index.js like so:

const express = require(‘express’);
const bodyParser = require(‘body-parser’);
const jwt = require('jsonwebtoken');
// import passport and passport-jwt modules
const passport = require(‘passport’);
const passportJWT = require(‘passport-jwt’);
// ExtractJwt to help extract the token
let ExtractJwt = passportJWT.ExtractJwt;
// JwtStrategy which is the strategy for the authentication
let JwtStrategy = passportJWT.Strategy;
let jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
jwtOptions.secretOrKey = ‘wowwow’;

passport.js works with the concept of strategies. They basically are a middleware function that a requests runs through before getting to the actual route. If your defined authentication strategy fails, which means that the callback will be called with an error that is not null or false as the second argument, the route will not be called, but an error 401 unauthorized response will be sent.

Let’s implement the jwt strategy by adding this below the above code,

// lets create our strategy for web token
let strategy = new JwtStrategy(jwtOptions, function(jwt_payload, next) {
console.log(‘payload received’, jwt_payload);
let user = getUser({ id: jwt_payload.id });
if (user) {
next(null, user);
} else {
next(null, false);
}
});
// use the strategy
passport.use(strategy);

Then we initialize passport by placing this below where we created our app,

app.use(passport.initialize());

Now, let’s create our login route using the helper function we created above,

// login routeapp.post(‘/login’, async function(req, res, next) { 
const { name, password } = req.body;
if (name && password) {
// we get the user with the name and save the resolved promise
returned
let user = await getUser({ name });
if (!user) {
res.status(401).json({ msg: ‘No such user found’, user });
}
if (user.password === password) {
// from now on we’ll identify the user by the id and the id is
// the only personalized value that goes into our token
let payload = { id: user.id };
let token = jwt.sign(payload, jwtOptions.secretOrKey);
res.json({ msg: ‘ok’, token: token });
} else {
res.status(401).json({ msg: ‘Password is incorrect’ });
}
}
});

Now, let’s test our login route with a user that is not registered, setting the http method to POST and type to raw JSON (application/json) we should get a response like so,

{
"msg": “No such user found”,
"user": null
}

And if we try with wrong password, we get this response,

{
"msg": "Password is incorrect"
}

Whereas the correct credentials would give us the following result,

Image for post
Image for post

The token in the response object can now be used for authorization, let’s say any request sent to a protected route cannot be allowed unless it has the token attached to it. We would demonstrate this next. First, let’s create a protected route,

// protected route
app.get('/protected', passport.authenticate('jwt', { session: false }), function(req, res) {
res.json({ msg: 'Congrats! You are seeing this because you are authorized'});
});

Then, we can test it by trying to access the protected route, we would receive a response of status 401 Unauthorized. As earlier mentioned, the token needs to be attached to the request, we can do this adding key Authorization to the headers with value “Bearer ” appended to the token we want to attach to the request. You can check the image below for clarity,

Image for post
Image for post

You can find the full code below. Was this helpful? If it was, please leave your review. You can also check the full project here.

I also built a boilerplate repository on top of this article which is enough to help you kick-start your project in the shortest time, you can check it out here https://github.com/emaitee/node-express-boilerplate. It contains additional features such as password encryption, user access level control, ES6 syntax etc.

DevC Kano

Medium Publication for Members of DevC Kano

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store