Skip to content

Commit 4bdeac3

Browse files
committed
first commit
0 parents  commit 4bdeac3

16 files changed

+509
-0
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
package-lock.json

Diff for: README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Node.js – JWT Authentication & Authorization example with JSONWebToken & Sequelize
2+
3+
For more detail, please visit:
4+
> [Node.js JWT Authentication & Authorization example](https://bezkoder.com/node-js-jwt-authentication-mysql/)
5+
6+
> [Deploying/Hosting Node.js app on Heroku with MySQL database](https://bezkoder.com/deploy-node-js-app-heroku-cleardb-mysql/)
7+
8+
Working with Front-end:
9+
> [Vue.js JWT Authentication with Vuex and Vue Router](https://bezkoder.com/jwt-vue-vuex-authentication/)
10+
11+
> [Angular 8 JWT Authentication with HttpInterceptor and Router](https://bezkoder.com/angular-jwt-authentication/)
12+
13+
> [React JWT Authentication (without Redux) example](https://bezkoder.com/react-jwt-auth/)
14+
15+
## Project setup
16+
```
17+
npm install
18+
```
19+
20+
### Run
21+
```
22+
node server.js
23+
```

Diff for: app/config/auth.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
secret: "bezkoder-secret-key"
3+
};

Diff for: app/config/db.config.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = {
2+
HOST: "localhost",
3+
USER: "root",
4+
PASSWORD: "123456",
5+
DB: "testdb",
6+
dialect: "mysql",
7+
pool: {
8+
max: 5,
9+
min: 0,
10+
acquire: 30000,
11+
idle: 10000
12+
}
13+
};

Diff for: app/controllers/auth.controller.js

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
const db = require("../models");
2+
const config = require("../config/auth.config");
3+
const User = db.user;
4+
const Role = db.role;
5+
6+
const Op = db.Sequelize.Op;
7+
8+
var jwt = require("jsonwebtoken");
9+
var bcrypt = require("bcryptjs");
10+
11+
exports.signup = (req, res) => {
12+
// Save User to Database
13+
User.create({
14+
username: req.body.username,
15+
email: req.body.email,
16+
password: bcrypt.hashSync(req.body.password, 8)
17+
})
18+
.then(user => {
19+
if (req.body.roles) {
20+
Role.findAll({
21+
where: {
22+
name: {
23+
[Op.or]: req.body.roles
24+
}
25+
}
26+
}).then(roles => {
27+
user.setRoles(roles).then(() => {
28+
res.send({ message: "User registered successfully!" });
29+
});
30+
});
31+
} else {
32+
// user role = 1
33+
user.setRoles([1]).then(() => {
34+
res.send({ message: "User registered successfully!" });
35+
});
36+
}
37+
})
38+
.catch(err => {
39+
res.status(500).send({ message: err.message });
40+
});
41+
};
42+
43+
exports.signin = (req, res) => {
44+
User.findOne({
45+
where: {
46+
username: req.body.username
47+
}
48+
})
49+
.then(user => {
50+
if (!user) {
51+
return res.status(404).send({ message: "User Not found." });
52+
}
53+
54+
var passwordIsValid = bcrypt.compareSync(
55+
req.body.password,
56+
user.password
57+
);
58+
59+
if (!passwordIsValid) {
60+
return res.status(401).send({
61+
accessToken: null,
62+
message: "Invalid Password!"
63+
});
64+
}
65+
66+
var token = jwt.sign({ id: user.id }, config.secret, {
67+
expiresIn: 86400 // 24 hours
68+
});
69+
70+
var authorities = [];
71+
user.getRoles().then(roles => {
72+
for (let i = 0; i < roles.length; i++) {
73+
authorities.push("ROLE_" + roles[i].name.toUpperCase());
74+
}
75+
res.status(200).send({
76+
id: user.id,
77+
username: user.username,
78+
email: user.email,
79+
roles: authorities,
80+
accessToken: token
81+
});
82+
});
83+
})
84+
.catch(err => {
85+
res.status(500).send({ message: err.message });
86+
});
87+
};

Diff for: app/controllers/user.controller.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
exports.allAccess = (req, res) => {
2+
res.status(200).send("Public Content.");
3+
};
4+
5+
exports.userBoard = (req, res) => {
6+
res.status(200).send("User Content.");
7+
};
8+
9+
exports.adminBoard = (req, res) => {
10+
res.status(200).send("Admin Content.");
11+
};
12+
13+
exports.moderatorBoard = (req, res) => {
14+
res.status(200).send("Moderator Content.");
15+
};

Diff for: app/middleware/authJwt.js

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const jwt = require("jsonwebtoken");
2+
const config = require("../config/auth.config.js");
3+
const db = require("../models");
4+
const User = db.user;
5+
6+
verifyToken = (req, res, next) => {
7+
let token = req.headers["x-access-token"];
8+
9+
if (!token) {
10+
return res.status(403).send({
11+
message: "No token provided!"
12+
});
13+
}
14+
15+
jwt.verify(token, config.secret, (err, decoded) => {
16+
if (err) {
17+
return res.status(401).send({
18+
message: "Unauthorized!"
19+
});
20+
}
21+
req.userId = decoded.id;
22+
next();
23+
});
24+
};
25+
26+
isAdmin = (req, res, next) => {
27+
User.findByPk(req.userId).then(user => {
28+
user.getRoles().then(roles => {
29+
for (let i = 0; i < roles.length; i++) {
30+
if (roles[i].name === "admin") {
31+
next();
32+
return;
33+
}
34+
}
35+
36+
res.status(403).send({
37+
message: "Require Admin Role!"
38+
});
39+
return;
40+
});
41+
});
42+
};
43+
44+
isModerator = (req, res, next) => {
45+
User.findByPk(req.userId).then(user => {
46+
user.getRoles().then(roles => {
47+
for (let i = 0; i < roles.length; i++) {
48+
if (roles[i].name === "moderator") {
49+
next();
50+
return;
51+
}
52+
}
53+
54+
res.status(403).send({
55+
message: "Require Moderator Role!"
56+
});
57+
});
58+
});
59+
};
60+
61+
isModeratorOrAdmin = (req, res, next) => {
62+
User.findByPk(req.userId).then(user => {
63+
user.getRoles().then(roles => {
64+
for (let i = 0; i < roles.length; i++) {
65+
if (roles[i].name === "moderator") {
66+
next();
67+
return;
68+
}
69+
70+
if (roles[i].name === "admin") {
71+
next();
72+
return;
73+
}
74+
}
75+
76+
res.status(403).send({
77+
message: "Require Moderator or Admin Role!"
78+
});
79+
});
80+
});
81+
};
82+
83+
const authJwt = {
84+
verifyToken: verifyToken,
85+
isAdmin: isAdmin,
86+
isModerator: isModerator,
87+
isModeratorOrAdmin: isModeratorOrAdmin
88+
};
89+
module.exports = authJwt;

Diff for: app/middleware/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const authJwt = require("./authJwt");
2+
const verifySignUp = require("./verifySignUp");
3+
4+
module.exports = {
5+
authJwt,
6+
verifySignUp
7+
};

Diff for: app/middleware/verifySignUp.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const db = require("../models");
2+
const ROLES = db.ROLES;
3+
const User = db.user;
4+
5+
checkDuplicateUsernameOrEmail = (req, res, next) => {
6+
// Username
7+
User.findOne({
8+
where: {
9+
username: req.body.username
10+
}
11+
}).then(user => {
12+
if (user) {
13+
res.status(400).send({
14+
message: "Failed! Username is already in use!"
15+
});
16+
return;
17+
}
18+
19+
// Email
20+
User.findOne({
21+
where: {
22+
email: req.body.email
23+
}
24+
}).then(user => {
25+
if (user) {
26+
res.status(400).send({
27+
message: "Failed! Email is already in use!"
28+
});
29+
return;
30+
}
31+
32+
next();
33+
});
34+
});
35+
};
36+
37+
checkRolesExisted = (req, res, next) => {
38+
if (req.body.roles) {
39+
for (let i = 0; i < req.body.roles.length; i++) {
40+
if (!ROLES.includes(req.body.roles[i])) {
41+
res.status(400).send({
42+
message: "Failed! Role does not exist = " + req.body.roles[i]
43+
});
44+
return;
45+
}
46+
}
47+
}
48+
49+
next();
50+
};
51+
52+
const verifySignUp = {
53+
checkDuplicateUsernameOrEmail: checkDuplicateUsernameOrEmail,
54+
checkRolesExisted: checkRolesExisted
55+
};
56+
57+
module.exports = verifySignUp;

Diff for: app/models/index.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const config = require("../config/db.config.js");
2+
3+
const Sequelize = require("sequelize");
4+
const sequelize = new Sequelize(
5+
config.DB,
6+
config.USER,
7+
config.PASSWORD,
8+
{
9+
host: config.HOST,
10+
dialect: config.dialect,
11+
operatorsAliases: false,
12+
13+
pool: {
14+
max: config.pool.max,
15+
min: config.pool.min,
16+
acquire: config.pool.acquire,
17+
idle: config.pool.idle
18+
}
19+
}
20+
);
21+
22+
const db = {};
23+
24+
db.Sequelize = Sequelize;
25+
db.sequelize = sequelize;
26+
27+
db.user = require("../models/user.model.js")(sequelize, Sequelize);
28+
db.role = require("../models/role.model.js")(sequelize, Sequelize);
29+
30+
db.role.belongsToMany(db.user, {
31+
through: "user_roles",
32+
foreignKey: "roleId",
33+
otherKey: "userId"
34+
});
35+
db.user.belongsToMany(db.role, {
36+
through: "user_roles",
37+
foreignKey: "userId",
38+
otherKey: "roleId"
39+
});
40+
41+
db.ROLES = ["user", "admin", "moderator"];
42+
43+
module.exports = db;

Diff for: app/models/role.model.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = (sequelize, Sequelize) => {
2+
const Role = sequelize.define("roles", {
3+
id: {
4+
type: Sequelize.INTEGER,
5+
primaryKey: true
6+
},
7+
name: {
8+
type: Sequelize.STRING
9+
}
10+
});
11+
12+
return Role;
13+
};

Diff for: app/models/user.model.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = (sequelize, Sequelize) => {
2+
const User = sequelize.define("users", {
3+
username: {
4+
type: Sequelize.STRING
5+
},
6+
email: {
7+
type: Sequelize.STRING
8+
},
9+
password: {
10+
type: Sequelize.STRING
11+
}
12+
});
13+
14+
return User;
15+
};

0 commit comments

Comments
 (0)