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.
Nội Dung Chính
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
npminstall
express--save
2
npminstall
sequelize--save
3
npminstall
sequelize--save
4
npminstall
mysql--save
5
npminstall
passport--save
6
npminstall
passport-local--save
7
npminstall
express-session--save
8
npminstall
bcryptjs--save
9
npminstall
express-handlebars--save
10
npminstall
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
npminstall
--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
:
{
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 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 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
:
'
'
,
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
,
,
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
:
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
:
,
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
:
'
'
,
9
passwordField
:
'
password
'
,
10
passReqToCallback
:
true
// allows us to pass back the entire request to the callback
11
},
12
function
(
req
,
,
password
,
done
)
{
13
var
generateHash
=
function
(
password
)
{
14
return
bCrypt
.
hashSync
(
password
,
bCrypt
.
genSaltSync
(
8
),
null
);
15
};
16
User
.
findOne
({
17
where
:
{
18
:
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
:
,
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 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
:
'
'
,
6
passwordField
:
'
password
'
,
7
passReqToCallback
:
true
// allows us to pass back the entire request to the callback
8
},
9
function
(
req
,
,
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
:
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.