sendgrid / sendgrid-java

The Official Twilio SendGrid Led, Community Driven Java API Library
https://sendgrid.com
MIT License
484 stars 408 forks source link

Sendgrid Webhook event tests not passing real scenarios #708

Closed zurich-ah closed 2 years ago

zurich-ah commented 2 years ago

Issue Summary

Reusing test cases with our own public key and event from Sendgrid yields different results. Please note; the values supplied in the organisation based keys have been taken from a real Sendgrid event and the public key retrieved via both the UI and calling https://api.sendgrid.com/v3/user/webhooks/event/settings/signed. I have raised a support ticket (7281978) with Sendgrid internal cases however they pointed us here.

Steps to Reproduce

  1. Reference this test: https://github.com/sendgrid/sendgrid-java/blob/5a1a08d5a08568e5d66182489e8508b138f3385e/src/test/java/com/sendgrid/helpers/eventwebhook/EventWebhookTest.java
  2. Play a real bounce transaction and scape the headers from Sendgrid for this event.
  3. Add new organisation based keys, example TESTORG_PUBLICKEY, TESTORG_TIMESTAMP, TESTORG_SIGNATURE
  4. Add new function or expand testVerifySignature to include a separate verification call using the three new keys and existing payload
  5. Run test

Code Snippet

public static void testOrgSignature() throws Exception{

    final String TESTORG_PUBLIC_KEY = "<string taken from UI under Settings -> Mail Settings -> Signed Event Webhook Requests OR via  https://api.sendgrid.com/v3/user/webhooks/event/settings/signed";
    final String TESTORG_SIGNATURE = "<scrapped value from header in Sendgrid event>";
    final String TESTORG_TIMESTAMP = "<scrapped value from header in Sendgrid event>";

    System.out.println("Starting Sendgrid provided test, this passes");

    Assert.assertTrue(verify(
            PUBLIC_KEY,
            PAYLOAD,
            SIGNATURE,
            TIMESTAMP
        ));

    System.out.println("Starting our details test, this fails");

    Assert.assertTrue(verify(
        TESTORG_PUBLIC_KEY,
            PAYLOAD,
            TESTORG_SIGNATURE,
            TESTORG_TIMESTAMP
        ));
}


### Technical details:
        <dependency>
            <groupId>com.sendgrid</groupId>
            <artifactId>sendgrid-java</artifactId>
            <version>4.7.6</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.69</version>
        </dependency>
shwetha-manvinkurke commented 2 years ago

Here are some tips for you to try and see if it helps

zurich-ah commented 2 years ago

hi @shwetha-manvinkurke ,

I've reviewed the tips page you have provided. This is indeed the samples from where these tests were referenced. Please see the link in step 1 to reproduce.

The core issue is that, following the provided documentation, using a real event from Sendgrid, the provided test cases are not passing the transaction. (It then also obviously fails the real processing).

If you would like I am happy to share the real transaction information / test values.

To help eliminate human error, the reason we reused the existing test class provided by sendgrid-java libraries is that I've noted a lot of errors around processing the PAYLOAD object (with cr characters and what not).

However, simply replacing the other keys (public, private and timestamp) still yields an error return.

zurich-ah commented 2 years ago

Hi,

I've found the root issues for both the test and core execution.

The verification method is extremely sensitive to whitespaces and format. As such, the supplied PAYLOAD when verifying is required to be a single line no spaced value.

As we were running this via a Mulesoft API the following code snippet for the payload has fixed this issue:

(write(payload,"text/json",indent:false) replace ": " with ":") ++ "\r\n"

Happy to close this issue now. Thanks.