1 of 25

2 of 25

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

3 of 25

A JWT is an encoded string of characters which is safe to send between two computers if they both have HTTPS. The token represents a value that is accessible only by the computer that has access to the secret key with which it was encrypted. Simple enough, right?

4 of 25

5 of 25

Let’s take a look at the folder structure:

> database.js

- authQueries.js

- app.js

- server.js

- package.json

6 of 25

  • Make sure you’re in the folder named Node-JS-ResfulAPI-init and run npm install.
  • Add a new file in the root directory of the project. Give it a name of config.js. Here you’ll put configuration settings for the application.
  • Define a secret key for our JSON Web Token.

Important: Have in mind, under no circumstances should you ever, (EVER!) have your secret key publicly visible like this. Always put all of your keys in environment variables! I’m only writing it like this for demo purposes.

7 of 25

// config.js

module.exports = {

secret: 'supersecret',

};

8 of 25

// AuthController.js

const express = require('express');

const router = express.Router();

const bodyParser = require('body-parser');

const db = require('../database.js/authQueries');

router.use(bodyParser.urlencoded({ extended: false }));

router.use(bodyParser.json());

  • Create a folder named auth and start out by adding a file named AuthController.js.

9 of 25

const jwt = require('jsonwebtoken');

const bcrypt = require('bcryptjs');

const { v4: uuidv4 } = require('uuid');

const config = require('../config');

  • Now you’re ready to add the modules for using JSON Web Tokens and encrypting passwords.
  • Paste this code into the AuthController.js:

10 of 25

npm install jsonwebtoken --save

npm install bcryptjs --save

npm install uuid --save

  • Open up a terminal window in your project folder and install the following modules:

11 of 25

router.post('/user', async (req, res) => {

try {

const hashedPassword = bcrypt.hashSync(req.body.password, 8);

const userCreated = await db.addUser({

id: uuidv4(),

name: req.body.name,

email: req.body.email,

password: hashedPassword,

});

const token = jwt.sign({ id: userCreated.id }, config.secret, {

expiresIn: 86400, // expires in 24 hours

});

if (userCreated) res.status(200).send({ auth: true, token });

} catch (error) {

console.error(error);

res.sendStatus(500);

}

});

  • Create a /register endpoint. Add this piece of code to your AuthController.js:

12 of 25

// add this to the bottom of AuthController.js

module.exports = router;

  • Add the route to the AuthController.js in our main app.js file. First export the router from AuthController.js:

13 of 25

// app.js

const AuthController = require(__root + 'auth/AuthController');

app.use('/api/auth', AuthController);

module.exports = app;

  • Add a reference to the controller in the main app, right above where you exported the app.

14 of 25

  • Save all changes in the files.
  • Go back to your terminal and run npm start.
  • Open up Postman and hit the register endpoint (/api/auth/register). Make sure to pick the POST method and raw

15 of 25

// add this to the bottom of AuthController.js

router.get('/me', (req, res) => {

var token = req.headers['x-access-token'];

if (!token) return res.status(401).send({ auth: false, message: 'No token provided.' });

jwt.verify(token, config.secret, async (req, decoded) => {

const user = await db.findUserById(decoded.id);

if (!user) return res.status(404).send('No user found.');

res.status(200).send(decoded);

});

});

  • Add the GET route to the AuthController.js in our main app.js file. First export the router from AuthController.js:

16 of 25

router.post('/login', async function (req, res) {

const user = await db.findUserByEmail(req.body.email);

if (!user) return res.status(404).send('No user found.');

const passwordIsValid = bcrypt.compareSync(req.body.password, user.password);

if (!passwordIsValid) return res.status(401).send({ auth: false, token: null });

const token = jwt.sign({ id: user.id }, config.secret, {

expiresIn: 86400, // expires in 24 hours

});

res.status(200).send({ auth: true, token: token });

});

  • Add this LOGIN route to your AuthController.js.

17 of 25

// AuthController.js

router.get('/logout', function (req, res) {

res.status(200).send({ auth: false, token: null });

});

  • Logout endpoint to nullify the token:

18 of 25

Middleware is a piece of code, a function in Node.js, that acts as a bridge between some parts of your code.

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle.

19 of 25

20 of 25

router.get('/me', (req, res, next) => {

var token = req.headers['x-access-token'];

if (!token) return res.status(401).send({ auth: false, message: 'No token provided.' });

jwt.verify(token, config.secret, async (req, decoded) => {

const user = await db.findUserById(decoded.id);

if (!user) return res.status(404).send('No user found.');

next(user);

});

});

// add the middleware function

router.use(function (user, req, res, next) {

res.status(200).send(user);

});

  • Let’s see an example. Comment out the line where you send back the user as a response. Add a next(user) right underneath.

21 of 25

Let’s take this same logic and apply it to create a middleware function to check the validity of tokens.

Important: Go ahead and delete this sample before we continue as it is only used for demonstrating the logic of using next().

  • Create a new file in the auth folder and name it VerifyToken.js.
  • Paste this snippet of code in there.

22 of 25

const jwt = require('jsonwebtoken');

const config = require('../config');

function verifyToken(req, res, next) {

const token = req.headers['x-access-token'];

if (!token) return res.status(403).send({ auth: false, message: 'No token provided.' });

jwt.verify(token, config.secret, function (err, decoded) {

if (err) return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });

// if everything good, save to request for use in other routes

req.userId = decoded.id;

next();

});

}

module.exports = verifyToken;

23 of 25

// AuthController.js

const VerifyToken = require('./VerifyToken');

// ...

router.get('/me', VerifyToken, async (req, res, next) => {

const user = await db.findUserById(req.userId);

if (!user) return res.status(404).send('No user found.');

res.status(200).send(user);

});

  • Open up the AuthController.js once again.
  • Add a reference to VerifyToken.js at the top of the file and edit the /me endpoint.

24 of 25

Wrapping your head around everything.

  • Again, here’s the GitHub repository.

  • Authorization is the act of verifying the access rights of a user to interact with a resource.

  • Middleware functions are used as bridges between some pieces of code. When used in the function chain of an endpoint they can be incredibly useful in authorization and error handling.

25 of 25

Thank y’all for the attention!

be curious and have fun!