api-auth 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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