Skip to contentSkip to navigationSkip to topbar
On this page

Securing your Inbound Parse webhooks


The Inbound Parse service provides secure communication with your webhook endpoint by enforcing security policies. These policies allow you to use mechanisms like cryptographic signatures and OAuth to validate requests. By defining a security policy and attaching it to your Parse webhook, you can ensure that communication between your webhook endpoint and Twilio SendGrid is authentic and secure.


Supported security mechanisms

supported-security-mechanisms page anchor
  • Signature Verification: Validate incoming Inbound Parse Webhook requests by verifying their Elliptic Curve Digital Signature Algorithm (ECDSA) cryptographic signature. Twilio SendGrid signs the payload with a private key, and you verify the signature included in the HTTP headers with the public key (which you download and store on your end).
  • OAuth Verification: Use OAuth to authenticate webhook requests, ensuring that only requests with valid access tokens are processed. SendGrid fetches access tokens from an OAuth server that you designate and includes the access token in the Authorization header of the HTTP POST request.
  • Hybrid Approach: Combine both signature validation and OAuth for enhanced security, adding multiple layers of protection to your webhooks.

Step 1: Set up a Parse webhook via Parse Settings endpoint

step-1-set-up-a-parse-webhook-via-parse-settings-endpoint page anchor

If you don't have an Inbound Parse webhook, see Create a Parse Setting.

You should have a Parse setting of the following shape:

1
{
2
"url": "http://mydomain.com/parse",
3
"hostname": "mail.mydomain.com",
4
"spam_check": false,
5
"send_raw": true
6
}

Step 2: Define a webhook security policy

step-2-define-a-webhook-security-policy page anchor

The following example shows how to create a security policy with both OAuth authorization and request signing. At least one of the two security methods is required; using both is optional.

1
curl -v -X POST https://api.sendgrid.com/v3/user/webhooks/security/policies \
2
--header "Authorization: bearer <<YOUR_API_KEY_HERE>>" \
3
--data '{
4
"name": "example policy",
5
"oauth": {
6
"client_id": "client_456",
7
"client_secret": "secret",
8
"token_url": "http://oauth.example.com/user/456/token",
9
"scopes": ["webhooks:read", "webhooks:write"]
10
},
11
"signature": { "enabled": true }
12
}'
1
{
2
"policy": {
3
"id": "dd677638-a16d-4e19-95ea-20231c35511b",
4
"name": "example policy",
5
"oauth": {
6
"client_id": "client_456",
7
"token_url": "http://oauth.example.com/user/456/token",
8
"scopes": [
9
"webhooks:read",
10
"webhooks:write"
11
]
12
},
13
"signature": {
14
"public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmgmjvPAR/Lmwn2teL2WJUDIx35PqsnLKjPhPbrKkfMg6vK4NZQB1VeFSKbV7whQbEJRFHjF8+1zJxsXRP1GbWw=="
15
}
16
}
17
}
(information)

Info

You can omit either the signature key or the OAuth key, but one of the two must be included in order to have a valid security policy.

(warning)

Store the public key for Signature Verification

If you're using Signature Verification, use the public key returned in the request to verify webhook requests. Store the public key so that it's easily accessible in your webhook server.

You don't need to request the public key for each incoming webhook. Doing so may introduce unnecessary latency and dependencies. Instead, ensure that the public key is stored securely and is easily accessible within your application for signature verification.

Step 3: Attach the security policy to the Parse webhook

step-3-attach-the-security-policy-to-the-parse-webhook page anchor

The next step is to attach the security policy to your Parse webhook settings. You can do so by updating your parse settings with a security_policy key whose value is the policy ID from the security policy you created earlier:

1
curl -X PATCH "https://api.sendgrid.com/v3/user/webhooks/parse/settings/parse.yourdomain.com" \
2
--header "Authorization: bearer <<YOUR_API_KEY_HERE>>" \
3
--header "Content-Type: application/json" \
4
--data '{
5
"url": "http://mydomain.com/parse",
6
"spam_check": false,
7
"send_raw": true,
8
"security_policy": "dd677638-a16d-4e19-95ea-20231c35511b"
9
}'

You'll receive a JSON object containing the updated Parse settings with the security policy association:

1
{
2
"url": "http://mydomain.com/parse",
3
"hostname": "parse.yourdomain.com",
4
"spam_check": false,
5
"send_raw": true,
6
"security_policy": "dd677638-a16d-4e19-95ea-20231c35511b"
7
}

After this step, any further Inbound Parse API requests to your webhook endpoint will include the following HTTP headers:

  • OAuth Security Policy
    • Authorization: Bearer <OAUTH_ACCESS_TOKEN>
  • Signature Verification
    • X-Twilio-Email-Event-Webhook-Signature: <String>
    • X-Twilio-Email-Event-Webhook-Timestamp: <String>

Step 4: Validate Inbound Parse webhooks

step-4-validate-inbound-parse-webhooks page anchor

Signature verification

signature-verification page anchor

Verifying webhook signatures from the Inbound Parse API is functionally similar to verifying SendGrid Event Webhook Signatures. However, there is one key difference: The Inbound Parse API sends request payloads using the multipart/form-data encoding. This means any attachments included in the original email will be delivered as file parts in the request payload.

(warning)

Warning

Some web frameworks automatically parse multipart data and separate file uploads from the rest of the request body. This can break signature validation.

To ensure signature validation works correctly:

  • Do not parse or modify the request body before validating the signature.
  • Use the raw request body exactly as it was received to generate your signature hash.

Using OAuth to verify your Inbound Parse webhooks follows the same process as Event Webhooks(link takes you to an external page).