ey-hmac 2.0.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +35 -0
- data/CHANGELOG.md +68 -0
- data/Gemfile +4 -2
- data/ey-hmac.gemspec +18 -14
- data/lib/ey-hmac/adapter/faraday.rb +38 -16
- data/lib/ey-hmac/adapter/rack.rb +15 -9
- data/lib/ey-hmac/adapter.rb +43 -12
- data/lib/ey-hmac/version.rb +1 -1
- data/lib/ey-hmac.rb +6 -6
- data/spec/faraday_spec.rb +6 -10
- data/spec/shared/authenticated.rb +20 -0
- data/spec/spec_helper.rb +1 -0
- metadata +21 -21
- data/.travis.yml +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 780a6fcc90418a0389166a31e520337dced06873038bb0a9e71a6f3b70996835
|
|
4
|
+
data.tar.gz: 073f26a6c11bd06036e23a49b50e8ffea15ca70c608d05e0e7be1a0b7547cda7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f0b5f2b1827e7a180b35ffa2d3b2e2918a470d008735dbb5b5b79430ac2201c7d58a5abcf124f5ee69119ab83b2b882f9802b70e0f00208df130f9974fc82e2f
|
|
7
|
+
data.tar.gz: 8d5b959e371034a6a436f7bfec4602e4e477a9830b6d67a6fc2e23378d5002fb2fbbd3714a635b8efe579bcf4f07316176be42ae90985317a86f72e2d7c57a15
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
2
|
+
# They are provided by a third-party and are governed by
|
|
3
|
+
# separate terms of service, privacy policy, and support
|
|
4
|
+
# documentation.
|
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
|
7
|
+
|
|
8
|
+
name: Ruby
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [ master ]
|
|
13
|
+
pull_request:
|
|
14
|
+
branches: [ master ]
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
strategy:
|
|
21
|
+
matrix:
|
|
22
|
+
ruby-version: ['2.5', '2.6', '2.7', '3.0']
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v2
|
|
26
|
+
- name: Set up Ruby
|
|
27
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
|
28
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
|
29
|
+
# uses: ruby/setup-ruby@v1
|
|
30
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
|
31
|
+
with:
|
|
32
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
33
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
## [v2.2.0](https://github.com/engineyard/hmac/tree/v2.2.0) (2017-01-09)
|
|
4
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v2.1.0...v2.2.0)
|
|
5
|
+
|
|
6
|
+
**Closed issues:**
|
|
7
|
+
|
|
8
|
+
- :sha512 and :sha384 [\#4](https://github.com/engineyard/hmac/issues/4)
|
|
9
|
+
|
|
10
|
+
**Merged pull requests:**
|
|
11
|
+
|
|
12
|
+
- use Base64\#strict\_encode64 when signing requests [\#5](https://github.com/engineyard/hmac/pull/5) ([lanej](https://github.com/lanej))
|
|
13
|
+
|
|
14
|
+
## [v2.1.0](https://github.com/engineyard/hmac/tree/v2.1.0) (2015-12-03)
|
|
15
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v2.0.2...v2.1.0)
|
|
16
|
+
|
|
17
|
+
**Merged pull requests:**
|
|
18
|
+
|
|
19
|
+
- add optional server-side HMAC TTL to prevent replay attacks [\#3](https://github.com/engineyard/hmac/pull/3) ([hudon](https://github.com/hudon))
|
|
20
|
+
|
|
21
|
+
## [v2.0.2](https://github.com/engineyard/hmac/tree/v2.0.2) (2015-09-17)
|
|
22
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v2.0.1...v2.0.2)
|
|
23
|
+
|
|
24
|
+
## [v2.0.1](https://github.com/engineyard/hmac/tree/v2.0.1) (2015-09-17)
|
|
25
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v2.0.0...v2.0.1)
|
|
26
|
+
|
|
27
|
+
**Merged pull requests:**
|
|
28
|
+
|
|
29
|
+
- update faraday usage in the readme [\#2](https://github.com/engineyard/hmac/pull/2) ([svarks](https://github.com/svarks))
|
|
30
|
+
|
|
31
|
+
## [v2.0.0](https://github.com/engineyard/hmac/tree/v2.0.0) (2014-08-09)
|
|
32
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v1.0.0...v2.0.0)
|
|
33
|
+
|
|
34
|
+
## [v1.0.0](https://github.com/engineyard/hmac/tree/v1.0.0) (2014-04-29)
|
|
35
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.1.3...v1.0.0)
|
|
36
|
+
|
|
37
|
+
## [v0.1.3](https://github.com/engineyard/hmac/tree/v0.1.3) (2014-04-29)
|
|
38
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.1.2...v0.1.3)
|
|
39
|
+
|
|
40
|
+
## [v0.1.2](https://github.com/engineyard/hmac/tree/v0.1.2) (2014-04-01)
|
|
41
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.1.1...v0.1.2)
|
|
42
|
+
|
|
43
|
+
**Merged pull requests:**
|
|
44
|
+
|
|
45
|
+
- Fix deprecated usage of Digest::Digest. [\#1](https://github.com/engineyard/hmac/pull/1) ([ericlathrop](https://github.com/ericlathrop))
|
|
46
|
+
|
|
47
|
+
## [v0.1.1](https://github.com/engineyard/hmac/tree/v0.1.1) (2014-02-19)
|
|
48
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.1.0...v0.1.1)
|
|
49
|
+
|
|
50
|
+
## [v0.1.0](https://github.com/engineyard/hmac/tree/v0.1.0) (2014-02-18)
|
|
51
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.0.5...v0.1.0)
|
|
52
|
+
|
|
53
|
+
## [v0.0.5](https://github.com/engineyard/hmac/tree/v0.0.5) (2013-10-18)
|
|
54
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.0.4...v0.0.5)
|
|
55
|
+
|
|
56
|
+
## [v0.0.4](https://github.com/engineyard/hmac/tree/v0.0.4) (2013-02-08)
|
|
57
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.0.3...v0.0.4)
|
|
58
|
+
|
|
59
|
+
## [v0.0.3](https://github.com/engineyard/hmac/tree/v0.0.3) (2013-02-06)
|
|
60
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.0.2...v0.0.3)
|
|
61
|
+
|
|
62
|
+
## [v0.0.2](https://github.com/engineyard/hmac/tree/v0.0.2) (2013-02-05)
|
|
63
|
+
[Full Changelog](https://github.com/engineyard/hmac/compare/v0.0.1...v0.0.2)
|
|
64
|
+
|
|
65
|
+
## [v0.0.1](https://github.com/engineyard/hmac/tree/v0.0.1) (2013-02-05)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Gemfile
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
source 'https://rubygems.org'
|
|
2
4
|
|
|
3
5
|
# Specify your gem's dependencies in ey-hmac.gemspec
|
|
@@ -10,11 +12,11 @@ end
|
|
|
10
12
|
|
|
11
13
|
group(:rack) do
|
|
12
14
|
gem 'rack'
|
|
13
|
-
gem 'rack-test'
|
|
14
15
|
gem 'rack-client'
|
|
16
|
+
gem 'rack-test'
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
group(:faraday) do
|
|
18
|
-
gem 'faraday', '~>
|
|
20
|
+
gem 'faraday', '~> 1.3'
|
|
19
21
|
gem 'faraday_middleware'
|
|
20
22
|
end
|
data/ey-hmac.gemspec
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'English'
|
|
4
|
+
require File.expand_path('lib/ey-hmac/version', __dir__)
|
|
3
5
|
|
|
4
6
|
Gem::Specification.new do |gem|
|
|
5
|
-
gem.name =
|
|
7
|
+
gem.name = 'ey-hmac'
|
|
6
8
|
gem.version = Ey::Hmac::VERSION
|
|
7
|
-
gem.authors = [
|
|
8
|
-
gem.email = [
|
|
9
|
-
gem.description =
|
|
10
|
-
gem.summary =
|
|
11
|
-
gem.homepage =
|
|
9
|
+
gem.authors = ['Josh Lane']
|
|
10
|
+
gem.email = ['me@joshualane.com']
|
|
11
|
+
gem.description = 'Lightweight HMAC signing libraries and middleware for Farday and Rack'
|
|
12
|
+
gem.summary = 'Lightweight HMAC signing libraries and middleware for Farday and Rack'
|
|
13
|
+
gem.homepage = ''
|
|
12
14
|
|
|
13
|
-
gem.files = `git ls-files`.split(
|
|
14
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
15
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
|
15
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
16
|
-
gem.require_paths = [
|
|
17
|
-
gem.license =
|
|
18
|
+
gem.require_paths = ['lib']
|
|
19
|
+
gem.license = 'MIT'
|
|
20
|
+
|
|
21
|
+
gem.required_ruby_version = '>= 2.5'
|
|
18
22
|
|
|
19
|
-
gem.add_development_dependency
|
|
20
|
-
gem.add_development_dependency
|
|
23
|
+
gem.add_development_dependency 'bundler', '~> 2.3'
|
|
24
|
+
gem.add_development_dependency 'rake'
|
|
21
25
|
end
|
|
@@ -4,21 +4,29 @@ class Ey::Hmac::Adapter::Faraday < Ey::Hmac::Adapter
|
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
def content_type
|
|
7
|
-
|
|
7
|
+
@content_type ||= find_header(
|
|
8
|
+
*%w[CONTENT-TYPE CONTENT_TYPE Content-Type Content_Type]
|
|
9
|
+
)
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def content_digest
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
@content_digest ||= find_header(
|
|
14
|
+
*%w[CONTENT-DIGEST CONTENT_DIGEST Content-Digest Content_Digest]
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def set_content_digest
|
|
19
|
+
return if content_digest
|
|
20
|
+
|
|
21
|
+
digestable = if body.respond_to?(:rewind)
|
|
22
|
+
body.rewind
|
|
23
|
+
body.read.tap { |_| body.rewind }
|
|
24
|
+
else
|
|
25
|
+
body.to_s
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if digestable && digestable != ""
|
|
29
|
+
@content_digest = request[:request_headers]['Content-Digest'] = Digest::MD5.hexdigest(digestable)
|
|
22
30
|
end
|
|
23
31
|
end
|
|
24
32
|
|
|
@@ -29,8 +37,13 @@ class Ey::Hmac::Adapter::Faraday < Ey::Hmac::Adapter
|
|
|
29
37
|
end
|
|
30
38
|
|
|
31
39
|
def date
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
find_header(*%w[DATE Date])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def set_date
|
|
44
|
+
unless date
|
|
45
|
+
request[:request_headers]['Date'] = Time.now.httpdate
|
|
46
|
+
end
|
|
34
47
|
end
|
|
35
48
|
|
|
36
49
|
def path
|
|
@@ -38,7 +51,8 @@ class Ey::Hmac::Adapter::Faraday < Ey::Hmac::Adapter
|
|
|
38
51
|
end
|
|
39
52
|
|
|
40
53
|
def sign!(key_id, key_secret)
|
|
41
|
-
|
|
54
|
+
set_content_digest
|
|
55
|
+
set_date
|
|
42
56
|
|
|
43
57
|
if options[:version]
|
|
44
58
|
request[:request_headers]['X-Signature-Version'] = options[:version]
|
|
@@ -48,6 +62,14 @@ class Ey::Hmac::Adapter::Faraday < Ey::Hmac::Adapter
|
|
|
48
62
|
end
|
|
49
63
|
|
|
50
64
|
def authorization_signature
|
|
51
|
-
|
|
65
|
+
find_header(*%w[Authorization AUTHORIZATION])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def find_header(*keys)
|
|
71
|
+
value = nil
|
|
72
|
+
keys.find { |k| value = request[:request_headers][k] }
|
|
73
|
+
value
|
|
52
74
|
end
|
|
53
75
|
end
|
data/lib/ey-hmac/adapter/rack.rb
CHANGED
|
@@ -3,10 +3,7 @@ require 'rack'
|
|
|
3
3
|
class Ey::Hmac::Adapter::Rack < Ey::Hmac::Adapter
|
|
4
4
|
def initialize(request, options)
|
|
5
5
|
super
|
|
6
|
-
@request =
|
|
7
|
-
::Rack::Request.new(request)
|
|
8
|
-
else request
|
|
9
|
-
end
|
|
6
|
+
@request = request.is_a?(Hash) ? ::Rack::Request.new(request) : request
|
|
10
7
|
end
|
|
11
8
|
|
|
12
9
|
def method
|
|
@@ -18,10 +15,12 @@ class Ey::Hmac::Adapter::Rack < Ey::Hmac::Adapter
|
|
|
18
15
|
end
|
|
19
16
|
|
|
20
17
|
def content_digest
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
request.env['HTTP_CONTENT_DIGEST']
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def set_content_digest
|
|
22
|
+
if body
|
|
23
|
+
request.env['HTTP_CONTENT_DIGEST'] = Digest::MD5.hexdigest(body)
|
|
25
24
|
end
|
|
26
25
|
end
|
|
27
26
|
|
|
@@ -36,7 +35,11 @@ class Ey::Hmac::Adapter::Rack < Ey::Hmac::Adapter
|
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
def date
|
|
39
|
-
request.env['HTTP_DATE']
|
|
38
|
+
request.env['HTTP_DATE']
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def set_date
|
|
42
|
+
request.env['HTTP_DATE'] = Time.now.httpdate
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
def path
|
|
@@ -44,6 +47,9 @@ class Ey::Hmac::Adapter::Rack < Ey::Hmac::Adapter
|
|
|
44
47
|
end
|
|
45
48
|
|
|
46
49
|
def sign!(key_id, key_secret)
|
|
50
|
+
set_date
|
|
51
|
+
set_content_digest
|
|
52
|
+
|
|
47
53
|
if options[:version]
|
|
48
54
|
request.env['HTTP_X_SIGNATURE_VERSION'] = options[:version]
|
|
49
55
|
end
|
data/lib/ey-hmac/adapter.rb
CHANGED
|
@@ -10,6 +10,7 @@ class Ey::Hmac::Adapter
|
|
|
10
10
|
|
|
11
11
|
# @param [Object] request signer-specific request implementation
|
|
12
12
|
# @option options [Integer] :version signature version
|
|
13
|
+
# @option options [Integer] :ttl (nil) duration during which HMAC is valid after signed date
|
|
13
14
|
# @option options [String] :authorization_header ('Authorization') Authorization header key.
|
|
14
15
|
# @option options [String] :server ('EyHmac') service name prefixed to {#authorization}. set to {#service}
|
|
15
16
|
# @option options [Symbol] :sign_with (:sha_256) outgoing signature digest algorithm. See {OpenSSL::Digest#new}
|
|
@@ -17,6 +18,7 @@ class Ey::Hmac::Adapter
|
|
|
17
18
|
def initialize(request, options={})
|
|
18
19
|
@request, @options = request, options
|
|
19
20
|
|
|
21
|
+
@ttl = options[:ttl]
|
|
20
22
|
@authorization_header = options[:authorization_header] || 'Authorization'
|
|
21
23
|
@service = options[:service] || 'EyHmac'
|
|
22
24
|
@sign_with = options[:sign_with] || :sha256
|
|
@@ -35,7 +37,9 @@ class Ey::Hmac::Adapter
|
|
|
35
37
|
# @param [String] signature digest hash function. Defaults to #sign_with
|
|
36
38
|
# @return [String] HMAC signature of {#request}
|
|
37
39
|
def signature(key_secret, digest = self.sign_with)
|
|
38
|
-
Base64.
|
|
40
|
+
Base64.strict_encode64(
|
|
41
|
+
OpenSSL::HMAC.digest(
|
|
42
|
+
OpenSSL::Digest.new(digest.to_s), key_secret, canonicalize)).strip
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# @param [String] key_id public HMAC key
|
|
@@ -110,26 +114,30 @@ class Ey::Hmac::Adapter
|
|
|
110
114
|
|
|
111
115
|
# @see Ey::Hmac#authenticate!
|
|
112
116
|
def authenticated!(&block)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
key_id = authorization_match[1]
|
|
118
|
-
signature_value = authorization_match[2]
|
|
117
|
+
key_id, signature_value = check_signature!
|
|
118
|
+
key_secret = block.call(key_id)
|
|
119
119
|
|
|
120
|
-
unless key_secret
|
|
121
|
-
raise
|
|
120
|
+
unless key_secret
|
|
121
|
+
raise Ey::Hmac::MissingSecret,
|
|
122
|
+
"Failed to find secret matching #{key_id.inspect}"
|
|
122
123
|
end
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
check_ttl!
|
|
125
126
|
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
calculated_signatures = accept_digests.map { |ad| signature(key_secret, ad) }
|
|
128
|
+
matching_signature = calculated_signatures.any? { |cs| secure_compare(signature_value, cs) }
|
|
129
|
+
|
|
130
|
+
unless matching_signature
|
|
131
|
+
raise Ey::Hmac::SignatureMismatch,
|
|
132
|
+
"Calculated signature #{signature_value} does not match #{calculated_signatures.inspect} using #{canonicalize.inspect}"
|
|
128
133
|
end
|
|
134
|
+
|
|
129
135
|
true
|
|
130
136
|
end
|
|
131
137
|
alias authenticate! authenticated!
|
|
132
138
|
|
|
139
|
+
protected
|
|
140
|
+
|
|
133
141
|
# Constant time string comparison.
|
|
134
142
|
# pulled from https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L399
|
|
135
143
|
def secure_compare(a, b)
|
|
@@ -141,4 +149,27 @@ class Ey::Hmac::Adapter
|
|
|
141
149
|
b.each_byte { |v| r |= v ^ l[i+=1] }
|
|
142
150
|
r == 0
|
|
143
151
|
end
|
|
152
|
+
|
|
153
|
+
def check_ttl!
|
|
154
|
+
if @ttl && date
|
|
155
|
+
expiry = Time.parse(date).to_i + @ttl
|
|
156
|
+
current_time = Time.now.to_i
|
|
157
|
+
|
|
158
|
+
unless expiry > current_time
|
|
159
|
+
raise Ey::Hmac::ExpiredHmac,
|
|
160
|
+
"Signature has expired passed #{expiry}. Current time is #{current_time}"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def check_signature!
|
|
166
|
+
authorization_match = AUTHORIZATION_REGEXP.match(authorization_signature)
|
|
167
|
+
|
|
168
|
+
unless authorization_match
|
|
169
|
+
raise Ey::Hmac::MissingAuthorization,
|
|
170
|
+
"Failed to parse authorization_signature #{authorization_signature}"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
[authorization_match[1], authorization_match[2]]
|
|
174
|
+
end
|
|
144
175
|
end
|
data/lib/ey-hmac/version.rb
CHANGED
data/lib/ey-hmac.rb
CHANGED
|
@@ -3,6 +3,7 @@ require "ey-hmac/version"
|
|
|
3
3
|
require 'base64'
|
|
4
4
|
require 'digest/md5'
|
|
5
5
|
require 'openssl'
|
|
6
|
+
require 'time'
|
|
6
7
|
|
|
7
8
|
module Ey
|
|
8
9
|
module Hmac
|
|
@@ -11,6 +12,7 @@ module Ey
|
|
|
11
12
|
MissingSecret = Class.new(Error)
|
|
12
13
|
MissingAuthorization = Class.new(Error)
|
|
13
14
|
SignatureMismatch = Class.new(Error)
|
|
15
|
+
ExpiredHmac = Class.new(Error)
|
|
14
16
|
|
|
15
17
|
autoload :Adapter, "ey-hmac/adapter"
|
|
16
18
|
autoload :Faraday, "ey-hmac/faraday"
|
|
@@ -21,12 +23,10 @@ module Ey
|
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def self.default_adapter
|
|
24
|
-
@default_adapter ||=
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Ey::Hmac::Adapter::Rails
|
|
29
|
-
end
|
|
26
|
+
@default_adapter ||= if defined?(::Rack) || defined?(::Rails)
|
|
27
|
+
Ey::Hmac::Adapter::Rack
|
|
28
|
+
elsif defined?(::Faraday)
|
|
29
|
+
Ey::Hmac::Adapter::Faraday
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
data/spec/faraday_spec.rb
CHANGED
|
@@ -38,8 +38,7 @@ describe "faraday" do
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
it "signs and reads a request" do
|
|
41
|
-
request = Faraday::Request.
|
|
42
|
-
r.method = :get
|
|
41
|
+
request = Faraday::Request.create(:get) { |r|
|
|
43
42
|
r.path = "/auth"
|
|
44
43
|
r.body = "{1: 2}"
|
|
45
44
|
r.headers = {"Content-Type" => "application/xml"}
|
|
@@ -49,8 +48,8 @@ describe "faraday" do
|
|
|
49
48
|
|
|
50
49
|
Ey::Hmac.sign!(request, key_id, key_secret, adapter: adapter)
|
|
51
50
|
|
|
52
|
-
expect(request[:request_headers]['Authorization']).to
|
|
53
|
-
expect(request[:request_headers]['Content-Digest']).to
|
|
51
|
+
expect(request[:request_headers]['Authorization']).to start_with("EyHmac")
|
|
52
|
+
expect(request[:request_headers]['Content-Digest']).to eq(Digest::MD5.hexdigest(request[:body]))
|
|
54
53
|
expect(Time.parse(request[:request_headers]['Date'])).not_to be_nil
|
|
55
54
|
|
|
56
55
|
yielded = false
|
|
@@ -65,8 +64,7 @@ describe "faraday" do
|
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
it "does not set Content-Digest if body is nil" do
|
|
68
|
-
request = Faraday::Request.
|
|
69
|
-
r.method = :get
|
|
67
|
+
request = Faraday::Request.create(:get) { |r|
|
|
70
68
|
r.path = "/auth"
|
|
71
69
|
r.body = nil
|
|
72
70
|
r.headers = {"Content-Type" => "application/xml"}
|
|
@@ -92,8 +90,7 @@ describe "faraday" do
|
|
|
92
90
|
end
|
|
93
91
|
|
|
94
92
|
it "does not set Content-Digest if body is empty" do
|
|
95
|
-
request = Faraday::Request.
|
|
96
|
-
r.method = :get
|
|
93
|
+
request = Faraday::Request.create(:get) do |r|
|
|
97
94
|
r.path = "/auth"
|
|
98
95
|
r.body = ""
|
|
99
96
|
r.headers = {"Content-Type" => "application/xml"}
|
|
@@ -118,8 +115,7 @@ describe "faraday" do
|
|
|
118
115
|
|
|
119
116
|
context "with a request" do
|
|
120
117
|
let!(:request) do
|
|
121
|
-
Faraday::Request.
|
|
122
|
-
r.method = :get
|
|
118
|
+
Faraday::Request.create(:get) do |r|
|
|
123
119
|
r.path = "/auth"
|
|
124
120
|
r.body = "{1: 2}"
|
|
125
121
|
r.headers = {"Content-Type" => "application/xml"}
|
|
@@ -51,5 +51,25 @@ shared_examples_for "authentication" do
|
|
|
51
51
|
end).to be_falsey
|
|
52
52
|
}.to raise_exception(Ey::Hmac::MissingAuthorization)
|
|
53
53
|
end
|
|
54
|
+
|
|
55
|
+
context "when the server specifies an HMAC TTL" do
|
|
56
|
+
it "should not authenticate expired hmac" do
|
|
57
|
+
Ey::Hmac.sign!(request, key_id, key_secret, adapter: adapter)
|
|
58
|
+
expect {
|
|
59
|
+
Ey::Hmac.authenticate!(request, adapter: adapter, ttl: 0) do |auth_id|
|
|
60
|
+
(auth_id == key_id) && key_secret
|
|
61
|
+
end
|
|
62
|
+
}.to raise_exception(Ey::Hmac::ExpiredHmac)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should authenticate non-expired hmac" do
|
|
66
|
+
Ey::Hmac.sign!(request, key_id, key_secret, adapter: adapter)
|
|
67
|
+
expect {
|
|
68
|
+
Ey::Hmac.authenticate!(request, adapter: adapter, ttl: 100) do |auth_id|
|
|
69
|
+
(auth_id == key_id) && key_secret
|
|
70
|
+
end
|
|
71
|
+
}.to_not raise_exception
|
|
72
|
+
end
|
|
73
|
+
end
|
|
54
74
|
end
|
|
55
75
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,52 +1,53 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ey-hmac
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0
|
|
4
|
+
version: 2.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
- Josh Lane
|
|
8
|
-
autorequire:
|
|
7
|
+
- Josh Lane
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-02-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.3'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '2.3'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
40
|
+
version: '0'
|
|
41
41
|
description: Lightweight HMAC signing libraries and middleware for Farday and Rack
|
|
42
42
|
email:
|
|
43
|
-
-
|
|
43
|
+
- me@joshualane.com
|
|
44
44
|
executables: []
|
|
45
45
|
extensions: []
|
|
46
46
|
extra_rdoc_files: []
|
|
47
47
|
files:
|
|
48
|
+
- ".github/workflows/ruby.yml"
|
|
48
49
|
- ".gitignore"
|
|
49
|
-
-
|
|
50
|
+
- CHANGELOG.md
|
|
50
51
|
- Gemfile
|
|
51
52
|
- LICENSE.txt
|
|
52
53
|
- README.md
|
|
@@ -67,7 +68,7 @@ homepage: ''
|
|
|
67
68
|
licenses:
|
|
68
69
|
- MIT
|
|
69
70
|
metadata: {}
|
|
70
|
-
post_install_message:
|
|
71
|
+
post_install_message:
|
|
71
72
|
rdoc_options: []
|
|
72
73
|
require_paths:
|
|
73
74
|
- lib
|
|
@@ -75,16 +76,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
75
76
|
requirements:
|
|
76
77
|
- - ">="
|
|
77
78
|
- !ruby/object:Gem::Version
|
|
78
|
-
version: '
|
|
79
|
+
version: '2.5'
|
|
79
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
81
|
requirements:
|
|
81
82
|
- - ">="
|
|
82
83
|
- !ruby/object:Gem::Version
|
|
83
84
|
version: '0'
|
|
84
85
|
requirements: []
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
signing_key:
|
|
86
|
+
rubygems_version: 3.1.6
|
|
87
|
+
signing_key:
|
|
88
88
|
specification_version: 4
|
|
89
89
|
summary: Lightweight HMAC signing libraries and middleware for Farday and Rack
|
|
90
90
|
test_files:
|