fastify / fastify/fastify

Documentation and example of webhook signature check (through rawBody)

Open
#5,491 12 comments 0 reactions 0 assignees View on GitHub
feature request
Dominant language
JavaScript
Stars
37.1k
Forks
3k
Avg merge
1d 15h
Merged PRs (30d)
13

Description

### Prerequisites

- [X] I have written a descriptive issue title
- [X] I have searched existing issues to ensure the feature has not already been requested

### 🚀 Feature Proposal

I'm currently aiming to verify the signature of a webhook route using the raw body data.

There is already a lot of issues around the subject since 2018:
- [Support rawBody or override JSON parser](https://github.com/fastify/fastify/issues/707)
- [Stripe webhooks rawBody](https://github.com/fastify/fastify/issues/1965)
- [preHandler types are broken for version](https://github.com/fastify/fastify/issues/5125)

There is still no clear documentation regarding signature verification or how to obtain a raw body inside the route handler to perform webhook signature check.

I think that the best option would still just to have a `rawBody: true` option on the route as @mcollina suggested here:
[issuecomment-619153284](https://github.com/fastify/fastify/issues/707#issuecomment-619153284)

This way, the raw body would appear only on selected routes to avoid unnecessary memory consumption.

### Motivation

Enhance Fastify's usability and create a more welcoming environment.

### Example

Payload:
```json
{
"msg" : "test"
}
```
```ts
fastify.post("/example", { rawBody: true }, (request, reply) => {
console.log(request.rawBody); // "{\n \"msg\" : \"text\"\n}"
console.log(request.body); // { msg: 'text' }
});
```

In my project I'm loading dynamically all routes from folders and subfolders, for an unknown reason `fastify-raw-body` wasn't working for me.

There is the implementation I made to address my issue for now (added a `preParsing` hook to the route and using [raw-body](https://www.npmjs.com/package/raw-body) library to read the stream).
```ts
//Add rawBody to Webhooksroutes
routeObj.opt.preParsing = (request: any, reply, payload, done) => {
getRawBody(payload, { length: null, limit: request.routeOptions.bodyLimit, encoding: "utf8" }, (err, str) => {
if (!err) { request.rawBody = str; }
});
done(null, payload); // `done` not called in the callback of `getRawBody` to let the original `contentTypeParse` hook `payload.on('data')` before `getRawBody` starts to read the stream
};
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.