Created
June 12, 2019 15:47
-
-
Save hoangsetup/993824ea1dd5a9b3f74606da0b4257b4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require('express'); | |
const bodyParser = require('body-parser'); | |
const jwt = require('jsonwebtoken'); | |
const router = express.Router(); | |
const config = require('./config'); | |
const utils = require('./utils'); | |
const tokenList = {}; | |
const app = express(); | |
router.get('/', (req, res) => { | |
res.send('Ok'); | |
}); | |
/** | |
* Đăng nhập | |
* POST /login | |
*/ | |
router.post('/login', (req, res) => { | |
const postData = req.body; | |
const user = { | |
"email": postData.email, | |
"name": postData.name | |
} | |
// Thực hiện việc kết nối cơ sở dữ liệu (hay tương tự) để kiểm tra thông tin username and password | |
// Đăng nhập thành công, tạo mã token cho user | |
const token = jwt.sign(user, config.secret, { | |
expiresIn: config.tokenLife, | |
}); | |
// Tạo một mã token khác - Refresh token | |
const refreshToken = jwt.sign(user, config.refreshTokenSecret, { | |
expiresIn: config.refreshTokenLife | |
}); | |
// Lưu lại mã Refresh token, kèm thông tin của user để sau này sử dụng lại | |
tokenList[refreshToken] = user; | |
// Trả lại cho user thông tin mã token kèm theo mã Refresh token | |
const response = { | |
token, | |
refreshToken, | |
} | |
res.json(response); | |
}) | |
/** | |
* Lấy mã token mới sử dụng Refresh token | |
* POST /refresh_token | |
*/ | |
router.post('/refresh_token', async (req, res) => { | |
// User gửi mã Refresh token kèm theo trong body | |
const { refreshToken } = req.body; | |
// Kiểm tra Refresh token có được gửi kèm và mã này có tồn tại trên hệ thống hay không | |
if ((refreshToken) && (refreshToken in tokenList)) { | |
try { | |
// Kiểm tra mã Refresh token | |
await utils.verifyJwtToken(refreshToken, config.refreshTokenSecret); | |
// Lấy lại thông tin user | |
const user = tokenList[refreshToken]; | |
// Tạo mới mã token và trả lại cho user | |
const token = jwt.sign(user, config.secret, { | |
expiresIn: config.tokenLife, | |
}); | |
const response = { | |
token, | |
} | |
res.status(200).json(response); | |
} catch (err) { | |
console.error(err); | |
res.status(403).json({ | |
message: 'Invalid refresh token', | |
}); | |
} | |
} else { | |
res.status(400).json({ | |
message: 'Invalid request', | |
}); | |
} | |
}); | |
/** | |
* Middleware xác thực người dùng dựa vào mã token | |
* @param {*} req | |
* @param {*} res | |
* @param {*} next | |
*/ | |
const TokenCheckMiddleware = async (req, res, next) => { | |
// Lấy thông tin mã token được đính kèm trong request | |
const token = req.body.token || req.query.token || req.headers['x-access-token']; | |
// decode token | |
if (token) { | |
// Xác thực mã token và kiểm tra thời gian hết hạn của mã | |
try { | |
const decoded = await utils.verifyJwtToken(token, config.secret); | |
// Lưu thông tin giã mã được vào đối tượng req, dùng cho các xử lý ở sau | |
req.decoded = decoded; | |
next(); | |
} catch (err) { | |
// Giải mã gặp lỗi: Không đúng, hết hạn... | |
console.error(err); | |
return res.status(401).json({ | |
message: 'Unauthorized access.', | |
}); | |
} | |
} else { | |
// Không tìm thấy token trong request | |
return res.status(403).send({ | |
message: 'No token provided.', | |
}); | |
} | |
} | |
router.use(TokenCheckMiddleware); | |
router.get('/profile', (req, res) => { | |
// all secured routes goes here | |
res.json(req.decoded) | |
}) | |
app.use(bodyParser.json()); | |
app.use('/api', router); | |
const listener = app.listen(config.port || process.env.PORT || 3000, () => { | |
console.log('Start at: http://localhost:' + listener.address().port); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
"secret": "s0me-secr3t-goes-here", | |
"refreshTokenSecret": "some-s3cret-refre2h-token", | |
"port": 3000, | |
"tokenLife": 900, // 15 minutes | |
"refreshTokenLife": 86400 // a day | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "jwt_auth_refresh_token", | |
"version": "1.0.0", | |
"description": "Simple app with refresh token mechanism", | |
"main": "app.js", | |
"scripts": { | |
"start": "node app.js", | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"keywords": [ | |
"nodejs", | |
"express", | |
"jwt", | |
"refresh token" | |
], | |
"author": "[email protected]", | |
"license": "ISC", | |
"dependencies": { | |
"body-parser": "^1.19.0", | |
"express": "^4.17.1", | |
"jsonwebtoken": "^8.5.1" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const jwt = require('jsonwebtoken'); | |
module.exports = { | |
verifyJwtToken: (token, secretKey) => { | |
return new Promise((resolve, reject) => { | |
jwt.verify(token, secretKey, (err, decoded) => { | |
if (err) { | |
return reject(err); | |
} | |
resolve(decoded); | |
}); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment