workflow-webhook icon indicating copy to clipboard operation
workflow-webhook copied to clipboard

Webhook Signature cannot be verified in AzureFunctions V4

Open ankitatdnv opened this issue 11 months ago • 2 comments

Hi,

I am trying to use this action for invoking a webhook with custom data, but I am not able to verify the Signature sent by the webhook, I have tried both SHA256 and SHA1 signatures. I am using the latest version 3.0.8

Please find below the code snippet, along with the data:

Action Step:

uses: distributhor/[email protected]
with:
       event_name: 'drift-check'
       webhook_url: ${{ vars.DRIFT_CHECK_WEBHOOK_URL }}
       webhook_secret: 'TestPassword'
       data: '{ "projectId": "1285", "groupId" : "grp_0001", "resourceId" : "5bc530b0-401c-5861-bce8-cccbf0ff25a1", "planOutput" : "2" }'

Payload:

{"event":"drift-check","repository":"dnv-cloud-infra/gssit-azure-webapp-iac","commit":"b739ebcf4625ff7897de579bfe664a905ab6e509","ref":"refs/heads/main","head":null,"workflow":"DriftCheck","requestID":"8ef0834a-326f-4eb5-970d-84510bbf19d6","data":{"projectId":"1285","groupId":"grp_0001","resourceId":"5bc530b0-401c-5861-bce8-cccbf0ff25a1","planOutput":"2"}}

Secret: TestPassword SHA-256 signature: sha256=77e5604907ed911d5e402e8ef42b5f2ee666f1709ea81cd347d69e28330ba248 SHA1 signature: sha1=a4ad993d459da604fe1d4e4db36a5f789efdb756

Code Snippet:

const body = await request.text();
const hmac = crypto.createHmac('sha1', 'TestPassword');
hmac.update(body);  
const sha1Signature = 'sha1='+hmac.digest('hex');

Generated SHA1: sha1=ff2046bbfc2a4caf3b39d93504772291869dbdf2

Also I have tried to verify the signature using GitHub octokit library, but without any luck.

ankitatdnv avatar Jan 13 '25 13:01 ankitatdnv

The webhook is currently being used in various production scenarios. I would have to try and recreate the problem you experience. Could you maybe try using request.rawBody instead of request.text and see if it makes a difference?

const signatureSha256 =
    "sha256=" + crypto
      .createHmac("sha256", secret)
      .update(req.rawBody)
      .digest("hex");

distributhor avatar Jan 13 '25 13:01 distributhor

@distributhor , Thanks for the quick reply, Actually I am using the Azure functions V4, which have only following operations to read the body:

const body = await request.text(); // Returns a promise fulfilled with the body as a string
const body = await request.json(); // Returns a promise fulfilled with the body parsed as JSON
const body = await request.formData(); // Returns a promise fulfilled with the body as FormData
const body = await request.arrayBuffer(); //Returns a promise fulfilled with the body as an ArrayBuffer
const body = await request.blob(); // Returns a promise fulfilled with the body as a Blob

I have tested with text(), json(), arrayBuffer, but no luck.

I have tried to generate the signature using following openssl commands in my local machine and got the exact signature as given by the node crypto library: WEBHOOK_SIGNATURE=$(echo -n "$WEBHOOK_DATA" | openssl dgst -sha1 -hmac "$webhook_secret" -binary | xxd -p) WEBHOOK_SIGNATURE_256=$(echo -n "$WEBHOOK_DATA" | openssl dgst -sha256 -hmac "$webhook_secret" -binary | xxd -p |tr -d '\n')

It looks like something is different in body when signature is calculated in GitHub environment and the API.

ankitatdnv avatar Jan 13 '25 16:01 ankitatdnv