├── .gitignore ├── .env ├── README.md ├── package.json ├── jwt.http ├── server.js └── authServer.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | ACCESS_TOKEN_SECRET=jwtabc 2 | REFRESH_TOKEN_SECRET=jwtabcRefresh -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jwt-tutorial 2 | 3 | Đây là source code của jwt tutorial trên kênh youtube HoleTex 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "src", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "startServer": "nodemon server", 9 | "startAuthServer": "nodemon authServer" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "dotenv": "^9.0.0", 16 | "express": "^4.17.1", 17 | "jsonwebtoken": "^8.5.1" 18 | }, 19 | "devDependencies": { 20 | "nodemon": "^2.0.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /jwt.http: -------------------------------------------------------------------------------- 1 | GET http://localhost:5000/books 2 | Authorization: Beaer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhvbGV0ZXgiLCJpYXQiOjE2MjA0NzQzMDQsImV4cCI6MTYyMDQ3NDMzNH0.NsKCpIBolNdQK-l4chi2urajCvXU529VISFNHnqYkzQ 3 | 4 | ### 5 | 6 | POST http://localhost:5500/login 7 | Content-Type: application/json 8 | 9 | { 10 | "username": "holetex" 11 | } 12 | 13 | ### 14 | POST http://localhost:5500/refreshToken 15 | Content-Type: application/json 16 | 17 | { 18 | "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhvbGV0ZXgiLCJpYXQiOjE2MjA0NzQxODV9.I8lKqN5PLE3Vz103O5Ml7ePJWsUksJoeA81uYFeCc6o" 19 | } 20 | 21 | ### 22 | POST http://localhost:5500/logout 23 | Content-Type: application/json 24 | 25 | { 26 | "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImhvbGV0ZXgiLCJpYXQiOjE2MjA0NzQxODV9.I8lKqN5PLE3Vz103O5Ml7ePJWsUksJoeA81uYFeCc6o" 27 | } -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import jwt from 'jsonwebtoken'; 3 | import dotenv from 'dotenv'; 4 | 5 | dotenv.config(); 6 | 7 | const app = express(); 8 | const PORT = process.env.PORT || 5000; 9 | 10 | app.use(express.json()); 11 | 12 | const books = [ 13 | { 14 | id: 1, 15 | name: 'Chi Pheo', 16 | author: 'ABC', 17 | }, 18 | { 19 | id: 2, 20 | name: 'Chien tranh va Hoa Binh', 21 | author: 'DEF', 22 | }, 23 | ]; 24 | 25 | app.get('/books', authenToken, (req, res) => { 26 | res.json({ status: 'Success', data: books }); 27 | }); 28 | 29 | function authenToken(req, res, next) { 30 | const authorizationHeader = req.headers['authorization']; 31 | // 'Beaer [token]' 32 | const token = authorizationHeader.split(' ')[1]; 33 | if (!token) res.sendStatus(401); 34 | 35 | jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, data) => { 36 | console.log(err, data); 37 | if (err) res.sendStatus(403); 38 | next(); 39 | }); 40 | } 41 | 42 | app.listen(PORT, () => { 43 | console.log(`Server is running on PORT ${PORT}`); 44 | }); 45 | -------------------------------------------------------------------------------- /authServer.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import jwt from 'jsonwebtoken'; 3 | import dotenv from 'dotenv'; 4 | 5 | dotenv.config(); 6 | 7 | const app = express(); 8 | const PORT = 5500; 9 | 10 | app.use(express.json()); 11 | 12 | let refreshTokens = []; 13 | 14 | app.post('/refreshToken', (req, res) => { 15 | const refreshToken = req.body.token; 16 | if (!refreshToken) res.sendStatus(401); 17 | if (!refreshTokens.includes(refreshToken)) res.sendStatus(403); 18 | 19 | jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, data) => { 20 | console.log(err, data); 21 | if (err) res.sendStatus(403); 22 | const accessToken = jwt.sign( 23 | { username: data.username }, 24 | process.env.ACCESS_TOKEN_SECRET, 25 | { 26 | expiresIn: '30s', 27 | } 28 | ); 29 | res.json({ accessToken }); 30 | }); 31 | }); 32 | 33 | app.post('/login', (req, res) => { 34 | // Authentication 35 | // Authorization 36 | // { username: 'Test' } 37 | const data = req.body; 38 | console.log({ data }); 39 | const accessToken = jwt.sign(data, process.env.ACCESS_TOKEN_SECRET, { 40 | expiresIn: '30s', 41 | }); 42 | const refreshToken = jwt.sign(data, process.env.REFRESH_TOKEN_SECRET); 43 | refreshTokens.push(refreshToken); 44 | res.json({ accessToken, refreshToken }); 45 | }); 46 | 47 | app.post('/logout', (req, res) => { 48 | const refreshToken = req.body.token; 49 | refreshTokens = refreshTokens.filter((refToken) => refToken !== refreshToken); 50 | res.sendStatus(200); 51 | }); 52 | 53 | app.listen(PORT, () => { 54 | console.log(`Server is running on PORT ${PORT}`); 55 | }); 56 | --------------------------------------------------------------------------------