Skip to content

Commit e29e9d0

Browse files
Refactor/hmac validator (#151) (#216)
* Replace doubles with singles for style * Bring hmac validator test closer to real life * Tidy-up hmac validator code * Backwards compatibility aliasing Co-authored-by: Matas Zanevičius <[email protected]>
1 parent 80bc3f4 commit e29e9d0

File tree

2 files changed

+27
-35
lines changed

2 files changed

+27
-35
lines changed

lib/adyen/utils/hmac_validator.rb

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def valid_notification_hmac?(notification_request_item, hmac_key)
1515

1616
def valid_webhook_hmac?(webhook_request_item, hmac_key)
1717
expected_sign = calculate_webhook_hmac(webhook_request_item, hmac_key)
18-
merchant_sign = fetch(webhook_request_item, 'additionalData.hmacSignature')
18+
merchant_sign =
19+
webhook_request_item.dig('additionalData', 'hmacSignature')
1920

2021
expected_sign == merchant_sign
2122
end
@@ -29,29 +30,20 @@ def calculate_notification_hmac(notification_request_item, hmac_key)
2930
def calculate_webhook_hmac(webhook_request_item, hmac_key)
3031
data = data_to_sign(webhook_request_item)
3132

32-
Base64.strict_encode64(OpenSSL::HMAC.digest(HMAC_ALGORITHM, [hmac_key].pack('H*'), data))
33+
Base64.strict_encode64(
34+
OpenSSL::HMAC.digest(HMAC_ALGORITHM, [hmac_key].pack('H*'), data)
35+
)
3336
end
3437

38+
# TODO: Deprecate instead of aliasing
39+
alias valid_notification_hmac? valid_webhook_hmac?
40+
alias calculate_notification_hmac calculate_webhook_hmac
3541

3642
def data_to_sign(webhook_request_item)
37-
data = WEBHOOK_VALIDATION_KEYS.map { |key| fetch(webhook_request_item, key).to_s }
38-
.join(DATA_SEPARATOR)
39-
end
40-
41-
private
42-
43-
def fetch(hash, keys)
44-
value = hash
45-
keys.to_s.split('.').each do |key|
46-
value = if key.to_i.to_s == key
47-
value[key.to_i]
48-
else
49-
value[key].nil? ? value[key.to_sym] : value[key]
50-
end
51-
break if value.nil?
52-
end
53-
54-
value
43+
WEBHOOK_VALIDATION_KEYS
44+
.map { webhook_request_item.dig(*_1.split('.')).to_s }
45+
.compact
46+
.join(DATA_SEPARATOR)
5547
end
5648
end
5749
end

spec/utils/hmac_validator_spec.rb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
let(:expected_sign) { 'coqCmt/IZ4E3CzPvMY8zTjQVL5hYJUiBRg8UU+iCWo0=' }
77
let(:webhook_request_item) do
88
{
9-
additionalData: {
10-
hmacSignature: expected_sign
9+
'additionalData' => {
10+
'hmacSignature' => expected_sign
1111
},
12-
amount: {
13-
value: 1130,
14-
currency: 'EUR'
12+
'amount' => {
13+
'value' => 1130,
14+
'currency' => 'EUR'
1515
},
16-
pspReference: '7914073381342284',
17-
eventCode: 'AUTHORISATION',
18-
merchantAccountCode: 'TestMerchant',
19-
merchantReference: 'TestPayment-1407325143704',
20-
paymentMethod: 'visa',
21-
success: 'true'
16+
'pspReference' => '7914073381342284',
17+
'eventCode' => 'AUTHORISATION',
18+
'merchantAccountCode' => 'TestMerchant',
19+
'merchantReference' => 'TestPayment-1407325143704',
20+
'paymentMethod' => 'visa',
21+
'success' => 'true'
2222
}
2323
end
2424

@@ -44,22 +44,22 @@
4444
end
4545

4646
it 'should validate backslashes correctly' do
47-
webhook = JSON.parse(json_from_file("mocks/responses/Webhooks/backslash_webhook.json"))
47+
webhook = JSON.parse(json_from_file('mocks/responses/Webhooks/backslash_webhook.json'))
4848
expect(validator.valid_webhook_hmac?(webhook, '74F490DD33F7327BAECC88B2947C011FC02D014A473AAA33A8EC93E4DC069174')).to be true
4949
end
5050

5151
it 'should validate colons correctly' do
52-
webhook = JSON.parse(json_from_file("mocks/responses/Webhooks/colon_webhook.json"))
52+
webhook = JSON.parse(json_from_file('mocks/responses/Webhooks/colon_webhook.json'))
5353
expect(validator.valid_webhook_hmac?(webhook, '74F490DD33F7327BAECC88B2947C011FC02D014A473AAA33A8EC93E4DC069174')).to be true
5454
end
5555

5656
it 'should validate forward slashes correctly' do
57-
webhook = JSON.parse(json_from_file("mocks/responses/Webhooks/forwardslash_webhook.json"))
57+
webhook = JSON.parse(json_from_file('mocks/responses/Webhooks/forwardslash_webhook.json'))
5858
expect(validator.valid_webhook_hmac?(webhook, '74F490DD33F7327BAECC88B2947C011FC02D014A473AAA33A8EC93E4DC069174')).to be true
5959
end
6060

6161
it 'should validate mix of slashes and colon correctly' do
62-
webhook = JSON.parse(json_from_file("mocks/responses/Webhooks/mixed_webhook.json"))
62+
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
6565
end

0 commit comments

Comments
 (0)