ebay-notification_api-verifier 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 60cda4b6d6ee107c647cadc62792b4d42bc86ead57fd2882d93bfbfd9959f08a
4
+ data.tar.gz: cd96e6c6eeedc269db22262b8e972603f91405557b57e0f96123d3f9d521c18e
5
+ SHA512:
6
+ metadata.gz: 9416110f6d0187dd00ec7e9deca77820ef7dab56791a460ea33eaa89e11d5c6c3402c9d6daff001c23d8dd229ad4d7142cf211bf83c51dc5563d41fe45f1c602
7
+ data.tar.gz: fb79e686440f7652038795ba9097742d8068853b0eccedef8841d51db6f2bb09b67c5f3b032dad178e20b98820e2cbbadf7e5551dcadf2b9d69850d4307f47e6
@@ -0,0 +1,23 @@
1
+ name: RSpec
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ rspec:
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ fail-fast: false
15
+
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+ - uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: 2.7
21
+ bundler-cache: true
22
+ - name: Run RSpec
23
+ run: bundle exec rake spec
@@ -0,0 +1,22 @@
1
+ name: Standard
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ standard:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: 2.7
18
+ bundler-cache: true
19
+ - name: Install dependencies
20
+ run: bundle install --gemfile gemfiles/standard.gemfile
21
+ - name: Lint Ruby code with Standard
22
+ run: bundle exec --gemfile gemfiles/standard.gemfile standardrb
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /bin/
10
+ Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ require:
2
+ - standard/cop/semantic_blocks
3
+ - rubocop-md
4
+
5
+ inherit_gem:
6
+ standard: config/base.yml
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Change log
2
+
3
+ ## master
4
+
5
+ ## 0.1.0 (2021-04-20)
6
+
7
+ - Initial version ([@DmitryTsepelev][])
8
+
9
+ [@DmitryTsepelev]: https://github.com/DmitryTsepelev
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in ebay-notification_api-verifier.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 DmitryTsepelev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Ebay::NotificationApi::Verifier
2
+
3
+ The Ruby implementation of [eBay Notification API verification](https://developer.ebay.com/api-docs/commerce/notification/overview.html#use).
4
+
5
+ In future it might be used for different cases, but for now eBay requires third–party applications that store user data to implement [eBay Marketplace Account Deletion/Closure Notifications Workflow](https://developer.ebay.com/marketplace-account-deletion). When such HTTP request is received, the backend must ensure, that this request is coming from eBay:
6
+
7
+ ```ruby
8
+ class EbayAccountDeletionController < ApplicationController
9
+ def account_deletion_notification
10
+ # eBay wants an immediate response, so we should postpone the deletion
11
+ EbayAccountDeletionWorker.perform_async(params, request.headers["x-ebay-signature"])
12
+ head :ok
13
+ end
14
+ end
15
+
16
+ class EbayAccountDeletionWorker
17
+ include Sidekiq::Worker
18
+
19
+ def perform(message, signature)
20
+ return unless Ebay::NotificationApi::Verifier.valid_message?(message, signature)
21
+
22
+ # delete data
23
+ end
24
+ end
25
+ ```
26
+
27
+ ⚠️ Heads up! Currently eBay supports only ECDSA/SHA1 encryption, and so does the gem. If something different is passed to the Verifier, the Ebay::NotificationApi::Verifier::WrongAlgorithm would be raised. ⚠️
28
+
29
+ ## Installation
30
+
31
+ Add this line to your application's Gemfile:
32
+
33
+ ```ruby
34
+ gem 'ebay-notification_api-verifier'
35
+ ```
36
+
37
+ Since we have to perform a request to fetch the public key, the ability to get application token should be provided to the verifier. You can pass any callable object:
38
+
39
+ ```ruby
40
+ Ebay::NotificationApi::Verifier.application_token_proc = proc { "token" }
41
+ Ebay::NotificationApi::Verifier.application_token_proc = Ebay::TokenFetcher.fetch
42
+ ```
43
+
44
+ ## Contributing
45
+
46
+ Bug reports and pull requests are welcome on GitHub at https://github.com/dmitrytsepelev/ebay-notification_api-verifier.
47
+
48
+ ## License
49
+
50
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
51
+
52
+ <p align="center">
53
+ <a href="https://evilmartians.com/?utm_source=ebay-notification_api-verifier">
54
+ <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
55
+ </a>
56
+ </p>
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/ebay/notification_api/verifier/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ebay-notification_api-verifier"
7
+ spec.version = Ebay::NotificationApi::Verifier::VERSION
8
+ spec.authors = ["DmitryTsepelev"]
9
+ spec.email = ["dmitry.a.tsepelev@gmail.com"]
10
+
11
+ spec.summary = "The Ruby implementation of eBay Notification API verification"
12
+ spec.description = spec.summary
13
+ spec.homepage = "https://github.com/DmitryTsepelev/ebay-notification_api-verifier"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["changelog_uri"] = "https://github.com/DmitryTsepelev/ebay-notification_api-verifier/blob/main/Rakefile/CHANGELOG.md"
19
+
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
22
+ end
23
+
24
+ spec.require_paths = ["lib"]
25
+ spec.required_ruby_version = ">= 2.3"
26
+
27
+ spec.add_dependency "httparty", "~> 0.17"
28
+
29
+ spec.add_development_dependency "rspec", "~> 3.1"
30
+ end
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "standard", "~> 0.10.0"
4
+
5
+ gemspec path: "../"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "verifier/version"
4
+ require_relative "verifier/message_validator"
5
+
6
+ module Ebay
7
+ module NotificationApi
8
+ module Verifier
9
+ class WrongAlgorithm < StandardError; end
10
+
11
+ class << self
12
+ def valid_message?(*args)
13
+ MessageValidator.new(*args).valid_message?
14
+ end
15
+
16
+ def application_token_proc=(value)
17
+ unless value.respond_to?(:call)
18
+ raise ArgumentError, "application_token_proc is not a callable object"
19
+ end
20
+
21
+ @application_token_proc = value
22
+ end
23
+
24
+ def application_token
25
+ raise ArgumentError, "application_token_proc is not configured" unless @application_token_proc
26
+
27
+ @application_token_proc.call
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ require "httparty"
2
+
3
+ module Ebay
4
+ module NotificationApi
5
+ module Verifier
6
+ class MessageValidator
7
+ class WrongAlgorithm < StandardError; end
8
+
9
+ def initialize(message, signature_header)
10
+ @signature_header = signature_header
11
+ @message = message
12
+ end
13
+
14
+ def valid_message?
15
+ verifier = OpenSSL::PKey::EC.new(format_key(public_key_response["key"]))
16
+ signature_base64 = Base64.decode64(signature_json["signature"])
17
+ verifier.verify(OpenSSL::Digest.new(DIGEST), signature_base64, @message.to_json)
18
+ end
19
+
20
+ private
21
+
22
+ PUBLIC_KEY_ENDPOINT = "https://api.ebay.com/commerce/notification/v1/public_key/"
23
+ ALGORITHM = "ECDSA"
24
+ DIGEST = "SHA1"
25
+
26
+ def public_key_response
27
+ @public_key_response ||=
28
+ begin
29
+ token = Ebay::NotificationApi::Verifier.application_token
30
+ headers = {"Authorization" => "Bearer #{token}"}
31
+ public_key_url = "#{PUBLIC_KEY_ENDPOINT}#{signature_json["kid"]}"
32
+
33
+ HTTParty.get(public_key_url, headers: headers).tap do |response|
34
+ next if response["algorithm"] == ALGORITHM && response["digest"] == DIGEST
35
+ raise WrongAlgorithm
36
+ end
37
+ end
38
+ end
39
+
40
+ KEY_PATTERN_START = "-----BEGIN PUBLIC KEY-----"
41
+ KEY_PATTERN_END = "-----END PUBLIC KEY-----"
42
+
43
+ def format_key(key)
44
+ key.sub(KEY_PATTERN_START, "#{KEY_PATTERN_START}\n")
45
+ .sub(KEY_PATTERN_END, "\n#{KEY_PATTERN_END}")
46
+ end
47
+
48
+ def signature_json
49
+ @signature_json ||= JSON.parse(Base64.decode64(@signature_header))
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ebay
4
+ module NotificationApi
5
+ module Verifier
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ebay-notification_api-verifier
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - DmitryTsepelev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.17'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ description: The Ruby implementation of eBay Notification API verification
42
+ email:
43
+ - dmitry.a.tsepelev@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".github/workflows/rspec.yml"
49
+ - ".github/workflows/standard.yml"
50
+ - ".gitignore"
51
+ - ".rubocop.yml"
52
+ - CHANGELOG.md
53
+ - Gemfile
54
+ - LICENSE.txt
55
+ - README.md
56
+ - Rakefile
57
+ - ebay-notification_api-verifier.gemspec
58
+ - gemfiles/standard.gemfile
59
+ - lib/ebay/notification_api/verifier.rb
60
+ - lib/ebay/notification_api/verifier/message_validator.rb
61
+ - lib/ebay/notification_api/verifier/version.rb
62
+ homepage: https://github.com/DmitryTsepelev/ebay-notification_api-verifier
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ homepage_uri: https://github.com/DmitryTsepelev/ebay-notification_api-verifier
67
+ source_code_uri: https://github.com/DmitryTsepelev/ebay-notification_api-verifier
68
+ changelog_uri: https://github.com/DmitryTsepelev/ebay-notification_api-verifier/blob/main/Rakefile/CHANGELOG.md
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '2.3'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.1.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: The Ruby implementation of eBay Notification API verification
88
+ test_files: []