Skip to content

Commit 93b8100

Browse files
committed
fix stripe endpoint
1 parent cdd979e commit 93b8100

File tree

3 files changed

+105
-39
lines changed

3 files changed

+105
-39
lines changed

src/api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"esbuild": "^0.24.2",
3737
"fastify": "^5.1.0",
3838
"fastify-plugin": "^4.5.1",
39+
"fastify-raw-body": "^5.0.0",
3940
"ical-generator": "^7.2.0",
4041
"jsonwebtoken": "^9.0.2",
4142
"jwks-rsa": "^3.1.0",

src/api/routes/membership.ts

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { FastifyPluginAsync } from "fastify";
88
import {
99
BaseError,
1010
InternalServerError,
11-
UnauthenticatedError,
1211
ValidationError,
1312
} from "common/errors/index.js";
1413
import { getEntraIdToken } from "api/functions/entraId.js";
@@ -22,11 +21,17 @@ import { getSecretValue } from "api/plugins/auth.js";
2221
import stripe, { Stripe } from "stripe";
2322
import { AvailableSQSFunctions, SQSPayload } from "common/types/sqsMessage.js";
2423
import { SendMessageCommand, SQSClient } from "@aws-sdk/client-sqs";
24+
import rawbody, { RawBodyPluginOptions } from "fastify-raw-body";
2525

2626
const NONMEMBER_CACHE_SECONDS = 1800; // 30 minutes
2727
const MEMBER_CACHE_SECONDS = 43200; // 12 hours
2828

2929
const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
30+
await fastify.register(rawbody, {
31+
field: "rawBody",
32+
global: false,
33+
runFirst: true,
34+
});
3035
const getAuthorizedClients = async () => {
3136
if (roleArns.Entra) {
3237
fastify.log.info(
@@ -190,47 +195,42 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
190195
.send({ netId, isPaidMember: false });
191196
});
192197
};
193-
194198
fastify.post(
195199
"/provision",
196-
{
197-
preParsing: async (request, _reply, payload) => {
198-
try {
199-
const sig = request.headers["stripe-signature"];
200-
if (!sig || typeof sig !== "string") {
201-
throw new Error("Missing or invalid Stripe signature");
202-
}
203-
204-
if (!Buffer.isBuffer(payload) && typeof payload !== "string") {
205-
throw new Error("Invalid payload format");
206-
}
207-
const secretApiConfig =
208-
(await getSecretValue(
209-
fastify.secretsManagerClient,
210-
genericConfig.ConfigSecretName,
211-
)) || {};
212-
if (!secretApiConfig) {
213-
throw new InternalServerError({
214-
message: "Could not connect to Stripe.",
215-
});
216-
}
217-
stripe.webhooks.constructEvent(
218-
payload.toString(),
219-
sig,
220-
secretApiConfig.stripe_endpoint_secret as string,
221-
);
222-
} catch (err: unknown) {
223-
if (err instanceof BaseError) {
224-
throw err;
225-
}
226-
throw new UnauthenticatedError({
227-
message: "Stripe webhook could not be validated.",
200+
{ config: { rawBody: true } },
201+
async (request, reply) => {
202+
let event: Stripe.Event;
203+
if (!request.rawBody) {
204+
throw new ValidationError({ message: "Could not get raw body." });
205+
}
206+
try {
207+
const sig = request.headers["stripe-signature"];
208+
if (!sig || typeof sig !== "string") {
209+
throw new Error("Missing or invalid Stripe signature");
210+
}
211+
const secretApiConfig =
212+
(await getSecretValue(
213+
fastify.secretsManagerClient,
214+
genericConfig.ConfigSecretName,
215+
)) || {};
216+
if (!secretApiConfig) {
217+
throw new InternalServerError({
218+
message: "Could not connect to Stripe.",
228219
});
229220
}
230-
},
231-
},
232-
async (request, reply) => {
233-
const event = request.body as Stripe.Event;
221+
event = stripe.webhooks.constructEvent(
222+
request.rawBody,
223+
sig,
224+
secretApiConfig.stripe_endpoint_secret as string,
225+
);
226+
} catch (err: unknown) {
227+
if (err instanceof BaseError) {
228+
throw err;
229+
}
230+
throw new ValidationError({
231+
message: "Stripe webhook could not be validated.",
232+
});
233+
}
234234
switch (event.type) {
235235
case "checkout.session.completed":
236236
if (

yarn.lock

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4131,6 +4131,11 @@ [email protected]:
41314131
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
41324132
integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
41334133

4134+
4135+
version "3.1.2"
4136+
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
4137+
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
4138+
41344139
cac@^6.7.14:
41354140
version "6.7.14"
41364141
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
@@ -4665,6 +4670,11 @@ delayed-stream@~1.0.0:
46654670
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
46664671
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
46674672

4673+
4674+
version "2.0.0"
4675+
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
4676+
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
4677+
46684678
dequal@^2.0.2, dequal@^2.0.3:
46694679
version "2.0.3"
46704680
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
@@ -5604,6 +5614,15 @@ fastify-plugin@^5.0.0:
56045614
resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-5.0.1.tgz#82d44e6fe34d1420bb5a4f7bee434d501e41939f"
56055615
integrity sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==
56065616

5617+
fastify-raw-body@^5.0.0:
5618+
version "5.0.0"
5619+
resolved "https://registry.yarnpkg.com/fastify-raw-body/-/fastify-raw-body-5.0.0.tgz#29d653c9af5605af9c937b4552b4838dfc99e0a7"
5620+
integrity sha512-2qfoaQ3BQDhZ1gtbkKZd6n0kKxJISJGM6u/skD9ljdWItAscjXrtZ1lnjr7PavmXX9j4EyCPmBDiIsLn07d5vA==
5621+
dependencies:
5622+
fastify-plugin "^5.0.0"
5623+
raw-body "^3.0.0"
5624+
secure-json-parse "^2.4.0"
5625+
56075626
fastify@^5.1.0:
56085627
version "5.2.1"
56095628
resolved "https://registry.yarnpkg.com/fastify/-/fastify-5.2.1.tgz#38381800eb26b7e27da72d9ee51c544f0c52ff39"
@@ -6108,6 +6127,17 @@ html5-qrcode@^2.3.8:
61086127
resolved "https://registry.yarnpkg.com/html5-qrcode/-/html5-qrcode-2.3.8.tgz#0b0cdf7a9926cfd4be530e13a51db47592adfa0d"
61096128
integrity sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==
61106129

6130+
6131+
version "2.0.0"
6132+
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
6133+
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
6134+
dependencies:
6135+
depd "2.0.0"
6136+
inherits "2.0.4"
6137+
setprototypeof "1.2.0"
6138+
statuses "2.0.1"
6139+
toidentifier "1.0.1"
6140+
61116141
http-proxy-agent@^7.0.2:
61126142
version "7.0.2"
61136143
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
@@ -6222,7 +6252,7 @@ inflight@^1.0.4:
62226252
once "^1.3.0"
62236253
wrappy "1"
62246254

6225-
inherits@2, inherits@^2.0.3:
6255+
inherits@2, inherits@2.0.4, inherits@^2.0.3:
62266256
version "2.0.4"
62276257
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
62286258
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -7907,6 +7937,16 @@ [email protected]:
79077937
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
79087938
integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==
79097939

7940+
raw-body@^3.0.0:
7941+
version "3.0.0"
7942+
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f"
7943+
integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==
7944+
dependencies:
7945+
bytes "3.1.2"
7946+
http-errors "2.0.0"
7947+
iconv-lite "0.6.3"
7948+
unpipe "1.0.0"
7949+
79107950
rc@^1.0.1, rc@^1.1.6:
79117951
version "1.2.8"
79127952
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@@ -8405,6 +8445,11 @@ scheduler@^0.23.2:
84058445
dependencies:
84068446
loose-envify "^1.1.0"
84078447

8448+
secure-json-parse@^2.4.0:
8449+
version "2.7.0"
8450+
resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862"
8451+
integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==
8452+
84088453
secure-json-parse@^3.0.1:
84098454
version "3.0.2"
84108455
resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-3.0.2.tgz#255b03bb0627ba5805f64f384b0a7691d8cb021b"
@@ -8491,6 +8536,11 @@ set-proto@^1.0.0:
84918536
es-errors "^1.3.0"
84928537
es-object-atoms "^1.0.0"
84938538

8539+
8540+
version "1.2.0"
8541+
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
8542+
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
8543+
84948544
shebang-command@^1.2.0:
84958545
version "1.2.0"
84968546
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -8683,6 +8733,11 @@ [email protected]:
86838733
resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
86848734
integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==
86858735

8736+
8737+
version "2.0.1"
8738+
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
8739+
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
8740+
86868741
std-env@^3.8.0:
86878742
version "3.8.0"
86888743
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5"
@@ -9192,6 +9247,11 @@ toad-cache@^3.7.0:
91929247
resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441"
91939248
integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==
91949249

9250+
9251+
version "1.0.1"
9252+
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
9253+
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
9254+
91959255
totalist@^3.0.0:
91969256
version "3.0.1"
91979257
resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8"
@@ -9453,6 +9513,11 @@ universalify@^0.2.0:
94539513
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
94549514
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
94559515

9516+
9517+
version "1.0.0"
9518+
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
9519+
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
9520+
94569521
unplugin@^1.3.1:
94579522
version "1.16.1"
94589523
resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.16.1.tgz#a844d2e3c3b14a4ac2945c42be80409321b61199"

0 commit comments

Comments
 (0)