JSON Web Token is an open standard based on JSON proposed by the IETF for the creation of access tokens that allow the propagation of identity and privileges or claims in English
In this case we configure a very simple api in which the way to integrate jwt will be analyzed
Start our project
$ npm init -y
Install the necessary dependencies
$ npm i --save express jsonwebtoken
We create an index.js file and add the following content:
1const express = require('express'); 2const jwt = require('jsonwebtoken'); 3const PORT = process.env.PORT || 3000; 4const SECRET_KEY = process.env.SECRET_KEY || 'secret-key'; 5const app = express(); 6 7app.use(express.json()); 8app.use(express.urlencoded({ extended: false })); 9 10app.get('/', (req, res) => { 11 res.send('API REST NodeJS'); 12}) 13 14app.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`)); 15
We start our server
$ node index.js
Add a route for our authentication
1 2app.post('/token', (req, res) => { 3 const { username, password } = req.body; 4 if(!(username && password)) return res.status(400).json({ msg: 'Username/Password are required!'}) 5 6 if(username === 'admin' && password === 'admin'){ 7 const payload = { 8 username: username, 9 } 10 11 const token = jwt.sign(payload, SECRET_KEY, { expiresIn: 1440 }); 12 13 return res.status(200).json({ 14 token: token 15 }) 16 } else { 17 return res.status(401).json({ msg: 'Username/password are incorrect!'}); 18 } 19}) 20
We should get a response similar to this
1{ 2 "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjYyNzYyOTU2LCJleHAiOjE2NjI3NjQzOTZ9.NH9johw1YWdhW5RQTCWpFBNNks7gHauUPDbrVxUyaMA" 3}
Now we must create a middleware that will take care of validating the token when accessing a private endpoint:
1... 2const auth = require('express').Router(); 3 4auth.use((req, res, next) => { 5 const token = req.headers['x-access-token']; 6 7 if(token){ 8 jwt.verify(token, SECRET_KEY, (err, decoded) => { 9 if(err) return res.json({ msg: 'Token is invalid!'}) 10 req.decoded = decoded; 11 next(); 12 }) 13 }else{ 14 return res.status(400).json({ msg: 'Token is missing!'}); 15 } 16}); 17
Now we add a private route and use our middleware that validates if the token is coming in the request.
1 2app.get('/datos-privados', auth, (req, res) => { 3 const tasks = [ 4 { task: 'Task 1', done: false }, 5 { task: 'Task 2', done: false }, 6 { task: 'Task 3', done: true }, 7 { task: 'Task 4', done: false }, 8 ] 9 10 return res.status(200).json(tasks); 11}) 12
Our index.js file should contain the following:
1const express = require('express'); 2const jwt = require('jsonwebtoken'); 3const auth = require('express').Router(); 4const PORT = process.env.PORT || 3000; 5const SECRET_KEY = process.env.SECRET_KEY || 'secret-key'; 6const app = express(); 7 8app.use(express.json()); 9app.use(express.urlencoded({ extended: false })); 10 11app.get('/', (req, res) => { 12 res.send('API REST NodeJS'); 13}) 14 15app.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`)); 16 17app.post('/token', (req, res) => { 18 const { username, password } = req.body; 19 if(!(username && password)) return res.status(400).json({ msg: 'Username/Password are required!'}) 20 21 if(username === 'admin' && password === 'admin'){ 22 const payload = { 23 username: username, 24 } 25 26 const token = jwt.sign(payload, SECRET_KEY, { expiresIn: 1440 }); 27 28 return res.status(200).json({ 29 token: token 30 }) 31 } else { 32 return res.status(401).json({ msg: 'Username/password are incorrect!'}); 33 } 34}) 35 36auth.use((req, res, next) => { 37 const token = req.headers['x-access-token']; 38 39 if(token){ 40 jwt.verify(token, SECRET_KEY, (err, decoded) => { 41 if(err) return res.status(403).json({ msg: 'Token is invalid!'}) 42 req.decoded = decoded; 43 next(); 44 }) 45 }else{ 46 return res.status(400).json({ msg: 'Token is missing!'}); 47 } 48}); 49 50app.get('/datos-privados', auth, (req, res) => { 51 const tasks = [ 52 { task: 'Task 1', done: false }, 53 { task: 'Task 2', done: false }, 54 { task: 'Task 3', done: true }, 55 { task: 'Task 4', done: false }, 56 ] 57 58 return res.status(200).json(tasks); 59})