sendgrid-java icon indicating copy to clipboard operation
sendgrid-java copied to clipboard

Signed Webhook event verification fails when payload is a JSON String and api request body is map of string

Open sauravkumar-dev opened this issue 3 years ago • 5 comments

Issue Summary We are trying to validate signed webhook events in java with POST API. We are sending mail and configured https://webhook.site/73452d78-3dea-478b-a005-d87371972190 as public webhoo url. We are getting payload, timestamp and signature. but while verifying above on public key its failing.

Steps to Reproduce Enable Signed Event Webhook Requests on SendGrid website Copy the public from SendGrid and paste it in the java method Configure Mail Settings to enable webhooks and configure to send the event to our endpoint Send an email using SendGrid The webhook event is received and we try to validate the request against the public key We retrieve the info in headers X-Twilio-Email-Event-Webhook-Signature and X-Twilio-Email-Event-Webhook-Timestamp The validation always fails.

Pls find the code which i am using.

public Boolean isValidSignature(List<Map<String,Object>> emailActivities, Map<String, String> headers) throws JsonProcessingException {
String sandGridPublicKey=;
boolean isValid = false;
Security.addProvider(new BouncyCastleProvider());
String payload= new ObjectMapper().writeValueAsString(emailActivities) + "\r\n";
try {

	        String signature = headers.get(EventWebhookHeader.SIGNATURE.toString().toLowerCase());
	        String timeStamp = headers.get(EventWebhookHeader.TIMESTAMP.toString().toLowerCase());
	        EventWebhook ew = new EventWebhook();
	        ECPublicKey ellipticCurvePublicKey = ew.ConvertPublicKeyToECDSA(sandGridPublicKey);
	        isValid = ew.VerifySignature(ellipticCurvePublicKey, payload, signature, timeStamp);
	        System.out.println(isValid);
	         
	    } catch (Exception e) {
	        e.printStackTrace();
	    }

	    return isValid;
	}

Payload as below:

[
{
"email": "[email protected]",
"event": "processed",
"send_at": 0,
"sg_event_id": "cHJvY2Vzc2VkLTIyODEyNzM5LTllOEljeGljUUt5cl8yWDNwZ0hnRlEtMA",
"sg_message_id": "9e8IcxicQKyr_2X3pgHgFQ.filterdrecv-75ff7b5ffb-96rhp-1-6227379B-A1.0",
"smtp-id": "9e8IcxicQKyr_2X3pgHgFQ@geopod-ismtpd-4-0",
"timestamp": 1646737307
}]

sauravkumar-dev avatar Mar 09 '22 05:03 sauravkumar-dev

Looks like it's not the raw payload which is needed to properly validate the event. Example here: https://github.com/sendgrid/sendgrid-java/blob/f158675d27e4150311ef370ae30e3a446b67871d/examples/helpers/eventwebhook/Example.java#L27

childish-sambino avatar Mar 11 '22 22:03 childish-sambino

Hi, I am also facing the same issue, anyone knows how to get the right payload if we are using Spring boot? The example provided is using Spark

Kaushik612 avatar Apr 04 '22 17:04 Kaushik612

@sauravkumar-dev Were you able to figure out a solution to this issue?

Kaushik612 avatar Apr 04 '22 18:04 Kaushik612

@Kaushik612 Yes, I was figure out the issues and its working for me now. Below is the solution String payload= new ObjectMapper().writeValueAsString(payloadFromSendgrid)+"\n\r"; payload=payload.replace("},{" , "},\n\r{");

sauravkumar-dev avatar Apr 05 '22 05:04 sauravkumar-dev

@Kaushik612 Was the above comment able to solve your issue? If not, are you able to get the raw payload from the Spring Boot implementation?

childish-sambino avatar Apr 05 '22 15:04 childish-sambino