-
Notifications
You must be signed in to change notification settings - Fork 51.5k
fix(Stripe Trigger Node): Add Stripe signature verification #22764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| /* eslint-disable n8n-nodes-base/node-param-description-excess-final-period */ | ||
| import { createHmac } from 'crypto'; | ||
| import type { | ||
| IDataObject, | ||
| IHookFunctions, | ||
|
|
@@ -948,9 +949,46 @@ export class StripeTrigger implements INodeType { | |
| async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> { | ||
| const bodyData = this.getBodyData(); | ||
| const req = this.getRequestObject(); | ||
| const headerData = this.getHeaderData(); | ||
| const webhookData = this.getWorkflowStaticData('node'); | ||
|
|
||
| const events = this.getNodeParameter('events', []) as string[]; | ||
| const stripeSignature = headerData['stripe-signature'] as string | undefined; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Rule violated: Prefer Typeguards over Type casting Avoid narrowing the Stripe signature header with Prompt for AI agents |
||
| if (!stripeSignature) { | ||
| return {}; | ||
| } | ||
|
|
||
| const webhookSecret = webhookData.webhookSecret as string | undefined; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Rule violated: Prefer Typeguards over Type casting Replace this Prompt for AI agents |
||
| if (!webhookSecret) { | ||
| return {}; | ||
| } | ||
|
|
||
| const elements = stripeSignature.split(','); | ||
| let timestamp: string | undefined; | ||
| let signature: string | undefined; | ||
|
|
||
| for (const element of elements) { | ||
| if (element.startsWith('t=')) { | ||
| timestamp = element.substring(2); | ||
| } else if (element.startsWith('v1=')) { | ||
| signature = element.substring(3); | ||
| } | ||
| } | ||
|
|
||
| if (!timestamp || !signature) { | ||
| return {}; | ||
| } | ||
|
|
||
| const signedPayload = `${timestamp}.${req.rawBody.toString()}`; | ||
|
|
||
| const expectedSignature = createHmac('sha256', webhookSecret) | ||
| .update(signedPayload) | ||
| .digest('hex'); | ||
|
|
||
| if (signature !== expectedSignature) { | ||
| return {}; | ||
| } | ||
|
|
||
| const events = this.getNodeParameter('events', []) as string[]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Rule violated: Prefer Typeguards over Type casting Do not cast the Prompt for AI agents |
||
| const eventType = bodyData.type as string | undefined; | ||
|
|
||
| if (eventType === undefined || (!events.includes('*') && !events.includes(eventType))) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: Rule violated: Tests
Add workflow or unit tests that cover both valid and invalid Stripe webhook signatures for the newly added verification logic to comply with the Community PR Guidelines testing requirement.
Prompt for AI agents