api-auth 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0fd8e9563fd57370a49c2c3b909432df2047bca
4
- data.tar.gz: 4e3ca050145a2e8271e904f852ac43ad608dd5e9
3
+ metadata.gz: 92c46c40ca59ec931c02893f62155ea3efdfba48
4
+ data.tar.gz: ac4c5514140b61f5df1b81408898413aef553cf7
5
5
  SHA512:
6
- metadata.gz: 717a5e94e609715659eb3355c062436962ba93fb0352d05041fe85604fb4cd7bbd3d4c460595c944c7a14fba2705960637026b2d66d8b5d63a328c845c96e9b8
7
- data.tar.gz: 8edeaa5acf7c890900531441ea137bbf59264ec99862896bd2f168232899b9451d34930813a21bfbe50d761ad1e41f84eb431ead00d5620fc56e1aaffa042632
6
+ metadata.gz: 38370d16d830ae325f862f972b20d267da8135750e923520df5902662cae46b4244a79d1520ec15b9ca4722f76018f88bfbb874bc4b64fd44f70b36f8402d018
7
+ data.tar.gz: c3a16015aa11cd3da2b296d5729b3c7f0fccdea1e5a8005a98a4b7465e95944a951afdb9a474f182e1ff3df996d5d36e369f37f2cc60ed9e9eaf6c9e82c04985
@@ -4,8 +4,9 @@ cache: bundler
4
4
  rvm:
5
5
  - 1.8.7-p374
6
6
  - 1.9.3
7
- - 2.1.5
8
- - 2.2.1
7
+ - 2.1.9
8
+ - 2.2.5
9
+ - 2.3.1
9
10
  gemfile:
10
11
  - gemfiles/rails_23.gemfile
11
12
  - gemfiles/rails_30.gemfile
@@ -14,6 +15,13 @@ gemfile:
14
15
  - gemfiles/rails_4.gemfile
15
16
  - gemfiles/rails_41.gemfile
16
17
  - gemfiles/rails_42.gemfile
18
+ - gemfiles/rails_5.gemfile
19
+ env:
20
+ - TEST_SUITE=rake
21
+
22
+ script:
23
+ - bundle exec $TEST_SUITE
24
+
17
25
  matrix:
18
26
  exclude:
19
27
  - rvm: 1.8.7-p374
@@ -22,20 +30,38 @@ matrix:
22
30
  gemfile: gemfiles/rails_41.gemfile
23
31
  - rvm: 1.8.7-p374
24
32
  gemfile: gemfiles/rails_42.gemfile
25
- - rvm: 2.1.5
33
+ - rvm: 1.8.7-p374
34
+ gemfile: gemfiles/rails_5.gemfile
35
+ - rvm: 1.9.3
36
+ gemfile: gemfiles/rails_5.gemfile
37
+ - rvm: 2.1.9
26
38
  gemfile: gemfiles/rails_23.gemfile
27
- - rvm: 2.1.5
39
+ - rvm: 2.1.9
28
40
  gemfile: gemfiles/rails_30.gemfile
29
- - rvm: 2.1.5
41
+ - rvm: 2.1.9
30
42
  gemfile: gemfiles/rails_31.gemfile
31
- - rvm: 2.2.1
43
+ - rvm: 2.1.9
44
+ gemfile: gemfiles/rails_5.gemfile
45
+ - rvm: 2.2.5
46
+ gemfile: gemfiles/rails_23.gemfile
47
+ - rvm: 2.2.5
48
+ gemfile: gemfiles/rails_30.gemfile
49
+ - rvm: 2.2.5
50
+ gemfile: gemfiles/rails_31.gemfile
51
+ - rvm: 2.2.5
52
+ gemfile: gemfiles/rails_32.gemfile
53
+ - rvm: 2.3.1
32
54
  gemfile: gemfiles/rails_23.gemfile
33
- - rvm: 2.2.1
55
+ - rvm: 2.3.1
34
56
  gemfile: gemfiles/rails_30.gemfile
35
- - rvm: 2.2.1
57
+ - rvm: 2.3.1
36
58
  gemfile: gemfiles/rails_31.gemfile
37
- - rvm: 2.2.1
59
+ - rvm: 2.3.1
38
60
  gemfile: gemfiles/rails_32.gemfile
61
+ include:
62
+ - rvm: 2.3.1
63
+ gemfile: gemfiles/rails_5.gemfile
64
+ env: TEST_SUITE="rubocop lib/ spec/"
39
65
 
40
66
  notifications:
41
67
  email: false
@@ -1,3 +1,10 @@
1
+ # 2.0.1 (2016-07-25)
2
+ - Support of `api_auth_options` in ActiveResource integration (#102 fwininger)
3
+ - Replace use of `#blank?` with `#nil?` to not depend on ActiveSupport (#114 packrat386)
4
+ - Fix Auth header matching to not match invalid SHA algorithms (#115 packrat386)
5
+ - Replace `alias_method_chain` with `alias_method` in the railtie since
6
+ alias_method_chain is deprecated in Rails 5 (#118 mlarraz)
7
+
1
8
  # 2.0.0 (2016-05-11)
2
9
  - IMPORTANT: 2.0.0 is backwards incompatible with the default settings of v1.x
3
10
  v2.0.0 always includes the http method in the canonical string.
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem "rake", "< 11.0", :platforms => :ruby_18
5
- gem "tins", "< 1.7", :platforms => :ruby_19 # amatch dependency
4
+ gem 'rake', '< 11.0', :platforms => :ruby_18
5
+ gem 'tins', '< 1.7', :platforms => :ruby_19 # amatch dependency
6
+
7
+ gem 'rubocop', :platforms => [:ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0
1
+ 2.0.1
@@ -0,0 +1,11 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 5.0.0"
6
+ gem "activeresource", "~> 5.0.0", git: 'https://github.com/rails/activeresource.git'
7
+ gem "activesupport", "~> 5.0.0"
8
+
9
+ gem "rubocop"
10
+
11
+ gemspec :path => "../"
@@ -69,7 +69,7 @@ module ApiAuth
69
69
 
70
70
  private
71
71
 
72
- AUTH_HEADER_PATTERN = /APIAuth(?:-HMAC-(MD[245]|SHA(?:1|224|256|384|512)*))? ([^:]+):(.+)$/
72
+ AUTH_HEADER_PATTERN = /APIAuth(?:-HMAC-(MD[245]|SHA(?:1|224|256|384|512)?))? ([^:]+):(.+)$/
73
73
 
74
74
  def request_too_old?(headers)
75
75
  # 900 seconds is 15 minutes
@@ -83,7 +83,7 @@ module ApiAuth
83
83
  match_data = parse_auth_header(headers.authorization_header)
84
84
  return false unless match_data
85
85
 
86
- digest = match_data[1].blank? ? 'SHA1' : match_data[1].upcase
86
+ digest = match_data[1].nil? ? 'SHA1' : match_data[1].upcase
87
87
  raise InvalidRequestDigest if !options[:digest].nil? && !options[:digest].casecmp(digest).zero?
88
88
 
89
89
  options = { :digest => digest }.merge(options)
@@ -58,8 +58,7 @@ module ApiAuth
58
58
  @request.content_type,
59
59
  @request.content_md5,
60
60
  parse_uri(@request.request_uri),
61
- @request.timestamp
62
- ].join(',')
61
+ @request.timestamp].join(',')
63
62
  end
64
63
 
65
64
  # Returns the authorization header from the request's headers
@@ -27,10 +27,12 @@ module ApiAuth
27
27
  base.class_attribute :hmac_access_id
28
28
  base.class_attribute :hmac_secret_key
29
29
  base.class_attribute :use_hmac
30
+ base.class_attribute :api_auth_options
30
31
  else
31
32
  base.class_inheritable_accessor :hmac_access_id
32
33
  base.class_inheritable_accessor :hmac_secret_key
33
34
  base.class_inheritable_accessor :use_hmac
35
+ base.class_inheritable_accessor :api_auth_options
34
36
  end
35
37
  end
36
38
 
@@ -39,9 +41,11 @@ module ApiAuth
39
41
  self.hmac_access_id = access_id
40
42
  self.hmac_secret_key = secret_key
41
43
  self.use_hmac = true
44
+ self.api_auth_options = options
42
45
 
43
46
  class << self
44
- alias_method_chain :connection, :auth
47
+ alias_method :connection_without_auth, :connection
48
+ alias_method :connection, :connection_with_auth
45
49
  end
46
50
  end
47
51
 
@@ -50,6 +54,7 @@ module ApiAuth
50
54
  c.hmac_access_id = hmac_access_id
51
55
  c.hmac_secret_key = hmac_secret_key
52
56
  c.use_hmac = use_hmac
57
+ c.api_auth_options = api_auth_options
53
58
  c
54
59
  end
55
60
  end # class methods
@@ -60,9 +65,11 @@ module ApiAuth
60
65
 
61
66
  module Connection
62
67
  def self.included(base)
63
- base.send :alias_method_chain, :request, :auth
68
+ base.send :alias_method, :request_without_auth, :request
69
+ base.send :alias_method, :request, :request_with_auth
70
+
64
71
  base.class_eval do
65
- attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac
72
+ attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac, :api_auth_options
66
73
  end
67
74
  end
68
75
 
@@ -71,7 +78,7 @@ module ApiAuth
71
78
  h = arguments.last
72
79
  tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
73
80
  tmp.body = arguments[0] if arguments.length > 1
74
- ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key)
81
+ ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key, api_auth_options)
75
82
  arguments.last['Content-MD5'] = tmp['Content-MD5'] if tmp['Content-MD5']
76
83
  arguments.last['DATE'] = tmp['DATE']
77
84
  arguments.last['Authorization'] = tmp['Authorization']
@@ -21,10 +21,9 @@ module ApiAuth
21
21
  end
22
22
 
23
23
  def populate_content_md5
24
- if @request.put? || @request.post?
25
- @request.env['Content-MD5'] = calculated_md5
26
- fetch_headers
27
- end
24
+ return unless @request.put? || @request.post?
25
+ @request.env['Content-MD5'] = calculated_md5
26
+ fetch_headers
28
27
  end
29
28
 
30
29
  def md5_mismatch?
@@ -21,10 +21,9 @@ module ApiAuth
21
21
  end
22
22
 
23
23
  def populate_content_md5
24
- if %w(POST PUT).include?(@request.method.to_s.upcase)
25
- @request.headers['Content-MD5'] = calculated_md5
26
- fetch_headers
27
- end
24
+ return unless %w(POST PUT).include?(@request.method.to_s.upcase)
25
+ @request.headers['Content-MD5'] = calculated_md5
26
+ fetch_headers
28
27
  end
29
28
 
30
29
  def md5_mismatch?
@@ -20,10 +20,9 @@ module ApiAuth
20
20
  end
21
21
 
22
22
  def populate_content_md5
23
- if @request.body
24
- @request.headers['Content-MD5'] = calculated_md5
25
- fetch_headers
26
- end
23
+ return unless @request.body
24
+ @request.headers['Content-MD5'] = calculated_md5
25
+ fetch_headers
27
26
  end
28
27
 
29
28
  def md5_mismatch?
@@ -27,9 +27,8 @@ module ApiAuth
27
27
  end
28
28
 
29
29
  def populate_content_md5
30
- if @request.class::REQUEST_HAS_BODY
31
- @request['Content-MD5'] = calculated_md5
32
- end
30
+ return unless @request.class::REQUEST_HAS_BODY
31
+ @request['Content-MD5'] = calculated_md5
33
32
  end
34
33
 
35
34
  def md5_mismatch?
@@ -26,10 +26,9 @@ module ApiAuth
26
26
  end
27
27
 
28
28
  def populate_content_md5
29
- if %w(POST PUT).include?(@request.request_method)
30
- @request.env['Content-MD5'] = calculated_md5
31
- fetch_headers
32
- end
29
+ return unless %w(POST PUT).include?(@request.request_method)
30
+ @request.env['Content-MD5'] = calculated_md5
31
+ fetch_headers
33
32
  end
34
33
 
35
34
  def md5_mismatch?
@@ -29,10 +29,9 @@ module ApiAuth
29
29
  end
30
30
 
31
31
  def populate_content_md5
32
- if [:post, :put].include?(@request.method)
33
- @request.headers['Content-MD5'] = calculated_md5
34
- save_headers
35
- end
32
+ return unless [:post, :put].include?(@request.method)
33
+ @request.headers['Content-MD5'] = calculated_md5
34
+ save_headers
36
35
  end
37
36
 
38
37
  def md5_mismatch?
@@ -60,8 +60,7 @@ describe 'ApiAuth' do
60
60
  Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
61
61
  'content-type' => 'text/plain',
62
62
  'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
63
- 'date' => Time.now.utc.httpdate
64
- )
63
+ 'date' => Time.now.utc.httpdate)
65
64
  end
66
65
 
67
66
  let(:canonical_string) { ApiAuth::Headers.new(request).canonical_string }
@@ -79,8 +78,7 @@ describe 'ApiAuth' do
79
78
  new_request = Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
80
79
  'content-type' => 'text/plain',
81
80
  'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
82
- 'date' => Time.now.utc.httpdate
83
- )
81
+ 'date' => Time.now.utc.httpdate)
84
82
 
85
83
  signature = hmac('123', new_request)
86
84
  new_request['Authorization'] = "APIAuth 1044:#{signature}"
@@ -106,11 +104,10 @@ describe 'ApiAuth' do
106
104
  end
107
105
 
108
106
  it 'fails to validate if the date is invalid' do
109
- request['date'] = "٢٠١٤-٠٩-٠٨ ١٦:٣١:١٤ +٠٣٠٠"
107
+ request['date'] = '٢٠١٤-٠٩-٠٨ ١٦:٣١:١٤ +٠٣٠٠'
110
108
  expect(ApiAuth.authentic?(request, '123')).to eq false
111
109
  end
112
110
 
113
-
114
111
  it 'fails to validate if the request method differs' do
115
112
  canonical_string = ApiAuth::Headers.new(request).canonical_string('POST')
116
113
  signature = hmac('123', request, canonical_string)
@@ -123,20 +120,35 @@ describe 'ApiAuth' do
123
120
  new_request = Net::HTTP::Put.new('/resource.xml?foo=bar&bar=foo',
124
121
  'content-type' => 'text/plain',
125
122
  'content-md5' => '1B2M2Y8AsgTpgAmY7PhCfg==',
126
- 'date' => Time.now.utc.httpdate
127
- )
123
+ 'date' => Time.now.utc.httpdate)
128
124
  canonical_string = ApiAuth::Headers.new(new_request).canonical_string
129
125
  signature = hmac('123', new_request, canonical_string, 'sha256')
130
- new_request['Authorization'] = "APIAuth-HMAC-SHA256 1044:#{signature}"
126
+ new_request['Authorization'] = "APIAuth-HMAC-#{digest} 1044:#{signature}"
131
127
  new_request
132
128
  end
133
129
 
134
- it 'validates for sha256 digest' do
135
- expect(ApiAuth.authentic?(request, '123', :digest => 'sha256')).to eq true
130
+ context 'valid request digest' do
131
+ let(:digest) { 'SHA256' }
132
+
133
+ context 'matching client digest' do
134
+ it 'validates matching digest' do
135
+ expect(ApiAuth.authentic?(request, '123', :digest => 'sha256')).to eq true
136
+ end
137
+ end
138
+
139
+ context 'different client digest' do
140
+ it 'raises an exception' do
141
+ expect { ApiAuth.authentic?(request, '123', :digest => 'sha512') }.to raise_error(ApiAuth::InvalidRequestDigest)
142
+ end
143
+ end
136
144
  end
137
145
 
138
- it 'validates exception with wrong client digest' do
139
- expect { ApiAuth.authentic?(request, '123', :digest => 'sha512') }.to raise_error(ApiAuth::InvalidRequestDigest)
146
+ context 'invalid request digest' do
147
+ let(:digest) { 'SHA111' }
148
+
149
+ it 'fails validation' do
150
+ expect(ApiAuth.authentic?(request, '123', :digest => 'sha111')).to eq false
151
+ end
140
152
  end
141
153
  end
142
154
  end
@@ -62,7 +62,11 @@ describe 'Rails integration' do
62
62
  end
63
63
 
64
64
  it 'should permit a request with properly signed headers' do
65
- request = ActionController::TestRequest.new
65
+ request = if ActionController::TestRequest.respond_to?(:create)
66
+ ActionController::TestRequest.create
67
+ else
68
+ ActionController::TestRequest.new
69
+ end
66
70
  request.env['DATE'] = Time.now.utc.httpdate
67
71
  ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
68
72
  response = generated_response(request, :index)
@@ -70,7 +74,11 @@ describe 'Rails integration' do
70
74
  end
71
75
 
72
76
  it 'should forbid a request with properly signed headers but timestamp > 15 minutes' do
73
- request = ActionController::TestRequest.new
77
+ request = if ActionController::TestRequest.respond_to?(:create)
78
+ ActionController::TestRequest.create
79
+ else
80
+ ActionController::TestRequest.new
81
+ end
74
82
  request.env['DATE'] = 'Mon, 23 Jan 1984 03:29:56 GMT'
75
83
  ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
76
84
  response = generated_response(request, :index)
@@ -78,26 +86,42 @@ describe 'Rails integration' do
78
86
  end
79
87
 
80
88
  it "should insert a DATE header in the request when one hasn't been specified" do
81
- request = ActionController::TestRequest.new
89
+ request = if ActionController::TestRequest.respond_to?(:create)
90
+ ActionController::TestRequest.create
91
+ else
92
+ ActionController::TestRequest.new
93
+ end
82
94
  ApiAuth.sign!(request, '1044', API_KEY_STORE['1044'])
83
95
  expect(request.headers['DATE']).not_to be_nil
84
96
  end
85
97
 
86
98
  it 'should forbid an unsigned request to a protected controller action' do
87
- request = ActionController::TestRequest.new
99
+ request = if ActionController::TestRequest.respond_to?(:create)
100
+ ActionController::TestRequest.create
101
+ else
102
+ ActionController::TestRequest.new
103
+ end
88
104
  response = generated_response(request, :index)
89
105
  expect(response.code).to eq('401')
90
106
  end
91
107
 
92
108
  it 'should forbid a request with a bogus signature' do
93
- request = ActionController::TestRequest.new
109
+ request = if ActionController::TestRequest.respond_to?(:create)
110
+ ActionController::TestRequest.create
111
+ else
112
+ ActionController::TestRequest.new
113
+ end
94
114
  request.env['Authorization'] = 'APIAuth bogus:bogus'
95
115
  response = generated_response(request, :index)
96
116
  expect(response.code).to eq('401')
97
117
  end
98
118
 
99
119
  it 'should allow non-protected controller actions to function as before' do
100
- request = ActionController::TestRequest.new
120
+ request = if ActionController::TestRequest.respond_to?(:create)
121
+ ActionController::TestRequest.create
122
+ else
123
+ ActionController::TestRequest.new
124
+ end
101
125
  response = generated_response(request, :public)
102
126
  expect(response.code).to eq('200')
103
127
  end
@@ -122,7 +146,7 @@ describe 'Rails integration' do
122
146
  },
123
147
  { :id => '1' }.to_xml(:root => 'test_resource')
124
148
  end
125
- expect(ApiAuth).to receive(:sign!).with(anything, '1044', API_KEY_STORE['1044']).and_call_original
149
+ expect(ApiAuth).to receive(:sign!).with(anything, '1044', API_KEY_STORE['1044'], {}).and_call_original
126
150
  TestResource.find(1)
127
151
  end
128
152
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api-auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mauricio Gomes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-11 00:00:00.000000000 Z
11
+ date: 2016-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -216,6 +216,7 @@ files:
216
216
  - gemfiles/rails_4.gemfile
217
217
  - gemfiles/rails_41.gemfile
218
218
  - gemfiles/rails_42.gemfile
219
+ - gemfiles/rails_5.gemfile
219
220
  - lib/api-auth.rb
220
221
  - lib/api_auth.rb
221
222
  - lib/api_auth/base.rb