Categories
Express JavaScript Nodejs

Verifying JSON Web Tokens with Express-JWT

With the use of single-page apps and API-only back end, JSON web tokens (JWTs) have become a popular way of adding authentication capabilities to our apps.

In this article, we’ll look at how to verify JSON web tokens with Express-JWT.

Installation

express-jwt is available as a Node package. To install it, we run:

npm install express-jwt

Usage

We can use the jwt function that’s included with the express-jwt package to verify a token.

jwt is a middleware function, so we don’t have to create our own middleware to verify the token.

For example, we can use the jwt function as follows:

const express = require('express');  
const jsonwebtoken = require('jsonwebtoken');  
const jwt = require('express-jwt');  
const app = express();
const secret = 'secret';
app.post('/auth', (req, res) => {  
  const token = jsonwebtoken.sign({ foo: 'bar' }, secret);  
  res.send(token);  
})
app.get('/protected', jwt({ secret }), (req, res) => {  
  res.send('protected');  
})
app.listen(3000, () => console.log('server started'));

In the code above, we called jsonwebtoken.sign to issue a token in the auth route.

Then we can call the protected route by putting Bearer and then our token in the Authorization request header.

An example Authorization header would be:

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE1Nzk0NzczMDd9.QW7FOvyJQ36dir0199nJTv07VhlNo9\_cItGTkdyJeK8

If the token isn’t valid or isn’t present, then we would get an error.

We can also check other fields like audience or issuer as follows:

const express = require('express');  
const jsonwebtoken = require('jsonwebtoken');  
const jwt = require('express-jwt');  
const app = express();
const secret = 'secret';  
const audience = 'http://myapi/protected';  
const issuer = 'http://issuer';
app.post('/auth', (req, res) => {  
  const token = jsonwebtoken.sign({ foo: 'bar' }, secret, { audience, issuer });  
  res.send(token);  
})
app.get('/protected', jwt({ secret, audience, issuer }), (req, res) => {  
  res.send('protected');  
})
app.listen(3000, () => console.log('server started'));

In the code above, we added audience and issuer to the object in the 3rd argument of the sign method call, which holds the options that we want to add to the token issued.

Then in the protected route, we added the jwt middleware with the audience and issuer in the options object that we passed into jwt .

If the token has a secret , audience , and issuer that match what the code has, then the protected route returns the protected response. Otherwise, we get an error.

We can verify a token that’s generated with a Base64 encoded secret as follows:

const express = require('express');  
const jsonwebtoken = require('jsonwebtoken');  
const jwt = require('express-jwt');  
const app = express();
const secret = 'secret';
app.post('/auth', (req, res) => {  
  const token = jsonwebtoken.sign({ foo: 'bar' }, new Buffer(secret, 'base64'));  
  res.send(token);  
})
app.get('/protected', jwt({ secret: new Buffer(secret, 'base64') }), (req, res) => {  
  res.send('protected');  
})
app.listen(3000, () => console.log('server started'));

In the code above, we have the new Buffer(secret, ‘base64’) passed to the second argument of the sign method, which generates a token from a Base64 encoded secret.

Then in the protected route handler, we can call the jwt middleware function with the same secret to verify the token.

To verify a token generated with an RSA private key, we can write the following:

const express = require('express');  
const jsonwebtoken = require('jsonwebtoken');  
const jwt = require('express-jwt');  
const fs = require('fs');  
const app = express();
const publicKey = fs.readFileSync('public.pub');
app.post('/auth', (req, res) => {  
  const privateKey = fs.readFileSync('private.key');  
  const token = jsonwebtoken.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });  
  res.send(token);  
})
app.get('/protected', jwt({ secret: publicKey }), (req, res) => {  
  res.send('protected');  
})
app.listen(3000, () => console.log('server started'));

The token is generated in the auth route by reading the private key from a file on the file system and then using that to sign the token with the sign method.

Then we can use the public key that corresponds to the private key that was used to generate the token to verify the token by writing:

jwt({ secret: publicKey })

To access the decoded token, we can use the req.user property as follows:

const express = require('express');  
const jsonwebtoken = require('jsonwebtoken');  
const jwt = require('express-jwt');  
const app = express();  
const secret = 'secret';app.post('/auth', (req, res) => {  
  const token = jsonwebtoken.sign({ foo: 'bar' }, secret);  
  res.send(token);  
})app.get('/protected', jwt({ secret }), (req, res) => {  
  res.send(req.user);  
})app.listen(3000, () => console.log('server started'));

In the protected route, we returned req.user as the response. Then we should get something like:

{  
    "foo": "bar",  
    "iat": 1579478314  
}

in the response content.

We can change what property the decoded token is attached to by setting the requestProperty property as follows:

app.get('/protected', jwt({ secret, requestProperty: 'auth' }), (req, res) => {  
  res.send(req.auth);  
})

Then we get the same response as the previous example.

Conclusion

We can use the express-jwt middleware to verify our JSON web tokens.

It takes a secret and other token options like audience and issuer and then sets the decoded token to the Express request object if verification is successful.

If verification isn’t successful, then an error is returned.

It supports both symmetric and asymmetric crypto algorithms.

Categories
Express JavaScript

Guide to the Express Response Object — Sending Things

The Express response object lets us send a response to the client.

Various kinds of responses like strings, JSON, and files can be sent. Also, we can send various headers and status code to the client in addition to the body.

In this article, we’ll look at various properties of the response object, including send , sendFile , and sendStatus .

Methods

res.send([body])

We can use the res.send method to send an HTTP response.

The body parameter can be a Buffer object, string, a plain object or an array.

For example, we can send a binary response by writing:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  res.send(Buffer.from('foo'));  
})  
app.listen(3000);

To send JSON, we can pass in an object:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))app.get('/', (req, res, next) => {  
  res.send({ foo: 'bar' });  
})  
app.listen(3000);

We can also send HTML by passing in a string:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))app.get('/', (req, res, next) => {  
  res.send('<p>foo</p>');  
})  
app.listen(3000);

We can send the response code in addition to the send method:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  res.status(404).send('not found');  
})
app.listen(3000);

We can set the response header before sending our response:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  res.set('Content-Type', 'text/html');  
  res.send(Buffer.from('<p>foo</p>'))  
})  
app.listen(3000);

send also works with an array:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  res.send([1, 2, 3]);  
})
app.listen(3000);

Then we get [1,2,3] .

res.sendFile(path [, options] [, fn])

We can use the sendFile to send a file with various options specified in the options object.

An absolute path is required for the path for sendFile to work.

For example, we can use it as follows:

const express = require('express');  
const path = require('path');  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  const options = {  
    root: path.join(__dirname, 'files'),  
    dotfiles: 'deny',  
    headers: {  
      'x-timestamp': Date.now(),  
      'x-sent': true  
    }  
  }  
  res.sendFile('foo.txt', options);  
})  
app.listen(3000);

The code above sets the root path in the options so that we don’t have to construct the absolute path every time we call sendFile .

The following properties can be added to the options object:

  • maxAge — sets the max-age property of the Cache-Control header in milliseconds or a string in ms format
  • root — root directory for relative filenames
  • lastModified — sets the Last-Modified header to the last modified date of the file on the OS. Set to false to disable it.
  • headers — an object containing HTTP response headers to serve with the file.
  • dotfiles — option for serving dotfiles. Possible values are allow , deny , or ignore .
  • acceptRanges — enable or disable accepting range requests
  • cacheControl — enable or disable setting Cache-Control response header
  • immutable — enable or disable immutable directive in the Cache-Control header. If it’s enabled, the maxAge option should be specified to enable caching. The immutable directive will prevent supported clients from making conditional requests during the life of maxAge option to check if a file has changed.

We can also pass in a callback to handle errors as the last argument:

const express = require('express');  
const path = require('path');  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  const options = {  
    root: path.join(__dirname, 'files'),  
    dotfiles: 'deny',  
    headers: {  
      'x-timestamp': Date.now(),  
      'x-sent': true  
    }  
  }  
  res.sendFile('foo.txt', options, err => next(err));  
})  
app.listen(3000);

res.sendStatus(statusCode)

We can send an HTTP response status code with this method. We just have to pass in a number.

If an unsupported status code is specified the code will still be sent and a string version of it will be sent in the response body.

For example, if we have:

const express = require('express');  
const path = require('path');  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  res.sendStatus(200)  
})  
app.listen(3000);

Then we get back OK .

If we write the following:

const express = require('express');  
const path = require('path');  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res, next) => {  
  res.sendStatus(900)  
})  
app.listen(3000);

We get 900 since we sent an unsupported response code.

Conclusion

We can send responses in various ways with Express. The most generic one is send , which lets us send both textual and binary data. We can set headers to indicate what we’re sending.

sendFile sends a file response with the absolute file path of the file on the server. We can specify various options for the file we send.

The sendStatus method lets us send an HTTP response code only. We can use it to send both supported and unsupported response codes.

Categories
Express JavaScript Nodejs

Tracking Response Time of Express App Responses

To gauge the performance of our apps, we need to measure the response time of our API.

To do this with our Express app, we can use the response-time package.

Installation

response-time is available as a Node package. We can install it by running:

npm install response-time

Then we can import it by writing:

const responseTime = require('response-time');

responseTime([options])

We can set various options by passing an object into the optional options parameter.

It’ll create a middleware that adds a X-Response-Time header to responses.

The options object takes the following properties:

digits

The digits property is a fixed number of digits to include in the output, which is always in milliseconds. The default is 3.

header

The name of the header to be set. It defaults to X-Response-Time.

suffix

The suffix property is a boolean property to indicate if units of measure should be added to the output. The default value is true.

responseTime(fn)

The function creates a middleware that records the response time of a request and makes it available to our own function fn. fn has the signature (req, res, time) where time is a number in milliseconds.

Examples

Simple Example

We can use the responseTime package without any options or function passed in:

const express = require('express');  
const bodyParser = require('body-parser');  
const responseTime = require('response-time')  
const app = express();  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(responseTime());app.get('/', (req, res) => {  
  res.send('foo');  
});
app.listen(3000);

Then we get a X-Response-Time response header with a value like 0.587ms.

We can check the response header on an HTTP client like Postman.

Passing in Options

We can change the options for the header returned with the response. For example, we can write the following to change the number of digits sent:

const express = require('express');  
const bodyParser = require('body-parser');  
const responseTime = require('response-time')  
const app = express();  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(responseTime({  
  digits: 5  
}))
app.get('/', (req, res) => {  
  req.id = 1;  
  res.send('foo');  
});
app.listen(3000);

Then we get a X-Response-Time response header with a value like 0.71987ms.

Passing in Our Own Function

We can pass a function into the responseTime function as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const responseTime = require('response-time')  
const app = express();  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(responseTime((req, res, time) => {  
  console.log(`${req.method} ${req.url} ${time}`);  
}))
app.get('/', (req, res) => {  
  req.id = 1;  
  res.send('foo');  
});
app.listen(3000);

Then we get something like:

GET / 2.9935419999999997

from the console.log.

It’s useful if we want to manipulate the response time data or log it ourselves.

Conclusion

We can get the response time in the response header of a request with the response-time package.

It has a responseTime function which returns a middleware that we can use with the use method of express or express.Router() .

The function can either take an options object and or a function with the req, res, and time parameters to get the request, response, and response time respectively.

Categories
Express JavaScript Nodejs

Serve Favicons in Express Apps with serve-favicon

If we have an Express app that renders templates, we can use the serve-favicon middleware to serve Favicons.

Favicons are icons on the left side of a browser tab.

In this article, we’ll look at how to use it to display our favorite favicon in users’ browsers.

Why do we need this module?

The serve-favicon module lets us exclude requests for the favicon in our logger middleware.

It also caches the icon in memory to improve performance by reducing disk access.

In addition, it provides an ETag based on the contents of the icon, rather than file system properties.

Finally, this module serves with the most compatible Content-Type .

This module is exclusive for serving the favicon with the GET /favicon.ico request.

Installation

We can install it by running:

npm install serve-favicon

Options

The favicon function is provided by this module. It takes 2 arguments, which are path, and options and returns a middleware to serve a favicon from the given path .

The options object takes one property, which is the maxAge property. It sets the cache-control max-age directive in milliseconds. The default is 1 yeat. It also can be a string that’s accepted by the ms module.

Examples

Simple Usage

The serve-favicon middleware should come before other middleware so that it won’t conflict with other requests for favicon.ico .

For instance, we can load a favicon with serve-favicon as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const favicon = require('serve-favicon')  
const path = require('path')  
const app = express();  
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.get('/', (req, res) => {  
  res.sendFile('public/index.html');  
});
app.listen(3000);

Then we get:

https://thewebdev.info/wp-content/uploads/2020/04/icon.png

Setting Max Age

We can also set the maxAge option as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const favicon = require('serve-favicon')  
const path = require('path')  
const app = express();  
const iconPath = path.join(__dirname, 'public', 'favicon.ico');  
const options = {  
  maxAge: 200 * 60 * 60 * 24 * 1000  
}  
app.use(favicon(iconPath, options));  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));app.get('/', (req, res) => {  
  res.sendFile('public/index.html');  
});
app.listen(3000);

Then we set the expiry of the icon to 200 days.

Conclusion

We can use the serve-favicon middleware to cache requests for favicon and serve it instead of loading it every time when users make a request for the favicon.

The expiry can also be set so the favicon request result won’t be cached forever.

It should be included before other middleware so that it won’t conflict with other middleware that makes request for a favicon.

Categories
Express JavaScript

Guide to the Express Response Object — Redirection and Templates

The Express response object lets us send a response to the client.

Various kinds of responses like strings, JSON, and files can be sent. Also, we can send various headers and status code to the client in addition to the body.

In this article, we’ll look at various properties of the response object, including sending the Links response header, redirect to different paths and URLs, and rendering HTML.

Methods

res.links(links)

The links method joins an object with links together and sends the Link response header with the links joined together.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res  
    .links({  
      next: 'http://foo.com?page=1',  
      last: 'http://foo.com?page=2'
    })  
    .send();  
});
app.listen(3000, () => console.log('server started'));

Then we get that the Link response header has the value:

<http://foo.com?page=1>; rel="next", <http://foo.com?page=2>; rel="last"

when we make a request to the / path.

res.location(path)

The location method sends the Location response header with the specified path parameter as the value.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res  
    .location('http://medium.com')  
    .send();  
});
app.listen(3000, () => console.log('server started'));

Then we get:

http://medium.com

as the value of the Location response header when we make a request to the / route.

res.redirect([status,] path)

The redirect method redirects to the URL or path specified with the specified status . If no status is specified, the default is 302.

For example, we can use it as follows to redirect to another route:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.redirect('/bar');  
});

app.get('/bar', (req, res) => {  
  res.send('bar');  
});

app.listen(3000, () => console.log('server started'));

Then we should see bar since we redirected to the bar route.

We can specify a status code as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.redirect(301, '/bar');  
});

app.get('/bar', (req, res) => {  
  res.send('bar');  
});

app.listen(3000, () => console.log('server started'));

We can also redirect to a full URL:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
    res.redirect('http://google.com');  
});

app.listen(3000, () => console.log('server started'));

Then when we go to / in our browser, we get Google displayed in our browser.

We can redirect back to the referrer with:

res.redirect('back')

and we can also redirect to a higher level URL, which defaults to / .

We can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const post = express.Router();app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));

post.get('/', (req, res) => {  
    res.redirect('..');  
});

app.get('/', (req, res) => {  
    res.send('hi');  
});

app.use('/post', post);app.listen(3000, () => console.log('server started'));

Then we get hi if we go to /post since we see redirect to '..' .

res.render(view [, locals] [, callback])

res.render lets us render HTML using a template. Once we set the HTML template engine, we can use template files to display the results.

The locals object has the properties that we can access in the templates.

And the callback can get the error and the rendered HTML string.

The view argument has the string with the template’s file name. The view’s folder is set before we can call res.render so we don’t need the full folder name.

For example, we can use the Pug template to render templates as follows:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))  
app.set('views', './views');  
app.set('view engine', 'pug');
app.get('/', (req, res, next) => {  
  res.render('index', { pageTitle: 'Hello', pageMessage: 'Hello there!' });  
})  
app.listen(3000, () => console.log('server started'));

Then we can add a template file called index.pug to the views folder as follows:

html  
  head  
    title= pageTitle  
  body  
    h1= pageMessage

Then we get:

https://thewebdev.info/wp-content/uploads/2020/04/hello-there.png

We can also pass in a callback to the render method as follows:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))  
app.set('views', './views');  
app.set('view engine', 'pug');app.get('/', (req, res, next) => {  
  res.render(  
    'index',  
    { pageTitle: 'Hello', pageMessage: 'Hello there!' },  
    (err, html) => {  
      if (err) {  
        next(err);  
      }  
      else {  
        console.log(html);  
      }  
    }  
  );  
})  
app.listen(3000);

Then we get the rendered HTML from the console.log :

<html><head><title>Hello</title></head><body><h1>Hello there!</h1></body></html>

Any error will be sent to the Express error handler with the next function.

Conclusion

We can render HTML results with render method.

With the redirect method, we can redirect to different paths and URLs with the different response code.

We can use the links and locations methods to send the Links and Locations response headers respectively.