How to sign JSON responses in Express

Viewed 21

I'm developing an Express.js server; since it manages sensible data, I'd like to add a cryptographic signature to every response, using a private key. The signature part is already OK, the problem is catching the JSON string just before is sent to the client to sign it.

Ideally I'd like to add a custom response header, e.g. X-signature, so clients could verify the received payload against the public key exposed by the service.

In Express, how can I intercept the response body after the JSON.stringify() call but before the headers are sent?

1 Answers

I've copied what is done in the compression() middleware, replacing the send() method of Response with my own and calling the original one after I calculate the signature. Here's a simplified solution just to show the concept, in the real word I've taken care of body's possible types. The fact that calculateSignature() is an async function is a little troublesome, but everything seems to work well now.

Any comment is appreciated!

import express, { RequestHandler } from 'express';

declare const calculateSignature = (payload: string) => Promise<string>;

const responseSignature = (): RequestHandler => (_, res, next) => {
    const _send = res.send;
    res.send = (body) => {
        if (isPlaintextType(body)) {
            calculateSignature(body)
                .then((signature) => res.setHeader('X-Signature', signature))
                .catch((e) => console.error(e))
                .finally(() => _send.call(res, body));
            return res;
        } else {
            return _send.call(res, body);
        }
    };
    next();
};


const app = express();
app.use(responseSignature());
app.listen(3000);
Related