diff --git a/CHANGELOG.md b/CHANGELOG.md index 3589e4826..45190a69a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## Next Release + +- Fixes webhook validation when the `weight` field contains a float by converting it back into a float after conversion from a string (closes #467) + ## v7.5.1 (2024-08-09) - Adds missing properties to `Rate` model diff --git a/examples b/examples index 7bafcddd4..9447e72e0 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 7bafcddd4e7e9f11827a734784127773887443b1 +Subproject commit 9447e72e087b823445b8c3e1351d28c070a8e6b1 diff --git a/src/utils/util.js b/src/utils/util.js index 2153d8bb5..cef638968 100644 --- a/src/utils/util.js +++ b/src/utils/util.js @@ -120,9 +120,14 @@ export default class Utils { const normalizedSecret = webhookSecret.normalize('NFKD'); const encodedSecret = Buffer.from(normalizedSecret, 'utf8'); + // Fixes Javascript's float to string conversion. See https://github.com/EasyPost/easypost-node/issues/467 + const correctedEventBody = Buffer.from(eventBody) + .toString('utf8') + .replace(/("weight":)(\d+)(?!\.\d)/g, '$1$2.0'); + const expectedSignature = crypto .createHmac('sha256', encodedSecret) - .update(eventBody, 'utf-8') + .update(correctedEventBody, 'utf-8') .digest('hex'); const digest = `hmac-sha256-hex=${expectedSignature}`; diff --git a/test/helpers/fixture.js b/test/helpers/fixture.js index f4155de13..0b5ba09fc 100644 --- a/test/helpers/fixture.js +++ b/test/helpers/fixture.js @@ -42,10 +42,6 @@ export default class Fixture { return '2022-04-11'; } - static webhookUrl() { - return this.readFixtureData().webhook_url; - } - static caAddress1() { return this.readFixtureData().addresses.ca_address_1; } @@ -143,6 +139,18 @@ export default class Fixture { return Buffer.from(JSON.stringify(eventBody), 'utf8'); } + static webhookHmacSignature() { + return this.readFixtureData().webhook_hmac_signature; + } + + static webhookSecret() { + return this.readFixtureData().webhook_secret; + } + + static webhookUrl() { + return this.readFixtureData().webhook_url; + } + static plannedShipDate() { return '2024-08-01'; } diff --git a/test/services/webhook.test.js b/test/services/webhook.test.js index 3d1a1811e..389417fe0 100644 --- a/test/services/webhook.test.js +++ b/test/services/webhook.test.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import EasyPostClient from '../../src/easypost'; +import SignatureVerificationError from '../../src/errors/general/signature_verification_error'; import Webhook from '../../src/models/webhook'; import Fixture from '../helpers/fixture'; -import SignatureVerificationError from '../../src/errors/general/signature_verification_error'; import * as setupPolly from '../helpers/setup_polly'; import { withoutParams } from '../helpers/utils'; @@ -87,20 +87,17 @@ describe('Webhook Service', function () { }); it('validates a webhook secret', function () { - const webhookSecret = 'sécret'; - const expectedHmacSignature = - 'hmac-sha256-hex=e93977c8ccb20363d51a62b3fe1fc402b7829be1152da9e88cf9e8d07115a46b'; const headers = { - 'X-Hmac-Signature': expectedHmacSignature, + 'X-Hmac-Signature': Fixture.webhookHmacSignature(), }; const webhookBody = this.client.Utils.validateWebhook( Fixture.eventBody(), headers, - webhookSecret, + Fixture.webhookSecret(), ); - expect(webhookBody.description).to.equal('batch.created'); + expect(webhookBody.description).to.equal('tracker.updated'); }); it('throws an error when a webhook secret is a differing length', function () {