How Do We Verify Webhook v3 Signatures (Current Documentation Outdated) 🤷

Hello, my name is Simeon.

We have come into an issue with your platform.

We are trying to use PagerDuty Webhooks v3 to communicate with our different integrated platforms. Before we use the Webhooks we want to verify the signature so we know it is coming from a legitimate source (PagerDuty).

So we used this documentation to try to do this - https://developer.pagerduty.com/docs/webhooks/webhook-signatures/

But I think the documentation is outdated.

For example in the documentation it wants us to split the signatures.

X-PagerDuty-Signature:
v1=f03de6f61df6e454f3620c4d6aca17ad072d3f8bbb2760eac3b2ad391b5e8073,
v1=130dcacb53a94d983a37cf2acba98e805a1c37185309ba56fdcccbcf00d6dd8b

Step 1 : Extract the signature(s) from the request

  • Extract the signature string from the X-PagerDuty-Signature header on the request.
  • Split the signatures which are separated by the , character.
  • Select only signatures which are version v1 and remove the v1= prefix.

But with the payload we receive, we don’t have multiple signatures, just one. I’ll post an example below of the payload request we receive from PagerDuty (the signature and details are fake and just used as an example).

"headers": {
      "Accept": "application/json",
      "User-Agent": "PagerDuty-Webhook/V3.0",
      "X-PagerDuty-Signature": "v1=vu3js9c1dbfwky1gm99bo798e0yjsysggbxomgqkstvxtq0j2u9dn50esg5okqsv",
      "Content-Length": "620",
      "Content-Type": "application/json"
}

You see it is only one signature not two and it is not separated by a comma.

This is also reflected in the Javascript example code you provided in your documentation (https://developer.pagerduty.com/docs/webhooks/webhook-signatures/) which I believe is also wrong or outdated, as it requires you to split the signature string, which we can’t do.

Is the documentation wrong/outdated, or am I looking in the wrong place, if so how do we go about verifying PagerDuty v3 webhook signatures so we can start to make secure requests?

Thank You

Kind Regards
Simeon

It appears that you’ve also raised a support ticket for this - thank you for doing so, Simeon! My colleague responded and we will be happy to discuss this further on the ticket.

Hello

It’s taking some time for support to get back to me, please can you guide me on what I am doing wrong and why my signature checks are always failing.

I’ve posted an example below.

So for example, let’s say I wanted to use your Javascript code to verify the signature which is available in the documentation.

var PagerDutyVerifier = require(’./pagerduty_verifier.js’)
var verifier = new PagerDutyVerifier(key, version)
verifier.verify(payload, signatures)

And let’s say I had the header information sent to me from PagerDuty to verify a request.

"headers": {
        "Accept": "application/json",
        "User-Agent": "PagerDuty-Webhook/V3.0",
        "X-PagerDuty-Signature": "v1=54e121b4467b52c2f2840bc7683164a99c007cd7633b8a82d7c0b5c5e0a91aa4",
        "Content-Length": "620",
        "Content-Type": "application/json"
    }

And I also had the body of the request.

{
  "id": "PGR0VU2",
  "type": "incident",
  "self": "https://api.pagerduty.com/incidents/PGR0VU2",
  "html_url": "https://acme.pagerduty.com/incidents/PGR0VU2",
  "number": 2,
  "status": "triggered",
  "title": "A little bump in the road",
  "service": {
    "html_url": "https://acme.pagerduty.com/services/PF9KMXH",
    "id": "PF9KMXH",
    "self": "https://api.pagerduty.com/services/PF9KMXH",
    "summary": "API Service",
    "type": "service_reference"
  },
  "assignees": [
    {
      "html_url": "https://acme.pagerduty.com/users/PTUXL6G",
      "id": "PTUXL6G",
      "self": "https://api.pagerduty.com/users/PTUXL6G",
      "summary": "User 123",
      "type": "user_reference"
    }
  ],
  "escalation_policy": {
    "html_url": "https://acme.pagerduty.com/escalation_policies/PUS0KTE",
    "id": "PUS0KTE",
    "self": "https://api.pagerduty.com/escalation_policies/PUS0KTE",
    "summary": "Default",
    "type": "escalation_policy_reference"
  },
  "teams": [
    {
      "html_url": "https://acme.pagerduty.com/teams/PFCVPS0",
      "id": "PFCVPS0",
      "self": "https://api.pagerduty.com/teams/PFCVPS0",
      "summary": "Engineering",
      "type": "team_reference"
    }
  ],
  "priority": {
    "html_url": "https://acme.pagerduty.com/account/incident_priorities",
    "id": "PSO75BM",
    "self": "https://api.pagerduty.com/priorities/PSO75BM",
    "summary": "P1",
    "type": "priority_reference"
  },
  "urgency": "high",
  "conference_bridge": {
    "conference_number": "+1 1234123412,,987654321#",
    "conference_url": "https://example.com"
  },
  "resolve_reason": null
}

Please let me know if I’m setting my Javascript code correctly. So for example with all the code, I have listed above this is how I’m forming the code.

var version = 'v1'
var key = '/{PagerDuty Webhook Signing Payload Token}' //This was given to me when I created the webhook
var payload = {PagerDuty JSON Body Request}
var signatures = '54e121b4467b52c2f2840bc7683164a99c007cd7633b8a82d7c0b5c5e0a91aa4'

var PagerDutyVerifier = require('./pagerduty_verifier.js')
var verifier = new PagerDutyVerifier(key, version)
verifier.verify(payload, signatures)

I am doing this correctly.

Did I miss something?

I always seem to get a false result.

I REALLY need some assistance with this.

Hi Simon,

Your Support ticket has been raised internally for further inquiry about your question. The Support team also handles community posts and we would rather keep communication on one issue in one place. We will respond to you on the support ticket once we have further information.

Kindly,

Hi,

The answer will be useful for any customer. So please if there is anything to know about webhook v3 signature, share it there and update the doc accordingly. :wink:

2 Likes

An excellent point, Sébastien. At this time, the documentation is not outdated. The specific examples for signature verification show two signatures, but it is possible to have situations where only one signature will be present. So if anyone is seeing results similar to those in the original post, that still falls under expected behavior.

The documentation states: “The X-PagerDuty-Signature header included with each webhook event delivery contains one or more signatures.” (emphasis mine)

When we tested the logic that splits the string with signatures with a single signature example, it worked as expected from our end - an array consisting one signature was extracted.