Using Passport With Sequelize and MySQL

Sequelize is a promise-based Node.js ORM. It can be used with PostgreSQL, MySQL, MariaDB, SQLite, and MSSQL. In this tutorial, we will be implementing authentication for users of a web app. And we will use Passport, the popular authentication middleware for Node, together with Sequelize and MySQL, to implement user registration and login.

Getting Started

Make sure you have the following installed on your machine:

  • Node
  • MySQL

For this tutorial, we will be using Node.js and the Express framework, so we go ahead and start installing what we need.

1.

 Generate a package.json File

Create a directory for your app. Inside this directory, run this from your terminal or command prompt:

1
 npm init

This initializes the npm dependency manager. This will present a series of prompts which we’ll quickly go through.

  • Type the name of your app without spaces for name.
  • Press Enter to use the default version.
  • Enter a description or leave it blank.
  • For entry point, type server.js.
  • You can press Enter to accept the default for the rest of the prompts.

2.

Install Dependencies

The major dependencies for this tutorial are:

  • Express
  • Sequelize
  • MySQL
  • Passport
  • Passport Local Strategy
  • Express Session
  • Bcryptjs
  • Express Handlebars for the views

To install them, from your terminal or command prompt, run the following one after another.

1
npm 

install

express

--save

2
npm 

install

sequelize

--save

3
npm 

install

sequelize

--save

4
npm 

install

mysql

--save

5
npm 

install

passport

--save

6
npm 

install

passport-local

--save

7
npm 

install

express-session

--save

8
npm 

install

bcryptjs

--save

9
npm 

install

express-handlebars

--save

10
npm 

install

mysql2

--save

If you’re using Git for this project, create a .gitignore file and add this line to it:

1
node_modules

3.

Set Up the App

In the root project directory, we will set up the application and create a new file called server.js. This will be the main file when you start the application.

Inside the server.js file, add the following code:

1

var

express

=

require

(

'

express

'

);

2

3

var

app

=

express

();

4

5

app

.

get

(

'

/

'

,

function

(

req

,

res

)

{

6
    

res

.

send

(

'

Welcome to Passport with Sequelize

'

);

7

});

8

9

app

.

listen

(

5000

,

function

(

err

)

{

10
    

if

(

!

err

)

11
        

console

.

log

(

"

Site is live

"

);

12
    

else

console

.

log

(

err

)

13

});

The first line assigns the express module to a variable express. We then initialize express and then assign it to the variable app.

Then we make the app listen on port 5000. You can choose any free port number on your computer.

Next, we call the app.get() express routing function to respond with “Welcome to Passport with Sequelize” when a GET request is made to /.

We can run the server we just created on our computer with the following command:

1
node server.js

If you see the text Welcome to Passport with Sequelize when you visit http://localhost:5000/, then congratulations! Otherwise, check that you have done everything exactly as it is written above.

Next, we import some modules we need, like passport and express-session.

After the snippet var app = express(), we add the following lines:

1

var

passport

=

require

(

'

passport

'

);

2

var

session

=

require

(

'

express-session

'

);

In these two lines, we import the passport module and the express-session module and assign them to variables. The passport and express-session modules are needed to handle authentication.

We need a module that extracts the entire body of an incoming request and exposes it in a format that is easier to work with. In this case, we will use the JSON format. Prior to recent versions of express, you needed to use the body-parser module, but with express versions 4.16+, express has a built-in middleware function that parses incoming requests with JSON payloads and is based on body-parser.

To let our app use the express built-in body parser, we add these lines below the import lines, leaving some space between them:

1

app

.

use

(

express

.

urlencoded

({

2
        

extended

:

true

3
        

})

4
    

);

5

app

.

use

(

express

.

json

());

Next, we initialize passport and the express session and passport session and add them both as middleware. We do this by adding these lines after the import line above, again leaving some space.

1

// For Passport

2
    

app

.

use

(

session

({

3
        

secret

:

'

keyboard cat

'

,

4
        

resave

:

true

,

5
        

saveUninitialized

:

true

6
        

}));

// session secret

7
    

app

.

use

(

passport

.

initialize

());

8

app

.

use

(

passport

.

session

());

// persistent login sessions

4.

Create the Authentication Flow

We will begin to work on the actual authentication now. We’ll do this in four steps:

  • Set up Sequelize with MySQL.
  • Create the user model.
  • Set up views.
  • Write a passport strategy.

Step 1: Set Up Sequelize With MySQL

First, we create a database in MySQL. Give it your preferred name. For the sake of this tutorial, let’s create a database named sequelize_passport in MySQL. Then we set up the configuration to handle the DB details.

First, let’s import the dot-env module to handle environment variables. Run this in your root project folder:

1
npm 

install

--save

dotenv

Then we import it in the main server file, server.js, just below the other imports.

1

var

env

=

require

(

'

dotenv

'

).

config

();

Next, we create a file in our project root folder and name it .env, and if we’re using Git, add it to the .gitignore file.

After this, we add our environment to the .env file by adding this line:

NODE_ENV='development'

Then we create a config.json file which will be used by Sequelize to manage different environments.

The first thing to do is to create a folder in the root project directory named app, with a folder inside it named config. Inside the config folder, we create a config.json file. This file should be ignored if you are pushing to a repository. To do this, add the following code to your .gitignore:

1
app/config/config.json

Then, we paste the following code in our config.json file.

1
{
2
    "development": {
3
        "username": "root",
4
        "password": yourPasswordHere,
5
        "database": "sequelize_passport",
6
        "host": "127.0.0.1",
7
        "dialect": "mysql"
8
    },
9
    "test": {
10
        "username": "",
11
        "password": null,
12
        "database": "",
13
        "host": "",
14
        "dialect": "mysql"
15
    },
16
    "production": {
17
        "username": "",
18
        "password": null,
19
        "database": "",
20
        "host": "127.0.0.1",
21
        "dialect": "mysql"
22
    }
23
}

Remember to replace the values in the development block above with your database authentication details.

Now it’s time to create the models folder.

Inside the app folder, we create a new folder named models and create a new file named index.js in the models folder.

Inside the index.js file, we paste the code snippets below.

1

"

use strict

"

;

2

var

fs

=

require

(

"

fs

"

);

3

var

path

=

require

(

"

path

"

);

4

var

Sequelize

=

require

(

"

sequelize

"

);

5

var

env

=

process

.

env

.

NODE_ENV

||

"

development

"

;

6

var

config

=

require

(

path

.

join

(

__dirname

,

'

..

'

,

'

config

'

,

'

config.json

'

))[

env

];

7

var

sequelize

=

new

Sequelize

(

config

.

database

,

config

.

username

,

config

.

password

,

config

);

8

var

db

=

{};

9

fs

10
    

.

readdirSync

(

__dirname

)

11
    

.

filter

(

function

(

file

)

{

12
        

return

(

file

.

indexOf

(

"

.

"

)

!==

0

)

&&

(

file

!==

"

index.js

"

);

13
    

})

14
    

.

forEach

(

function

(

file

)

{

15
        

var

model

=

sequelize

.

import

(

path

.

join

(

__dirname

,

file

));

16
        

db

[

model

.

name

]

=

model

;

17
    

});

18

Object

.

keys

(

db

).

forEach

(

function

(

modelName

)

{

19
    

if

(

"

associate

"

in

db

[

modelName

])

{

20
        

db

[

modelName

].

associate

(

db

);

21
    

}

22

});

23

db

.

sequelize

=

sequelize

;

24

db

.

Sequelize

=

Sequelize

;

25

module

.

exports

=

db

;

This file is used to import all the models we place in the models folder and export them. To test that all is well, we add this in our server.js file.

1

//Models

2

var

models

=

require

(

"

./app/models

"

);

3

//Sync Database

4

models

.

sequelize

.

sync

().

then

(

function

()

{

5
    

console

.

log

(

'

Nice! Database looks fine

'

);

6

}).

catch

(

function

(

err

)

{

7
    

console

.

log

(

err

,

"

Something went wrong with the Database Update!

"

);

8

});

Here, we are importing the models and then calling the models.sequelize sync function. Run this to see if all is well:

1
node server.js

If you get the message “Site is live. Nice! Database looks fine“, then you have set up Sequelize successfully.

If not, please go carefully over the steps above and try to debug the issue with help.

Step 2: Create the User Model

The next thing we are going to do is create the user model, which is basically the user table. This will contain basic user information.

In our models folder, we create a file and name it user.js. The full path for this file should be app/models/user.js.

Open the user.js file and add the following code:

1

module

.

exports

=

function

(

sequelize

,

Sequelize

)

{

2
    

var

User

=

sequelize

.

define

(

'

user

'

,

{

3
        

id

:

{

4
            

autoIncrement

:

true

,

5
            

primaryKey

:

true

,

6
            

type

:

Sequelize

.

INTEGER

7
        

},

8
        

firstname

:

{

9
            

type

:

Sequelize

.

STRING

,

10
            

notEmpty

:

true

11
        

},

12
        

lastname

:

{

13
            

type

:

Sequelize

.

STRING

,

14
            

notEmpty

:

true

15
        

},

16
        

username

:

{

17
            

type

:

Sequelize

.

TEXT

18
        

},

19
        

about

:

{

20
            

type

:

Sequelize

.

TEXT

21
        

},

22
        

email

:

{

23
            

type

:

Sequelize

.

STRING

,

24
            

validate

:

{

25
                

isEmail

:

true

26
            

}

27
        

},

28
        

password

:

{

29
            

type

:

Sequelize

.

STRING

,

30
            

allowNull

:

false

31
        

},

32
        

last_login

:

{

33
            

type

:

Sequelize

.

DATE

34
        

},

35
        

status

:

{

36
            

type

:

Sequelize

.

ENUM

(

'

active

'

,

'

inactive

'

),

37
            

defaultValue

:

'

active

'

38
        

}

39
    

});

40
    

return

User

;

41

}

Now run:

1
node server.js

You should see the familiar “Site is live. Nice! Database looks fine” message. This means that our Sequelize models have been synced successfully, and if you check your database, you should see a users table with the columns specified.

Step 3: Set Up Views

In this section, we will set up the views for the client side. First, let’s create the view for signup and wire it up.

The first thing to do is import the express-handlebars module which will be used for views in this tutorial. Express HandleBars can be used to render data on the server-side as web pages to the client side.

Add this code snippet to the server.js file.

var exphbs = require('express-handlebars')

Your import block should look like this at this point.

1

var

express

=

require

(

'

express

'

);

2

var

app

=

express

();

3

var

passport

=

require

(

'

passport

'

);

4

var

session

=

require

(

'

express-session

'

);

5

var

env

=

require

(

'

dotenv

'

).

config

();

6

var

exphbs

=

require

(

'

express-handlebars

'

);

In order to use handlebars in express, we save the HTML codes with a .hbs extension in the views folder, which we’ll create soon in the root directory, as handlebars looks for the pages in the views folder.

Next, we add the following lines in our server.js file.

1

//For Handlebars

2

app

.

set

(

'

views

'

,

'

./app/views

'

);

3

app

.

engine

(

'

hbs

'

,

exphbs

.

engine

({

4
    

extname

:

'

.hbs

'

,

5
    

defaultLayout

:

false

,

6
    

layoutsDir

:

"

views/layouts/

"

7

}));

8

app

.

set

(

'

view engine

'

,

'

.hbs

'

);

Now, in our app folder, we create three folders named views, controllers, and routes.

In the views folder, we create a file named signup.hbs and paste in the code snippets below.

1

<!DOCTYPE html>

2

<html>

3

<head>

4
    

<title>

Sign up layout

</title>

5
    

<link

rel=

"stylesheet"

href=

"/styles.css"

>

6

</head>

7

<body>

8
    

<h2>

Passport With Sequelize and MySQL

</h2>

9
    

<form

id=

"signup"

name=

"signup"

method=

"post"

action=

"/signup"

>

10
        

<label

for=

"email"

>

Email Address:

</label>

11
        

<input

class=

"text"

name=

"email"

type=

"email"

/>

12
        

<label

for=

"firstname"

>

First Name:

</label>

13
        

<input

name=

"firstname"

type=

"text"

/>

14
        

<label

for=

"lastname"

>

Last Name:

</label>

15
        

<input

name=

"lastname"

type=

"text"

/>

16
        

<label

for=

"password"

>

Password:

</label>

17
        

<input

name=

"password"

type=

"password"

/>

18
        

<input

class=

"btn"

type=

"submit"

value=

"Sign Up"

/>

19
    

</form>

20

</body>

21

</html>

Then, in our controllers folder, we create a new file called authController.js.

In this file, we paste the following controller for the signup route, which we will create in a moment.

1

var

exports

=

module

.

exports

=

{};

2

exports

.

signup

=

function

(

req

,

res

)

{

3
    

res

.

render

(

'

signup

'

);

4

};

Next, we create a route for signup. In the routes folder, we create a new file named auth.js, and then, in this file, we import the authController file and define the signup route.

1

var

authController

=

require

(

'

../controllers/authController.js

'

);

2

module

.

exports

=

function

(

app

)

{

3
    

app

.

get

(

'

/signup

'

,

authController

.

signup

);

4

};

Now, we’ll import this route in our server.js and pass the app as an argument. In server.js, after the models import, add these lines:

1

//Routes

2

var

authRoute

=

require

(

'

./app/routes/auth.js

'

)(

app

);

Run this:

1
node server.js

Now, visit http://localhost:5000/signup, and you will see the signup form.

Sign-up LayoutSign-up LayoutSign-up Layout
Sign-up Layout

Let’s repeat the steps for the sign-in form. As before, we’ll create a file named signin.hbs in our views folder and paste the following HTML code in it:

1

<!DOCTYPE html>

2

<html>

3

<head>

4
    

<title>

Sign in Layout

</title>

5
    

<link

rel=

"stylesheet"

href=

"/styles.css"

>

6

</head>

7

<body>

8
    

<h2>

Passport With Sequelize and MySQL

</h2>

9
    

<form

id=

"signin"

name=

"signin"

method=

"post"

action=

"signin"

>

10
        

<label

for=

"email"

>

Email Address

</label>

11
        

<input

class=

"text"

name=

"email"

type=

"text"

/>

12
        

<label

for=

"password"

>

Password

</label>

13
        

<input

name=

"password"

type=

"password"

/>

14
        

<input

class=

"btn"

type=

"submit"

value=

"Sign In"

/>

15
    

</form>

16

</body>

17

</html>

Then, add a controller for the sign-in in app/controllers/authcontroller.js.

1

exports

.

signin

=

function

(

req

,

res

)

{

2
    

res

.

render

(

'

signin

'

);

3

};

Then, in app/routes/auth.js, we add a route for sign-in like this:

app.get('/signin', authController.signin);

Now, when you run:

1
 node server.js 

and visit http://localhost:5000/signin/, you should see the sign-in form.

Sign-in LayoutSign-in LayoutSign-in Layout
Sign-in Layout

The final and major step is writing our passport strategies.

Step 4: Write a Passport Strategy

In app/config, we create a new folder named passport.

Then, in our new folder app/config/passport, we create a new file and name it passport.js. This file will contain our passport strategies.

In passport.js, we will use the user model and passport.

First, we import bcryptjs, which we need to secure passwords.

var bCrypt = require('bcryptjs');

Then, we add a module.exports block like this:

1

module

.

exports

=

function

(

passport

,

user

)

{

2

}

Inside this block, we initialize the passport-local strategy and the user model, which will be passed as an argument. Here’s how we do this:

1

module

.

exports

=

function

(

passport

,

user

)

{

2
    

var

User

=

user

;

3
    

var

LocalStrategy

=

require

(

'

passport-local

'

).

Strategy

;

4

}

Then we define our custom strategy with our instance of the LocalStrategy like this:

1

passport

.

use

(

'

local-signup

'

,

new

LocalStrategy

(

2
    

{

3
        

usernameField

:

'

email

'

,

4
        

passwordField

:

'

password

'

,

5
        

passReqToCallback

:

true

// allows us to pass back the entire request to the callback

6
    

},

7

))

Now we have declared what request fields our usernameField and passwordField (passport variables) are.

The last variable passReqToCallback allows us to pass the entire request to the callback, which is particularly useful for signing up.

After the last comma, we add this callback function.

1
  

function

(

req

,

email

,

password

,

done

)

{

2

}

In this function, we will handle storing a user’s details.

First, we add our hashed password-generating function inside the callback function.

1
 

var

generateHash

=

function

(

password

)

{

2
     

return

bCrypt

.

hashSync

(

password

,

bCrypt

.

genSaltSync

(

8

),

null

);

3

};

Then, using the Sequelize user model we initialized earlier as User, we check to see if the user already exists, and if not, we add them.

1

User

.

findOne

({

2
    

where

:

{

3
        

email

:

email

4
    

}

5

}).

then

(

function

(

user

)

{

6
    

if

(

user

)

7
    

{

8
        

return

done

(

null

,

false

,

{

9
            

message

:

'

That email is already taken

'

10
        

});

11
    

}

else

12
    

{

13
        

var

userPassword

=

generateHash

(

password

);

14
        

var

data

=

15
            

{

16
                

email

:

email

,

17
                

password

:

userPassword

,

18
                

firstname

:

req

.

body

.

firstname

,

19
                

lastname

:

req

.

body

.

lastname

20
            

};

21
        

User

.

create

(

data

).

then

(

function

(

newUser

,

created

)

{

22
            

if

(

!

newUser

)

{

23
                

return

done

(

null

,

false

);

24
            

}

25
            

if

(

newUser

)

{

26
                

return

done

(

null

,

newUser

);

27
            

}

28
        

});

29
    

}

30

});

User.create() is a Sequelize method for adding new entries to the database. Notice that the values in the data object are obtained from the req.body object, which contains the input from our signup form.

Your passport.js should look like this:

1

//load bcrypt

2

var

bCrypt

=

require

(

'

bcryptjs

'

);

3

module

.

exports

=

function

(

passport

,

user

)

{

4
    

var

User

=

user

;

5
    

var

LocalStrategy

=

require

(

'

passport-local

'

).

Strategy

;

6
    

passport

.

use

(

'

local-signup

'

,

new

LocalStrategy

(

7
        

{

8
            

usernameField

:

'

email

'

,

9
            

passwordField

:

'

password

'

,

10
            

passReqToCallback

:

true

// allows us to pass back the entire request to the callback

11
        

},

12
        

function

(

req

,

email

,

password

,

done

)

{

13
            

var

generateHash

=

function

(

password

)

{

14
                

return

bCrypt

.

hashSync

(

password

,

bCrypt

.

genSaltSync

(

8

),

null

);

15
            

};

16
            

User

.

findOne

({

17
                

where

:

{

18
                    

email

:

email

19
                

}

20
            

}).

then

(

function

(

user

)

{

21
                

if

(

user

)

22
                

{

23
                    

return

done

(

null

,

false

,

{

24
                        

message

:

'

That email is already taken

'

25
                    

});

26
                

}

else

27
                

{

28
                    

var

userPassword

=

generateHash

(

password

);

29
                    

var

data

=

30
                        

{

31
                            

email

:

email

,

32
                            

password

:

userPassword

,

33
                            

firstname

:

req

.

body

.

firstname

,

34
                            

lastname

:

req

.

body

.

lastname

35
                        

};

36
                    

User

.

create

(

data

).

then

(

function

(

newUser

,

created

)

{

37
                        

if

(

!

newUser

)

{

38
                            

return

done

(

null

,

false

);

39
                        

}

40
                        

if

(

newUser

)

{

41
                            

return

done

(

null

,

newUser

);

42
                        

}

43
                    

});

44
                

}

45
            

});

46
        

}

47
    

));

48

}

Now we will import the strategy in server.js. To do this, we add these lines below the routes import.

1

//load passport strategies

2

require

(

'

./app/config/passport/passport.js

'

)(

passport

,

models

.

user

);

Your server.js should now look like this:

1

var

express

=

require

(

'

express

'

);

2

var

app

=

express

();

3

var

passport

=

require

(

'

passport

'

);

4

var

session

=

require

(

'

express-session

'

);

5

var

env

=

require

(

'

dotenv

'

).

config

();

6

var

exphbs

=

require

(

'

express-handlebars

'

);

7

app

.

use

(

express

.

urlencoded

({

8
    

extended

:

true

9

})

10

);

11

app

.

use

(

express

.

json

());

12

// For Passport

13

app

.

use

(

session

({

14
    

secret

:

'

keyboard cat

'

,

15
    

resave

:

true

,

16
    

saveUninitialized

:

true

17

}));

// session secret

18

app

.

use

(

passport

.

initialize

());

19

app

.

use

(

passport

.

session

());

// persistent login sessions

20

//For Handlebars

21

app

.

set

(

'

views

'

,

'

./app/views

'

);

22

app

.

engine

(

'

hbs

'

,

exphbs

.

engine

({

23
    

extname

:

'

.hbs

'

,

24
    

defaultLayout

:

false

,

25
    

layoutsDir

:

"

views/layouts/

"

26

}));

27

app

.

set

(

'

view engine

'

,

'

.hbs

'

);

28

app

.

get

(

'

/

'

,

function

(

req

,

res

)

{

29
    

res

.

send

(

'

Welcome to Passport with Sequelize

'

);

30

});

31

//Models

32

var

models

=

require

(

"

./app/models

"

);

33

//Routes

34

var

authRoute

=

require

(

'

./app/routes/auth.js

'

)(

app

);

35

//load passport strategies

36

require

(

'

./app/config/passport/passport.js

'

)(

passport

,

models

.

user

);

37

//Sync Database

38

models

.

sequelize

.

sync

().

then

(

function

()

{

39
    

console

.

log

(

'

Nice! Database looks fine

'

);

40

}).

catch

(

function

(

err

)

{

41
    

console

.

log

(

err

,

"

Something went wrong with the Database Update!

"

);

42

});

43

app

.

listen

(

5000

,

function

(

err

)

{

44
    

if

(

!

err

)

45
        

console

.

log

(

"

Site is live

"

);

46
    

else

console

.

log

(

err

);

47

});

Now we will actually apply the strategy to our /signup route. Here’s how we do that:

First, we go to app/routes/auth.js and add a route for posting to signup like this.

1

app

.

post

(

'

/signup

'

,

passport

.

authenticate

(

'

local-signup

'

,

{

2
        

successRedirect

:

'

/dashboard

'

,

3
        

failureRedirect

:

'

/signup

'

4
    

}

5

));

Since we need passport, we need to pass it to this method. We can import passport in this script or pass it from server.js. Let’s do the latter.

Modify the function exported in this file app/routes/auth.js to have passport as a parameter. The code in app/routes/auth.js should look like this after your modification.

1

var

authController

=

require

(

'

../controllers/authcontroller.js

'

);

2

module

.

exports

=

function

(

app

,

passport

)

{

3
    

app

.

get

(

'

/signup

'

,

authController

.

signup

);

4
    

app

.

get

(

'

/signin

'

,

authController

.

signin

);

5
    

app

.

post

(

'

/signup

'

,

passport

.

authenticate

(

'

local-signup

'

,

{

6
            

successRedirect

:

'

/dashboard

'

,

7
            

failureRedirect

:

'

/signup

'

8
        

}

9
    

));

10

};

Then, in server.js, we modify the routes import and add passport as an argument like this:

var authRoute = require('./app/routes/auth.js')(app,passport);

Now, go to the signup URL http://localhost:5000/signup/ and try to sign up.

When you try to sign up, you will get an error “Failed to serialize user into session“. This is because passport has to save a user ID in the session, and it uses this to manage retrieving the user details when needed.

To solve this, we are going to implement both the serialize and deserialize functions of passport in our app/config/passport/passport.js file.

First, we add the serialize function. In this function, we will be saving the user id to the session. To do this, we add the following lines below the initialization of the local strategy.

1

//serialize

2

passport

.

serializeUser

(

function

(

user

,

done

)

{

3
    

done

(

null

,

user

.

id

);

4

});

Next, we implement the deserialize function. Add the function just below the serialize function.

1

// deserialize user

2

passport

.

deserializeUser

(

function

(

id

,

done

)

{

3
        

User

.

findByPk

(

id

).

then

(

function

(

user

)

{

4
            

if

(

user

)

{

5
                

done

(

null

,

user

.

get

());

6
            

}

else

{

7
                

done

(

user

.

errors

,

null

);

8
            

}

9
        

});

10

});

In the deserialize function above, we use the Sequelize findByPk promise to get the user, and if successful, an instance of the Sequelize model is returned. To get the User object from this instance, we use the Sequelize getter function like this: user.get().

Now run again:

1
node server.js

And attempt to sign up. Hurray if you got the “Cannot GET /dashboard” message! It means our authentication was successful. Remember we redirected to /dashboard in our passport.authenticate method in routes/auth.js.

Now let’s go ahead and add that route. Then, add some middleware to make sure the page can only be accessed when a user is logged into the session.

In our app/views folder, we create a new file named dashboard.hbs and add the following HTML code in it.

1

<!DOCTYPE html>

2

<html>

3

<head>

4
    

<title>

Passport with Sequelize

</title>

5
    

<link

rel=

"stylesheet"

href=

"/styles.css"

>

6

</head>

7

<body>

8
    

<h2>

Dashboard

</h2>

9
    

<h5>

Hurray! you are logged in 🥳.

</h5>

10

</body>

11

</html>

In routes/auth.js, we add this line inside the module.exports block:

1

app

.

get

(

'

/dashboard

'

,

authController

.

dashboard

);

Next, we go to app/controllers/authController.js and add the dashboard controller.

1

exports

.

dashboard

=

function

(

req

,

res

)

{

2
    

res

.

render

(

'

dashboard

'

);

3

};

Your AuthController.js should look like this:

1

var

exports

=

module

.

exports

=

{}

2

exports

.

signup

=

function

(

req

,

res

)

{

3
    

res

.

render

(

'

signup

'

);

4

}

5

exports

.

signin

=

function

(

req

,

res

)

{

6
    

res

.

render

(

'

signin

'

);

7

}

8

exports

.

dashboard

=

function

(

req

,

res

)

{

9
    

res

.

render

(

'

dashboard

'

);

10

}

Now, run the app again, and try to sign up with a different email address from the one you used earlier. You’ll be appropriately redirected to the /dashboard route.

But /dashboard isn’t a protected route, which means even if a user is not logged in, they can see it. We don’t want this, so we’ll add a /logout route to log the user out, and then protect the route and test what we have done.

In routes/auth.js we add this line:

1

app

.

get

(

'

/logout

'

,

authController

.

logout

);

Then we add the controller in app/controllers/authController.js.

1
 

exports

.

logout

=

function

(

req

,

res

)

{

2
     

req

.

session

.

destroy

(

function

(

err

)

{

3
         

res

.

redirect

(

'

/

'

);

4
     

});

5

}

Now run the app again and sign up with a different email address.

After that, visit http://localhost:5000/logout to log the user out. Now visit http://localhost:5000/dashboard.

Dashboard LayoutDashboard LayoutDashboard Layout
Dashboard Layout

You’ll notice that it is quite accessible. Let’s add some custom middleware to protect that route.

To do this, we open app/routes/auth.js and add this function in the module.exports block, below all the other lines of code.

1

function

isLoggedIn

(

req

,

res

,

next

)

{

2
    

if

(

req

.

isAuthenticated

())

3
    
4
        

return

next

();

5
        
6
    

res

.

redirect

(

'

/signin

'

);

7

}

Then we modify the dashboard route handler to look like this:

1

app

.

get

(

'

/dashboard

'

,

isLoggedIn

,

authController

.

dashboard

);

Now, when you run the app again and try to visit the dashboard page and you are not logged in, you should be redirected to the sign-in page.

Whew! It is time to implement the final part: the sign-in.

First, we’ll add a new local strategy for sign-in in app/config/passport/passport.js.

1

//LOCAL SIGNIN

2

passport

.

use

(

'

local-signin

'

,

new

LocalStrategy

(

3
    

{

4
        

// by default, local strategy uses username and password, we will override with email

5
        

usernameField

:

'

email

'

,

6
        

passwordField

:

'

password

'

,

7
        

passReqToCallback

:

true

// allows us to pass back the entire request to the callback

8
    

},

9
    

function

(

req

,

email

,

password

,

done

)

{

10
        

var

User

=

user

;

11
        

var

isValidPassword

=

function

(

userpass

,

password

)

{

12
            

return

bCrypt

.

compareSync

(

password

,

userpass

);

13
        

}

14
        

User

.

findOne

({

15
            

where

:

{

16
                

email

:

email

17
            

}

18
        

}).

then

(

function

(

user

)

{

19
            

if

(

!

user

)

{

20
                

return

done

(

null

,

false

,

{

21
                    

message

:

'

Email does not exist

'

22
                

});

23
            

}

24
            

if

(

!

isValidPassword

(

user

.

password

,

password

))

{

25
                

return

done

(

null

,

false

,

{

26
                    

message

:

'

Incorrect password.

'

27
                

});

28
            

}

29
            

var

userinfo

=

user

.

get

();

30
            

return

done

(

null

,

userinfo

);

31
        

}).

catch

(

function

(

err

)

{

32
            

console

.

log

(

"

Error:

"

,

err

);

33
            

return

done

(

null

,

false

,

{

34
                

message

:

'

Something went wrong with your Signin

'

35
            

});

36
        

});

37
    

}

38

));

In this strategy, the isValidPassword function compares the password entered with the bCrypt comparison method since we stored our password with bcrypt. If the details are correct, our user will be signed in.

Now, go to routes/auth.js and add the route for posting to /signin.

1

app

.

post

(

'

/signin

'

,

passport

.

authenticate

(

'

local-signin

'

,

{

2
        

successRedirect

:

'

/dashboard

'

,

3
        

failureRedirect

:

'

/signin

'

4
    

}

5

));

Your routes/auth.js should look like this when you’re done.

1

var

authController

=

require

(

'

../controllers/authcontroller.js

'

);

2

module

.

exports

=

function

(

app

,

passport

)

{

3
    

app

.

get

(

'

/signup

'

,

authController

.

signup

);

4
    

app

.

get

(

'

/signin

'

,

authController

.

signin

);

5
    

app

.

post

(

'

/signup

'

,

passport

.

authenticate

(

'

local-signup

'

,

{

6
            

successRedirect

:

'

/dashboard

'

,

7
            

failureRedirect

:

'

/signup

'

8
        

}

9
    

));

10
    

app

.

get

(

'

/dashboard

'

,

isLoggedIn

,

authController

.

dashboard

);

11
    

app

.

get

(

'

/logout

'

,

authController

.

logout

);

12
    

app

.

post

(

'

/signin

'

,

passport

.

authenticate

(

'

local-signin

'

,

{

13
            

successRedirect

:

'

/dashboard

'

,

14
            

failureRedirect

:

'

/signin

'

15
        

}

16
    

));

17
    

function

isLoggedIn

(

req

,

res

,

next

)

{

18
        

if

(

req

.

isAuthenticated

())

19
            

return

next

();

20
        

res

.

redirect

(

'

/signin

'

);

21
    

}

22

}

Now run the app and try to sign in. You should be able to sign in with any of the details you used while signing up, and you’ll be directed to http://localhost:5000/dashboard/.

Congratulations if you made it to the end of this tutorial! We have successfully used Sequelize and Passport with a MySQL database.

In order to make our application a lot more appealing, we would add a bit of CSS styling. The codes for styling and the full code for this tutorial can be found on GitHub.

Conclusion

This concludes our tutorial on using Passport for authentication of users with Sequelize and MySQL. Sequelize is a really useful ORM for dealing with MySQL when using Node. I have personally found it to be very useful, and you should definitely consider using it in your next Node-MySQL app.

This post has been updated with contributions from Mary Okosun. Mary is a software developer based in Lagos, Nigeria, with expertise in Node.js, JavaScript, MySQL, and NoSQL technologies.