This PR implements verification of the HMAC key header present on incoming webhook requests from Tito, based on the information provided in their docs.
Prior to this verification, event registration could be spoofed by simply hitting the webhook endpoint with a payload containing a first_name, last_name, and email. Granted, the negative implications of doing so were minimal, given this just adds users to the customer.io database and signs them up for the mailing list. But this added validation prevents abuse, eliminates potential spam/invalid data ending up in customer.io, and bolsters the site against denial of service attacks.
Prerequisites
The verification requires that an admin of the Begin deployment sets an additional environment variable, TITO_SECURITY_TOKEN, which matches the security token present on the Tito event settings page. This can be found by going to the event dashboard in Tito, then navigating to Settings > Webhook endpoints.
The annoying caveat to this is that presently, security tokens are uniquely generated per event. I've reached out to Tito to inquire about account-wide security tokens, or at least the ability to custom-set a token or copy a token from a previous event when you duplicate it. But until then, it will be necessary to rotate the security token each month when setting up the new Tito event. To that end, I've added an additional item to the meetup checklist to help with remembering to update this. 🙂
Test plan
Valid requests
Create a Tito testing account and test event
Add Tito event security token to .env
Comment out call to addToCustomerIO, add basic logging of first_name, last_name, and email instead (since we don't actually want to save a user for testing 😛)
Run server locally
Port forward/tunnel to get a public URL
Configure new webhook on Tito for the URL ${publicURL}/webhooks/tito, give it at least the registration.completed event
Register for test event
Observe request succeeds, user fields are logged out as expected
Invalid requests
Missing signature
Using a REST client of your choice, issue a POST request to ${publicURL}/webhooks/tito without any header, body doesn't matter
Observe request fails with "missing security signature header" error message
Invalid/mismatched signature
Copy the request payload and valid signature header for a real event from Tito
Using a REST client of your choice, build a POST request to ${publicURL}/webhooks/tito with the request payload body and signature header values you copied
Modify the signature header or payload body slightly
Observe request fails with "security signature does not match" error message
This PR implements verification of the HMAC key header present on incoming webhook requests from Tito, based on the information provided in their docs.
Prior to this verification, event registration could be spoofed by simply hitting the webhook endpoint with a payload containing a
first_name
,last_name
, andemail
. Granted, the negative implications of doing so were minimal, given this just adds users to the customer.io database and signs them up for the mailing list. But this added validation prevents abuse, eliminates potential spam/invalid data ending up in customer.io, and bolsters the site against denial of service attacks.Prerequisites
The verification requires that an admin of the Begin deployment sets an additional environment variable,
TITO_SECURITY_TOKEN
, which matches the security token present on the Tito event settings page. This can be found by going to the event dashboard in Tito, then navigating to Settings > Webhook endpoints.The annoying caveat to this is that presently, security tokens are uniquely generated per event. I've reached out to Tito to inquire about account-wide security tokens, or at least the ability to custom-set a token or copy a token from a previous event when you duplicate it. But until then, it will be necessary to rotate the security token each month when setting up the new Tito event. To that end, I've added an additional item to the meetup checklist to help with remembering to update this. 🙂
Test plan
Valid requests
.env
addToCustomerIO
, add basic logging offirst_name
,last_name
, andemail
instead (since we don't actually want to save a user for testing 😛)${publicURL}/webhooks/tito
, give it at least theregistration.completed
eventInvalid requests
Missing signature
${publicURL}/webhooks/tito
without any header, body doesn't matterInvalid/mismatched signature
${publicURL}/webhooks/tito
with the request payload body and signature header values you copied