Skip to content

Commit 940cbcd

Browse files
authored
HMAC validation bank webhooks (#243)
* log to console * log to console * Add HMAC validation for bank * Remove log to console
1 parent a95d758 commit 940cbcd

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

lib/adyen/services/checkout/payments_api.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def sessions(request, headers: {})
5656
endpoint = '/sessions'.gsub(/{.+?}/, '%s')
5757
endpoint = endpoint.gsub(%r{^/}, '')
5858
endpoint = format(endpoint)
59-
59+
6060
action = { method: 'post', url: endpoint }
6161
@client.call_adyen_api(@service, action, request, headers, @version)
6262
end

lib/adyen/utils/hmac_validator.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ def valid_notification_hmac?(notification_request_item, hmac_key)
1313
valid_webhook_hmac?(notification_request_item, hmac_key)
1414
end
1515

16+
# validates the HMAC signature of the NotificationRequestItem object. Use for webhooks that provide the
17+
# hmacSignature as part of the payload `AdditionalData` (i.e. Payments)
18+
#
19+
# @param webhook_request_item [Object] The webhook request item.
20+
# @param hmac_key [String] The HMAC key used to validate the payload.
21+
22+
# @return [Boolean] Returns true if the HMAC signature is valid, otherwise false.
1623
def valid_webhook_hmac?(webhook_request_item, hmac_key)
1724
expected_sign = calculate_webhook_hmac(webhook_request_item, hmac_key)
1825
merchant_sign =
@@ -21,12 +28,32 @@ def valid_webhook_hmac?(webhook_request_item, hmac_key)
2128
expected_sign == merchant_sign
2229
end
2330

31+
# validates the HMAC signature of a payload against an expected signature. Use for webhooks that provide the
32+
# hmacSignature in the HTTP header (i.e. Banking, Management API)
33+
#
34+
# @param hmac_signature [String] The HMAC signature to validate.
35+
# @param hmac_key [String] The HMAC key used to validate the payload.
36+
# @param payload [String] The webhook payload.
37+
38+
# @return [Boolean] Returns true if the HMAC signature is valid, otherwise false.
39+
def valid_webhook_payload_hmac?(hmac_signature, hmac_key, payload)
40+
expected_sign = calculate_webhook_payload_hmac(payload, hmac_key)
41+
puts(expected_sign)
42+
expected_sign == hmac_signature
43+
end
44+
2445
# <b>DEPRECATED:</b> Please use calculate_webhook_hmac() instead.
2546
def calculate_notification_hmac(notification_request_item, hmac_key)
2647
calculate_webhook_hmac(notification_request_item, hmac_key)
2748
end
2849

2950

51+
def calculate_webhook_payload_hmac(data, hmac_key)
52+
Base64.strict_encode64(
53+
OpenSSL::HMAC.digest(HMAC_ALGORITHM, [hmac_key].pack('H*'), data)
54+
)
55+
end
56+
3057
def calculate_webhook_hmac(webhook_request_item, hmac_key)
3158
data = data_to_sign(webhook_request_item)
3259

@@ -35,6 +62,7 @@ def calculate_webhook_hmac(webhook_request_item, hmac_key)
3562
)
3663
end
3764

65+
3866
# TODO: Deprecate instead of aliasing
3967
alias valid_notification_hmac? valid_webhook_hmac?
4068
alias calculate_notification_hmac calculate_webhook_hmac

spec/utils/hmac_validator_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@
6262
webhook = JSON.parse(json_from_file('mocks/responses/Webhooks/mixed_webhook.json'))
6363
expect(validator.valid_webhook_hmac?(webhook, '74F490DD33F7327BAECC88B2947C011FC02D014A473AAA33A8EC93E4DC069174')).to be true
6464
end
65+
66+
it 'should have an invalid payload hmac' do
67+
hmac_signature = "wrong signature"
68+
payload = json_from_file('mocks/responses/Webhooks/mixed_webhook.json')
69+
70+
expect(validator.valid_webhook_payload_hmac?(hmac_signature, key, payload)).to be false
71+
end
72+
73+
it 'should have an valid payload hmac' do
74+
hmac_signature = "93Av9t6OVkYCrVHU/xgiTkWGbulJz+Vcm2qO4TYQH2Q="
75+
payload = json_from_file('mocks/responses/Webhooks/mixed_webhook.json')
76+
77+
expect(validator.valid_webhook_payload_hmac?(hmac_signature, key, payload)).to be true
78+
end
79+
6580
end
6681
end
6782
# rubocop:enable Metrics/BlockLength

0 commit comments

Comments
 (0)