diff --git a/backend/controller/authController.js b/backend/controller/authController.js index e9bfcb4b56c71e63e5e6fa2c2f407c18620f08cc..9332a63774491304a6ba8de244308c64ebe67fc9 100644 --- a/backend/controller/authController.js +++ b/backend/controller/authController.js @@ -54,10 +54,17 @@ exports.signin = (req, res) => { var token = jwt.sign({id: user.id}, config.secret, { expiresIn: config.jwtExpireTime }); - - res.status(200).send({ - auth: true, - accessToken: token + + User.update( + {validToken: token}, + {where: {id: user.id}} + ).then(() => { + res.status(200).send({ + auth: true, + accessToken: token + }); + }).error(() => { + res.status(500).send("Error saving new token"); }); }).catch(err => { res.status(500).send('Error -> ' + err); diff --git a/backend/controller/testController.js b/backend/controller/testController.js index a1752d6cf3827e5101b180170a63279446a7ec6d..4cd032550353fead8b3b2bde536b1ae78abbd5a7 100644 --- a/backend/controller/testController.js +++ b/backend/controller/testController.js @@ -6,7 +6,7 @@ const Role = models.role; exports.memberContent = (req, res) => { User.findOne({ where: { - id: req.userId + id: res.locals.userId }, attributes: ['id', 'name', 'username', 'email'], include: [{ @@ -21,7 +21,7 @@ exports.memberContent = (req, res) => { }).catch(err => { res.status(500).json({ "description": "Can not access User Page", - "error": er + "error": err.message }); }) } diff --git a/backend/migrations/20190329134047-add-jwt-column-to-user.js b/backend/migrations/20190329134047-add-jwt-column-to-user.js new file mode 100644 index 0000000000000000000000000000000000000000..75e0498d16b93e9b250cbae5b2a718e0b4fd384b --- /dev/null +++ b/backend/migrations/20190329134047-add-jwt-column-to-user.js @@ -0,0 +1,27 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return queryInterface.addColumn('users', 'validToken', { + type: Sequelize.STRING + }); + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + return queryInterface.removeColumn('users', 'validToken'); + } +}; diff --git a/backend/models/user.js b/backend/models/user.js index 93a0213c96ea87f5229c267fad3f88d595e48e73..22900173b4f314c456f766d5489c1d00bf302e87 100644 --- a/backend/models/user.js +++ b/backend/models/user.js @@ -4,7 +4,8 @@ module.exports = (sequelize, DataTypes) => { name: DataTypes.STRING, email: DataTypes.STRING, password: DataTypes.STRING, - username: DataTypes.STRING + username: DataTypes.STRING, + validToken: DataTypes.STRING }, {}); user.associate = function(models) { models.user.belongsTo(models.role); diff --git a/backend/router/jwtTokenHandler.js b/backend/router/jwtTokenHandler.js new file mode 100644 index 0000000000000000000000000000000000000000..036793205e8998bc2e2274d4dde7153d37839f83 --- /dev/null +++ b/backend/router/jwtTokenHandler.js @@ -0,0 +1,34 @@ +const jwt = require('jsonwebtoken'); +const config = require('../config/app.config.js'); +const models = require('../models'); +const User = models.user; + +extendJwtToken = (req, res, next) => { + var userId = res.locals.userId; + var token = jwt.sign({id: userId}, config.secret, { + expiresIn: config.jwtExpireTime + }); + res.locals.token = token; + next(); +} + +saveTokenToUser = (req, res, next) => { + token = res.locals.token; + userId = res.locals.userId; + User.update({ + validToken: token + }, { + where: { + id: userId + } + }).then(() => { + next(); + }); +} + +const jwtTokenHandler = {}; + +jwtTokenHandler.extendJwtToken = extendJwtToken; +jwtTokenHandler.saveTokenToUser = saveTokenToUser; + +module.exports = jwtTokenHandler; \ No newline at end of file diff --git a/backend/router/router.js b/backend/router/router.js index 21eb47b044639ddc8c9da3ae4030681359cce2b1..dd5efcd028636a232bdffe83d74b535d6a712b4c 100644 --- a/backend/router/router.js +++ b/backend/router/router.js @@ -1,5 +1,6 @@ const verifySignUp = require('./verifySignUp'); -const authJwt = require('./verifyJwtToken'); +const verifyJwtToken = require('./verifyJwtToken'); +const tokenHandler = require('./jwtTokenHandler'); module.exports = function(app) { const authController = require('../controller/authController.js'); @@ -7,6 +8,6 @@ module.exports = function(app) { app.post('/api/auth/signup', [verifySignUp.checkDuplicateUserNameOrEmail, verifySignUp.checkRolesExisted], authController.signup); app.post('/api/auth/login', authController.signin); - app.get('/api/test/admin', [authJwt.verifyToken, authJwt.isAdmin], testController.adminContent); - app.get('/api/test/member', [authJwt.verifyToken], testController.memberContent); + app.get('/api/test/admin', [verifyJwtToken.verifyToken, verifyJwtToken.isAdmin, tokenHandler.extendJwtToken, tokenHandler.saveTokenToUser], testController.adminContent); + app.get('/api/test/member', [verifyJwtToken.verifyToken, tokenHandler.extendJwtToken, tokenHandler.saveTokenToUser], testController.memberContent); } \ No newline at end of file diff --git a/backend/router/verifyJwtToken.js b/backend/router/verifyJwtToken.js index c2b079eb13d5558598bff119294ff26331b2358b..5471b306615f6f0399dee790df0a35b77f3ccd7d 100644 --- a/backend/router/verifyJwtToken.js +++ b/backend/router/verifyJwtToken.js @@ -21,16 +21,29 @@ verifyToken = (req, res, next) => { auth: false }); } - req.userId = decoded.id; - next(); + res.locals.userId = decoded.id; + + // check if token is same + User.findOne({ + where: { + id: decoded.id + } + }).then(user => { + if (user.validToken === token) { + next(); + } else { + res.status(403).send("Cannot match token!"); + } + }); }); } isAdmin = (req, res, next) => { - User.findByPk(req.userId) + User.findByPk(res.locals.userId) .then(user => { user.getRole().then(role => { - if (role === 'Master Admin Diskominfo' || role === 'Admin Diskominfo' || role === 'Admin Dinas') { + if (role.name === 'Master Admin Diskominfo' || role.name === 'Admin Diskominfo' || role.name === 'Admin Dinas') { + res.locals.userId = res.locals.userId; next(); return; } diff --git a/backend/router/verifySignUp.js b/backend/router/verifySignUp.js index e6727cb61a9c5ebb45f09c7b89cfc7b090af7137..e105d6114826ab9482cfb4039d00c724b5221118 100644 --- a/backend/router/verifySignUp.js +++ b/backend/router/verifySignUp.js @@ -33,7 +33,6 @@ checkRolesExisted = (req, res, next) => { res.status(400).send("Fail -> Role does NOT exist = " + req.body.role); return; } - next(); }