JSON Web Token es un estándar abierto basado en JSON propuesto por IETF para la creación de tokens de acceso que permiten la propagación de identidad y privilegios o claims en inglés
En este caso configuramos una api muy simple en la cual se analizará la forma de integrar jwt
Iniciar nuestro proyecto
$ npm init -y
Instalar las dependencias necesarias
$ npm i --save express jsonwebtoken
Creamos un archivo index.js y agregamos el siguiente contenido:
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
Iniciamos nuestro servidor
$ node index.js
Agregar una ruta para nuestra autenticación
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
Debemos obtener una respuesta similar a esta
1{ 2 "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjYyNzYyOTU2LCJleHAiOjE2NjI3NjQzOTZ9.NH9johw1YWdhW5RQTCWpFBNNks7gHauUPDbrVxUyaMA" 3}
Ahora debemos crear un middleware que se encargara de validar el token al momento de acceder a un endpoint privado:
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
Ahora agregamos una ruta privada y utilizamos nuestro middleware que valida si viene el token en el 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
Nuestro archivo index.js debería contener lo siguiente:
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})