api-auth 1.3.2 → 1.4.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -2
  3. data/.travis.yml +4 -0
  4. data/Appraisals +6 -0
  5. data/CHANGELOG.md +36 -0
  6. data/Gemfile.lock +77 -44
  7. data/README.md +15 -8
  8. data/VERSION +1 -1
  9. data/api_auth.gemspec +4 -4
  10. data/gemfiles/rails_23.gemfile +1 -1
  11. data/gemfiles/rails_23.gemfile.lock +19 -11
  12. data/gemfiles/rails_30.gemfile +1 -1
  13. data/gemfiles/rails_30.gemfile.lock +19 -11
  14. data/gemfiles/rails_31.gemfile +1 -1
  15. data/gemfiles/rails_31.gemfile.lock +19 -11
  16. data/gemfiles/rails_32.gemfile +1 -1
  17. data/gemfiles/rails_32.gemfile.lock +19 -11
  18. data/gemfiles/rails_4.gemfile +1 -1
  19. data/gemfiles/rails_4.gemfile.lock +19 -11
  20. data/gemfiles/rails_41.gemfile +1 -1
  21. data/gemfiles/rails_41.gemfile.lock +19 -11
  22. data/gemfiles/rails_42.gemfile +9 -0
  23. data/gemfiles/rails_42.gemfile.lock +115 -0
  24. data/lib/api_auth/base.rb +37 -23
  25. data/lib/api_auth/headers.rb +23 -3
  26. data/lib/api_auth/request_drivers/action_controller.rb +4 -0
  27. data/lib/api_auth/request_drivers/curb.rb +4 -0
  28. data/lib/api_auth/request_drivers/faraday.rb +4 -0
  29. data/lib/api_auth/request_drivers/httpi.rb +5 -1
  30. data/lib/api_auth/request_drivers/net_http.rb +4 -0
  31. data/lib/api_auth/request_drivers/rack.rb +5 -1
  32. data/lib/api_auth/request_drivers/rest_client.rb +4 -0
  33. data/spec/api_auth_spec.rb +112 -628
  34. data/spec/headers_spec.rb +132 -289
  35. data/spec/helpers_spec.rb +2 -2
  36. data/spec/railtie_spec.rb +13 -8
  37. data/spec/request_drivers/action_controller_spec.rb +218 -0
  38. data/spec/request_drivers/action_dispatch_spec.rb +219 -0
  39. data/spec/request_drivers/curb_spec.rb +89 -0
  40. data/spec/request_drivers/faraday_spec.rb +243 -0
  41. data/spec/request_drivers/httpi_spec.rb +147 -0
  42. data/spec/request_drivers/net_http_spec.rb +185 -0
  43. data/spec/request_drivers/rack_spec.rb +288 -0
  44. data/spec/request_drivers/rest_client_spec.rb +311 -0
  45. metadata +44 -19
  46. data/spec/application_helper.rb +0 -2
  47. data/spec/test_helper.rb +0 -2
@@ -6,4 +6,4 @@ gem "actionpack", "~> 3.1.0"
6
6
  gem "activeresource", "~> 3.1.0"
7
7
  gem "activesupport", "~> 3.1.0"
8
8
 
9
- gemspec :path=>"../"
9
+ gemspec :path => "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- api-auth (1.3.2)
4
+ api-auth (1.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -33,7 +33,7 @@ GEM
33
33
  rake
34
34
  builder (3.0.4)
35
35
  curb (0.8.6)
36
- diff-lcs (1.1.3)
36
+ diff-lcs (1.2.5)
37
37
  erubis (2.7.0)
38
38
  faraday (0.9.1)
39
39
  multipart-post (>= 1.2, < 3)
@@ -55,14 +55,19 @@ GEM
55
55
  rake (10.1.1)
56
56
  rest-client (1.6.7)
57
57
  mime-types (>= 1.16)
58
- rspec (2.4.0)
59
- rspec-core (~> 2.4.0)
60
- rspec-expectations (~> 2.4.0)
61
- rspec-mocks (~> 2.4.0)
62
- rspec-core (2.4.0)
63
- rspec-expectations (2.4.0)
64
- diff-lcs (~> 1.1.2)
65
- rspec-mocks (2.4.0)
58
+ rspec (3.4.0)
59
+ rspec-core (~> 3.4.0)
60
+ rspec-expectations (~> 3.4.0)
61
+ rspec-mocks (~> 3.4.0)
62
+ rspec-core (3.4.0)
63
+ rspec-support (~> 3.4.0)
64
+ rspec-expectations (3.4.0)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.4.0)
67
+ rspec-mocks (3.4.0)
68
+ diff-lcs (>= 1.2.0, < 2.0)
69
+ rspec-support (~> 3.4.0)
70
+ rspec-support (3.4.0)
66
71
  rubyntlm (0.3.4)
67
72
  sprockets (2.0.4)
68
73
  hike (~> 1.2)
@@ -87,4 +92,7 @@ DEPENDENCIES
87
92
  multipart-post (~> 2.0)
88
93
  rake
89
94
  rest-client (~> 1.6.0)
90
- rspec (~> 2.4.0)
95
+ rspec (~> 3.4)
96
+
97
+ BUNDLED WITH
98
+ 1.10.6
@@ -6,4 +6,4 @@ gem "actionpack", "~> 3.2.17"
6
6
  gem "activeresource", "~> 3.2.17"
7
7
  gem "activesupport", "~> 3.2.17"
8
8
 
9
- gemspec :path=>"../"
9
+ gemspec :path => "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- api-auth (1.3.2)
4
+ api-auth (1.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -32,7 +32,7 @@ GEM
32
32
  rake
33
33
  builder (3.0.4)
34
34
  curb (0.8.6)
35
- diff-lcs (1.1.3)
35
+ diff-lcs (1.2.5)
36
36
  erubis (2.7.0)
37
37
  faraday (0.9.1)
38
38
  multipart-post (>= 1.2, < 3)
@@ -53,14 +53,19 @@ GEM
53
53
  rake (10.1.1)
54
54
  rest-client (1.6.7)
55
55
  mime-types (>= 1.16)
56
- rspec (2.4.0)
57
- rspec-core (~> 2.4.0)
58
- rspec-expectations (~> 2.4.0)
59
- rspec-mocks (~> 2.4.0)
60
- rspec-core (2.4.0)
61
- rspec-expectations (2.4.0)
62
- diff-lcs (~> 1.1.2)
63
- rspec-mocks (2.4.0)
56
+ rspec (3.4.0)
57
+ rspec-core (~> 3.4.0)
58
+ rspec-expectations (~> 3.4.0)
59
+ rspec-mocks (~> 3.4.0)
60
+ rspec-core (3.4.0)
61
+ rspec-support (~> 3.4.0)
62
+ rspec-expectations (3.4.0)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.4.0)
65
+ rspec-mocks (3.4.0)
66
+ diff-lcs (>= 1.2.0, < 2.0)
67
+ rspec-support (~> 3.4.0)
68
+ rspec-support (3.4.0)
64
69
  rubyntlm (0.3.4)
65
70
  sprockets (2.2.2)
66
71
  hike (~> 1.2)
@@ -86,4 +91,7 @@ DEPENDENCIES
86
91
  multipart-post (~> 2.0)
87
92
  rake
88
93
  rest-client (~> 1.6.0)
89
- rspec (~> 2.4.0)
94
+ rspec (~> 3.4)
95
+
96
+ BUNDLED WITH
97
+ 1.10.6
@@ -6,4 +6,4 @@ gem "actionpack", "~> 4.0.4"
6
6
  gem "activeresource", "~> 4.0.0"
7
7
  gem "activesupport", "~> 4.0.4"
8
8
 
9
- gemspec :path=>"../"
9
+ gemspec :path => "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- api-auth (1.3.2)
4
+ api-auth (1.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -33,7 +33,7 @@ GEM
33
33
  atomic (1.1.16)
34
34
  builder (3.1.4)
35
35
  curb (0.8.6)
36
- diff-lcs (1.1.3)
36
+ diff-lcs (1.2.5)
37
37
  erubis (2.7.0)
38
38
  faraday (0.9.1)
39
39
  multipart-post (>= 1.2, < 3)
@@ -53,14 +53,19 @@ GEM
53
53
  rake (10.1.1)
54
54
  rest-client (1.6.7)
55
55
  mime-types (>= 1.16)
56
- rspec (2.4.0)
57
- rspec-core (~> 2.4.0)
58
- rspec-expectations (~> 2.4.0)
59
- rspec-mocks (~> 2.4.0)
60
- rspec-core (2.4.0)
61
- rspec-expectations (2.4.0)
62
- diff-lcs (~> 1.1.2)
63
- rspec-mocks (2.4.0)
56
+ rspec (3.4.0)
57
+ rspec-core (~> 3.4.0)
58
+ rspec-expectations (~> 3.4.0)
59
+ rspec-mocks (~> 3.4.0)
60
+ rspec-core (3.4.0)
61
+ rspec-support (~> 3.4.0)
62
+ rspec-expectations (3.4.0)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.4.0)
65
+ rspec-mocks (3.4.0)
66
+ diff-lcs (>= 1.2.0, < 2.0)
67
+ rspec-support (~> 3.4.0)
68
+ rspec-support (3.4.0)
64
69
  rubyntlm (0.3.4)
65
70
  thread_safe (0.2.0)
66
71
  atomic (>= 1.1.7, < 2)
@@ -83,4 +88,7 @@ DEPENDENCIES
83
88
  multipart-post (~> 2.0)
84
89
  rake
85
90
  rest-client (~> 1.6.0)
86
- rspec (~> 2.4.0)
91
+ rspec (~> 3.4)
92
+
93
+ BUNDLED WITH
94
+ 1.10.6
@@ -6,4 +6,4 @@ gem "actionpack", "~> 4.1.0"
6
6
  gem "activeresource", "~> 4.0.0"
7
7
  gem "activesupport", "~> 4.1.0"
8
8
 
9
- gemspec :path=>"../"
9
+ gemspec :path => "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- api-auth (1.3.2)
4
+ api-auth (1.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -36,7 +36,7 @@ GEM
36
36
  thor (>= 0.14.0)
37
37
  builder (3.2.2)
38
38
  curb (0.8.6)
39
- diff-lcs (1.1.3)
39
+ diff-lcs (1.2.5)
40
40
  erubis (2.7.0)
41
41
  faraday (0.9.1)
42
42
  multipart-post (>= 1.2, < 3)
@@ -56,14 +56,19 @@ GEM
56
56
  rake (10.3.2)
57
57
  rest-client (1.6.7)
58
58
  mime-types (>= 1.16)
59
- rspec (2.4.0)
60
- rspec-core (~> 2.4.0)
61
- rspec-expectations (~> 2.4.0)
62
- rspec-mocks (~> 2.4.0)
63
- rspec-core (2.4.0)
64
- rspec-expectations (2.4.0)
65
- diff-lcs (~> 1.1.2)
66
- rspec-mocks (2.4.0)
59
+ rspec (3.4.0)
60
+ rspec-core (~> 3.4.0)
61
+ rspec-expectations (~> 3.4.0)
62
+ rspec-mocks (~> 3.4.0)
63
+ rspec-core (3.4.0)
64
+ rspec-support (~> 3.4.0)
65
+ rspec-expectations (3.4.0)
66
+ diff-lcs (>= 1.2.0, < 2.0)
67
+ rspec-support (~> 3.4.0)
68
+ rspec-mocks (3.4.0)
69
+ diff-lcs (>= 1.2.0, < 2.0)
70
+ rspec-support (~> 3.4.0)
71
+ rspec-support (3.4.0)
67
72
  rubyntlm (0.3.4)
68
73
  thor (0.19.1)
69
74
  thread_safe (0.3.3)
@@ -87,4 +92,7 @@ DEPENDENCIES
87
92
  multipart-post (~> 2.0)
88
93
  rake
89
94
  rest-client (~> 1.6.0)
90
- rspec (~> 2.4.0)
95
+ rspec (~> 3.4)
96
+
97
+ BUNDLED WITH
98
+ 1.10.6
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "actionpack", "~> 4.2.0"
6
+ gem "activeresource", "~> 4.0.0"
7
+ gem "activesupport", "~> 4.2.0"
8
+
9
+ gemspec :path => "../"
@@ -0,0 +1,115 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ api-auth (1.4.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ actionpack (4.2.5)
10
+ actionview (= 4.2.5)
11
+ activesupport (= 4.2.5)
12
+ rack (~> 1.6)
13
+ rack-test (~> 0.6.2)
14
+ rails-dom-testing (~> 1.0, >= 1.0.5)
15
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
16
+ actionview (4.2.5)
17
+ activesupport (= 4.2.5)
18
+ builder (~> 3.1)
19
+ erubis (~> 2.7.0)
20
+ rails-dom-testing (~> 1.0, >= 1.0.5)
21
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
22
+ activemodel (4.2.5)
23
+ activesupport (= 4.2.5)
24
+ builder (~> 3.1)
25
+ activeresource (4.0.0)
26
+ activemodel (~> 4.0)
27
+ activesupport (~> 4.0)
28
+ rails-observers (~> 0.1.1)
29
+ activesupport (4.2.5)
30
+ i18n (~> 0.7)
31
+ json (~> 1.7, >= 1.7.7)
32
+ minitest (~> 5.1)
33
+ thread_safe (~> 0.3, >= 0.3.4)
34
+ tzinfo (~> 1.1)
35
+ amatch (0.3.0)
36
+ tins (~> 1.0)
37
+ appraisal (1.0.0)
38
+ bundler
39
+ rake
40
+ thor (>= 0.14.0)
41
+ builder (3.2.2)
42
+ curb (0.8.6)
43
+ diff-lcs (1.2.5)
44
+ erubis (2.7.0)
45
+ faraday (0.9.1)
46
+ multipart-post (>= 1.2, < 3)
47
+ httpi (2.1.0)
48
+ rack
49
+ rubyntlm (~> 0.3.2)
50
+ i18n (0.7.0)
51
+ json (1.8.3)
52
+ loofah (2.0.3)
53
+ nokogiri (>= 1.5.9)
54
+ mime-types (2.6.2)
55
+ mini_portile (0.6.2)
56
+ minitest (5.8.2)
57
+ multipart-post (2.0.0)
58
+ nokogiri (1.6.6.2)
59
+ mini_portile (~> 0.6.0)
60
+ rack (1.6.4)
61
+ rack-test (0.6.3)
62
+ rack (>= 1.0)
63
+ rails-deprecated_sanitizer (1.0.3)
64
+ activesupport (>= 4.2.0.alpha)
65
+ rails-dom-testing (1.0.7)
66
+ activesupport (>= 4.2.0.beta, < 5.0)
67
+ nokogiri (~> 1.6.0)
68
+ rails-deprecated_sanitizer (>= 1.0.1)
69
+ rails-html-sanitizer (1.0.2)
70
+ loofah (~> 2.0)
71
+ rails-observers (0.1.2)
72
+ activemodel (~> 4.0)
73
+ rake (10.4.2)
74
+ rest-client (1.6.7)
75
+ mime-types (>= 1.16)
76
+ rspec (3.4.0)
77
+ rspec-core (~> 3.4.0)
78
+ rspec-expectations (~> 3.4.0)
79
+ rspec-mocks (~> 3.4.0)
80
+ rspec-core (3.4.0)
81
+ rspec-support (~> 3.4.0)
82
+ rspec-expectations (3.4.0)
83
+ diff-lcs (>= 1.2.0, < 2.0)
84
+ rspec-support (~> 3.4.0)
85
+ rspec-mocks (3.4.0)
86
+ diff-lcs (>= 1.2.0, < 2.0)
87
+ rspec-support (~> 3.4.0)
88
+ rspec-support (3.4.0)
89
+ rubyntlm (0.3.4)
90
+ thor (0.19.1)
91
+ thread_safe (0.3.5)
92
+ tins (1.6.0)
93
+ tzinfo (1.2.2)
94
+ thread_safe (~> 0.1)
95
+
96
+ PLATFORMS
97
+ ruby
98
+
99
+ DEPENDENCIES
100
+ actionpack (~> 4.2.0)
101
+ activeresource (~> 4.0.0)
102
+ activesupport (~> 4.2.0)
103
+ amatch
104
+ api-auth!
105
+ appraisal
106
+ curb (~> 0.8.1)
107
+ faraday
108
+ httpi
109
+ multipart-post (~> 2.0)
110
+ rake
111
+ rest-client (~> 1.6.0)
112
+ rspec (~> 3.4)
113
+
114
+ BUNDLED WITH
115
+ 1.10.6
@@ -22,19 +22,30 @@ module ApiAuth
22
22
  # access_id: The public unique identifier for the client
23
23
  #
24
24
  # secret_key: assigned secret key that is known to both parties
25
- def sign!(request, access_id, secret_key)
25
+ def sign!(request, access_id, secret_key, options = {})
26
+ options = { :override_http_method => nil, :with_http_method => false }.merge(options)
26
27
  headers = Headers.new(request)
27
28
  headers.calculate_md5
28
29
  headers.set_date
29
- headers.sign_header auth_header(request, access_id, secret_key)
30
+ headers.sign_header auth_header(headers, access_id, secret_key, options)
30
31
  end
31
32
 
32
33
  # Determines if the request is authentic given the request and the client's
33
34
  # secret key. Returns true if the request is authentic and false otherwise.
34
- def authentic?(request, secret_key)
35
+ def authentic?(request, secret_key, options = {})
35
36
  return false if secret_key.nil?
37
+ options = { :override_http_method => nil }.merge(options)
36
38
 
37
- return !md5_mismatch?(request) && signatures_match?(request, secret_key) && !request_too_old?(request)
39
+ headers = Headers.new(request)
40
+ if headers.md5_mismatch?
41
+ false
42
+ elsif !signatures_match?(headers, secret_key, options)
43
+ false
44
+ elsif request_too_old?(headers)
45
+ false
46
+ else
47
+ true
48
+ end
38
49
  end
39
50
 
40
51
  # Returns the access id from the request's authorization header
@@ -58,8 +69,9 @@ module ApiAuth
58
69
 
59
70
  private
60
71
 
61
- def request_too_old?(request)
62
- headers = Headers.new(request)
72
+ AUTH_HEADER_PATTERN = /APIAuth ([^:]+):(.+)$/
73
+
74
+ def request_too_old?(headers)
63
75
  # 900 seconds is 15 minutes
64
76
  begin
65
77
  Time.httpdate(headers.timestamp).utc < (Time.now.utc - 900)
@@ -68,33 +80,35 @@ module ApiAuth
68
80
  end
69
81
  end
70
82
 
71
- def md5_mismatch?(request)
72
- headers = Headers.new(request)
73
- headers.md5_mismatch?
74
- end
83
+ def signatures_match?(headers, secret_key, options)
84
+ match_data = parse_auth_header(headers.authorization_header)
85
+ return false unless match_data
75
86
 
76
- def signatures_match?(request, secret_key)
77
- headers = Headers.new(request)
78
- if match_data = parse_auth_header(headers.authorization_header)
79
- hmac = match_data[2]
80
- return hmac == hmac_signature(request, secret_key)
81
- end
82
- false
87
+ options = options.merge(:with_http_method => true)
88
+
89
+ header_sig = match_data[2]
90
+ calculated_sig_no_http = hmac_signature(headers, secret_key, {})
91
+ calculated_sig_with_http = hmac_signature(headers, secret_key, options)
92
+
93
+ header_sig == calculated_sig_with_http || header_sig == calculated_sig_no_http
83
94
  end
84
95
 
85
- def hmac_signature(request, secret_key)
86
- headers = Headers.new(request)
87
- canonical_string = headers.canonical_string
96
+ def hmac_signature(headers, secret_key, options)
97
+ if options[:with_http_method]
98
+ canonical_string = headers.canonical_string_with_http_method(options[:override_http_method])
99
+ else
100
+ canonical_string = headers.canonical_string
101
+ end
88
102
  digest = OpenSSL::Digest.new('sha1')
89
103
  b64_encode(OpenSSL::HMAC.digest(digest, secret_key, canonical_string))
90
104
  end
91
105
 
92
- def auth_header(request, access_id, secret_key)
93
- "APIAuth #{access_id}:#{hmac_signature(request, secret_key)}"
106
+ def auth_header(headers, access_id, secret_key, options)
107
+ "APIAuth #{access_id}:#{hmac_signature(headers, secret_key, options)}"
94
108
  end
95
109
 
96
110
  def parse_auth_header(auth_header)
97
- Regexp.new("APIAuth ([^:]+):(.+)$").match(auth_header)
111
+ AUTH_HEADER_PATTERN.match(auth_header)
98
112
  end
99
113
 
100
114
  end # class methods