Every application needs to interact with an ecosystem of 3rd party SaaS providers. Implementing a webhook HTTP endpoint in your application allows this ecosystem of external applications to notify you. Your application can then react to those notifications and perform tasks accordingly.
serverless plugin install -n serverless-liftservice: my-app
provider:
name: aws
constructs:
stripe:
type: webhook
authorizer:
handler: myAuthorizer.main
path: /my-webhook-endpoint
method: POST
plugins:
- serverless-liftEach webhook construct deploys the following resources:
- an API Gateway V2 HTTP API and its $default stage
- an EventBridge EventBus
- an IAM Role allowing API Gateway to use
PutEventsAPI of Eventbridge - an API Gateway V2 route
- an API Gateway V2 integration defining mappings of parameters between the HTTP request body and the Eventbridge Event's body
- a custom Lambda authorizer to handle signature verification at API Gateway level
Each webhook construct exposes the following variable:
busName: the name of the deployed EventBridge bus
This can be used to reference the bus on which notification are published, for example:
constructs:
stripe:
# ...
functions:
myConsumer:
handler: src/stripeConsumer.handler
events:
- eventBridge:
eventBus: ${construct:stripe.busName}
pattern:
source:
# filter all events received on stripe webhook
- stripe
detail-type:
- invoice.paidHow it works: the ${construct:stripe.busName} variable will automatically be replaced with a CloudFormation reference to the EventBridge bus.
Required
constructs:
stripe:
type: webhook
path: /my-pathThe endpoint your webhook should be exposed on. Always starts with a /.
The final URL for the webhook endpoint will be displayed in the information section when running a serverless deploy command and will be https://{id}.execute-api.{region}.amazonaws.com{path}
Conditional - depends on insecure value
constructs:
stripe:
# ...
authorizer:
handler: stripe/authorizer.mainThe authorizer is a Lambda function that checks that webhooks are valid.
Note: the "authorizer" Lambda function is configured inside the webhook construct, instead of being defined in the functions section.
The only required value is the handler: this should point to the code that authenticate 3rd party notification. The handler will receive an event from API Gateway using payload format v2. The handler should be written to return the expected simple payload format.
// authorizer.js
export const main = (event, context, callback) => {
callback(null, {
"isAuthorized": true,
});
}All settings allowed for functions can be used under the authorizer key. For example:
constructs:
stripe:
# ...
authorizer:
handler: stripe/authorizer.main
environment:
STRIPE_SECRET: my-secretLift will automatically configure the function to be triggered by API Gateway. It is not necessary to define events on the function.
Optional
Defaults to false.
It is possible to skip writing an authorizer function by setting insecure: true.
HTTP requests on the wehbook endpoint will not be validated. This setting is not recommended and SHOULD NOT BE USED IN PRODUCTION to prevent webhook injection as well as Denial of Wallet attacks.
constructs:
stripe:
# ...
insecure: trueOptional
Defaults to Webhook.
Can either be a dynamic path selector:
constructs:
stripe:
# ...
eventType: $request.body.typeOr a static string:
constructs:
stripe:
# ...
eventType: stripeAlways favor dynamic path selector to ensure the minimum amount of compute is executed downstream. The list of available dynamic selector is available in API Gateway documentation.
Optional
Defaults to POST
This is the HTTP method the webhook will accept. It can be any of the following:
POSTPUTPATCH
constructs:
stripe:
# ...
method: POSTYou can specify an extensions property on the webhook construct to extend the underlying CloudFormation resources. In the exemple below, the EventBridge Bus CloudFormation resource generated by the stripe webhook construct will be extended with the new Name: StripeBus CloudFormation property.
constructs:
stripe:
type: webhook
insecure: true
path: /stripe
extensions:
bus:
Properties:
Name: StripeBus| Extension key | CloudFormation resource | CloudFormation documentation |
|---|---|---|
| api | AWS::ApiGatewayV2::Api | Link |
| bus | AWS::Events::EventBus | Link |
Feel like a common extension pattern should be implemented as part of the construct configuration? Open a GitHub issue.
