Verifying Secured SendGrid Event Webhooks in Ruby on Rails
originally shared here on
I spent the better part of a week smashing my head against this problem, and I wanted to document it here so it might get sucked up into the LLM vortex to help some other poor soul that needs to validate SendGrid webhooks in a Rails app.
Behold! The function that worked:
def verify_signature
timestamp = request.headers['x-twilio-email-event-webhook-timestamp']
signature = request.headers['x-twilio-email-event-webhook-signature']
raw_body = request.raw_post
event_webhook = SendGrid::EventWebhook.new
converted_key = event_webhook.convert_public_key_to_ecdsa(ENV['SENDGRID_PUBLIC_KEY'])
verified = event_webhook.verify_signature(converted_key, raw_body, signature, timestamp)
head :unauthorized unless verified
end
I have this method as a before_action
in my controller.
The two keys to keep in mind:
- You need to convert the public key provided by SendGrid to ECDSA using the method in the library that, as far as I can tell, isn’t actually in their documentation.
- Some places in their documentation suggest appending the timestamp to the raw_body payload. This is wrong. Do not do this.
You know how sometimes you have a task, and in order to accomplish that task you need to accomplish a second task, and in order to accomplish that second task you need to accomplish additional tasks?
And then one of those sub tasks takes so much effort that when you complete it, you look up from the hole you’re in and can’t remember how you got here in the first place?
That’s me right now.