Skip to content

Commit 5daf790

Browse files
committed
Backend API Development Nodejs JWT Authentication Examples
1 parent 2a1b83e commit 5daf790

File tree

12 files changed

+1169
-0
lines changed

12 files changed

+1169
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
'secret': 'loizenai-super-secret-key',
3+
ROLEs: ['USER', 'ADMIN', 'PM']
4+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const env = require('./env.js');
2+
3+
const Sequelize = require('sequelize');
4+
const sequelize = new Sequelize(env.database, env.username, env.password, {
5+
host: env.host,
6+
dialect: env.dialect,
7+
operatorsAliases: false,
8+
9+
pool: {
10+
max: env.max,
11+
min: env.pool.min,
12+
acquire: env.pool.acquire,
13+
idle: env.pool.idle
14+
}
15+
});
16+
17+
const db = {};
18+
19+
db.Sequelize = Sequelize;
20+
db.sequelize = sequelize;
21+
22+
db.user = require('../model/user.model.js')(sequelize, Sequelize);
23+
db.role = require('../model/role.model.js')(sequelize, Sequelize);
24+
25+
db.role.belongsToMany(db.user, { through: 'user_roles', foreignKey: 'roleId', otherKey: 'userId'});
26+
db.user.belongsToMany(db.role, { through: 'user_roles', foreignKey: 'userId', otherKey: 'roleId'});
27+
28+
module.exports = db;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const env = {
2+
database: 'loizenaidb',
3+
username: 'root',
4+
password: '12345',
5+
host: 'localhost',
6+
dialect: 'mysql',
7+
pool: {
8+
max: 5,
9+
min: 0,
10+
acquire: 30000,
11+
idle: 10000
12+
}
13+
};
14+
15+
module.exports = env;
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
const db = require('../config/db.config.js');
2+
const config = require('../config/config.js');
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+
console.log("Processing func -> SignUp");
14+
15+
User.create({
16+
name: req.body.name,
17+
username: req.body.username,
18+
email: req.body.email,
19+
password: bcrypt.hashSync(req.body.password, 8)
20+
}).then(user => {
21+
Role.findAll({
22+
where: {
23+
name: {
24+
[Op.or]: req.body.roles
25+
}
26+
}
27+
}).then(roles => {
28+
user.setRoles(roles).then(() => {
29+
res.send("User registered successfully!");
30+
});
31+
}).catch(err => {
32+
res.status(500).send("Error -> " + err);
33+
});
34+
}).catch(err => {
35+
res.status(500).send("Fail! Error -> " + err);
36+
})
37+
}
38+
39+
exports.signin = (req, res) => {
40+
console.log("Sign-In");
41+
42+
User.findOne({
43+
where: {
44+
username: req.body.username
45+
}
46+
}).then(user => {
47+
if (!user) {
48+
return res.status(404).send('User Not Found.');
49+
}
50+
51+
var passwordIsValid = bcrypt.compareSync(req.body.password, user.password);
52+
if (!passwordIsValid) {
53+
return res.status(401).send({ auth: false, accessToken: null, reason: "Invalid Password!" });
54+
}
55+
56+
var token = jwt.sign({ id: user.id }, config.secret, {
57+
expiresIn: 86400 // expires in 24 hours
58+
});
59+
60+
res.status(200).send({ auth: true, accessToken: token });
61+
62+
}).catch(err => {
63+
res.status(500).send('Error -> ' + err);
64+
});
65+
}
66+
67+
exports.userContent = (req, res) => {
68+
User.findOne({
69+
where: {id: req.userId},
70+
attributes: ['name', 'username', 'email'],
71+
include: [{
72+
model: Role,
73+
attributes: ['id', 'name'],
74+
through: {
75+
attributes: ['userId', 'roleId'],
76+
}
77+
}]
78+
}).then(user => {
79+
res.status(200).json({
80+
"description": "User Content Page",
81+
"user": user
82+
});
83+
}).catch(err => {
84+
res.status(500).json({
85+
"description": "Can not access User Page",
86+
"error": err
87+
});
88+
})
89+
}
90+
91+
exports.adminBoard = (req, res) => {
92+
User.findOne({
93+
where: {id: req.userId},
94+
attributes: ['name', 'username', 'email'],
95+
include: [{
96+
model: Role,
97+
attributes: ['id', 'name'],
98+
through: {
99+
attributes: ['userId', 'roleId'],
100+
}
101+
}]
102+
}).then(user => {
103+
res.status(200).json({
104+
"description": "Admin Board",
105+
"user": user
106+
});
107+
}).catch(err => {
108+
res.status(500).json({
109+
"description": "Can not access Admin Board",
110+
"error": err
111+
});
112+
})
113+
}
114+
115+
exports.managementBoard = (req, res) => {
116+
User.findOne({
117+
where: {id: req.userId},
118+
attributes: ['name', 'username', 'email'],
119+
include: [{
120+
model: Role,
121+
attributes: ['id', 'name'],
122+
through: {
123+
attributes: ['userId', 'roleId'],
124+
}
125+
}]
126+
}).then(user => {
127+
res.status(200).json({
128+
"description": "Management Board",
129+
"user": user
130+
});
131+
}).catch(err => {
132+
res.status(500).json({
133+
"description": "Can not access Management Board",
134+
"error": err
135+
});
136+
})
137+
}
Lines changed: 13 additions & 0 deletions
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+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = (sequelize, Sequelize) => {
2+
const User = sequelize.define('users', {
3+
name: {
4+
type: Sequelize.STRING
5+
},
6+
username: {
7+
type: Sequelize.STRING
8+
},
9+
email: {
10+
type: Sequelize.STRING
11+
},
12+
password: {
13+
type: Sequelize.STRING
14+
}
15+
});
16+
17+
return User;
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const verifySignUp = require('./verifySignUp');
2+
const authJwt = require('./verifyJwtToken');
3+
4+
module.exports = function(app) {
5+
6+
const controller = require('../controller/controller.js');
7+
8+
app.post('/api/auth/signup', [verifySignUp.checkDuplicateUserNameOrEmail, verifySignUp.checkRolesExisted], controller.signup);
9+
10+
app.post('/api/auth/signin', controller.signin);
11+
12+
app.get('/api/test/user', [authJwt.verifyToken], controller.userContent);
13+
14+
app.get('/api/test/pm', [authJwt.verifyToken, authJwt.isPmOrAdmin], controller.managementBoard);
15+
16+
app.get('/api/test/admin', [authJwt.verifyToken, authJwt.isAdmin], controller.adminBoard);
17+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const jwt = require('jsonwebtoken');
2+
const config = require('../config/config.js');
3+
const db = require('../config/db.config.js');
4+
const Role = db.role;
5+
const User = db.user;
6+
7+
verifyToken = (req, res, next) => {
8+
let token = req.headers['x-access-token'];
9+
10+
if (!token){
11+
return res.status(403).send({
12+
auth: false, message: 'No token provided.'
13+
});
14+
}
15+
16+
jwt.verify(token, config.secret, (err, decoded) => {
17+
if (err){
18+
return res.status(500).send({
19+
auth: false,
20+
message: 'Fail to Authentication. Error -> ' + err
21+
});
22+
}
23+
req.userId = decoded.id;
24+
next();
25+
});
26+
}
27+
28+
isAdmin = (req, res, next) => {
29+
let token = req.headers['x-access-token'];
30+
31+
User.findByPk(req.userId)
32+
.then(user => {
33+
user.getRoles().then(roles => {
34+
for(let i=0; i<roles.length; i++){
35+
console.log(roles[i].name);
36+
if(roles[i].name.toUpperCase() === "ADMIN"){
37+
next();
38+
return;
39+
}
40+
}
41+
42+
res.status(403).send("Require Admin Role!");
43+
return;
44+
})
45+
})
46+
}
47+
48+
isPmOrAdmin = (req, res, next) => {
49+
let token = req.headers['x-access-token'];
50+
51+
User.findByPk(req.userId)
52+
.then(user => {
53+
user.getRoles().then(roles => {
54+
for(let i=0; i<roles.length; i++){
55+
if(roles[i].name.toUpperCase() === "PM"){
56+
next();
57+
return;
58+
}
59+
60+
if(roles[i].name.toUpperCase() === "ADMIN"){
61+
next();
62+
return;
63+
}
64+
}
65+
66+
res.status(403).send("Require PM or Admin Roles!");
67+
})
68+
})
69+
}
70+
71+
const authJwt = {};
72+
authJwt.verifyToken = verifyToken;
73+
authJwt.isAdmin = isAdmin;
74+
authJwt.isPmOrAdmin = isPmOrAdmin;
75+
76+
module.exports = authJwt;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const db = require('../config/db.config.js');
2+
const config = require('../config/config.js');
3+
const ROLEs = config.ROLEs;
4+
const User = db.user;
5+
const Role = db.role;
6+
7+
checkDuplicateUserNameOrEmail = (req, res, next) => {
8+
// -> Check Username is already in use
9+
User.findOne({
10+
where: {
11+
username: req.body.username
12+
}
13+
}).then(user => {
14+
if(user){
15+
res.status(400).send("Fail -> Username is already taken!");
16+
return;
17+
}
18+
19+
// -> Check Email is already in use
20+
User.findOne({
21+
where: {
22+
email: req.body.email
23+
}
24+
}).then(user => {
25+
if(user){
26+
res.status(400).send("Fail -> Email is already in use!");
27+
return;
28+
}
29+
30+
next();
31+
});
32+
});
33+
}
34+
35+
checkRolesExisted = (req, res, next) => {
36+
for(let i=0; i<req.body.roles.length; i++){
37+
if(!ROLEs.includes(req.body.roles[i].toUpperCase())){
38+
res.status(400).send("Fail -> Does NOT exist Role = " + req.body.roles[i]);
39+
return;
40+
}
41+
}
42+
next();
43+
}
44+
45+
const signUpVerify = {};
46+
signUpVerify.checkDuplicateUserNameOrEmail = checkDuplicateUserNameOrEmail;
47+
signUpVerify.checkRolesExisted = checkRolesExisted;
48+
49+
module.exports = signUpVerify;

0 commit comments

Comments
 (0)