api-auth 1.5.0 → 2.0.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 +4 -4
- data/.gitignore +10 -44
- data/.rubocop.yml +102 -0
- data/.travis.yml +1 -0
- data/Appraisals +8 -0
- data/CHANGELOG.md +8 -1
- data/Gemfile +3 -0
- data/README.md +33 -5
- data/VERSION +1 -1
- data/api_auth.gemspec +17 -17
- data/gemfiles/rails_23.gemfile +3 -0
- data/gemfiles/rails_30.gemfile +3 -0
- data/gemfiles/rails_31.gemfile +5 -0
- data/gemfiles/rails_32.gemfile +5 -0
- data/gemfiles/rails_4.gemfile +2 -0
- data/gemfiles/rails_41.gemfile +2 -0
- data/gemfiles/rails_42.gemfile +2 -0
- data/lib/api-auth.rb +1 -1
- data/lib/api_auth/base.rb +21 -25
- data/lib/api_auth/errors.rb +4 -3
- data/lib/api_auth/headers.rb +11 -27
- data/lib/api_auth/helpers.rb +2 -6
- data/lib/api_auth/railtie.rb +5 -50
- data/lib/api_auth/request_drivers/action_controller.rb +7 -13
- data/lib/api_auth/request_drivers/action_dispatch.rb +0 -6
- data/lib/api_auth/request_drivers/curb.rb +8 -14
- data/lib/api_auth/request_drivers/faraday.rb +11 -21
- data/lib/api_auth/request_drivers/httpi.rb +8 -14
- data/lib/api_auth/request_drivers/net_http.rb +8 -14
- data/lib/api_auth/request_drivers/rack.rb +10 -16
- data/lib/api_auth/request_drivers/rest_client.rb +9 -15
- data/spec/api_auth_spec.rb +90 -88
- data/spec/headers_spec.rb +69 -84
- data/spec/helpers_spec.rb +7 -9
- data/spec/railtie_spec.rb +42 -72
- data/spec/request_drivers/action_controller_spec.rb +53 -55
- data/spec/request_drivers/action_dispatch_spec.rb +52 -55
- data/spec/request_drivers/curb_spec.rb +25 -28
- data/spec/request_drivers/faraday_spec.rb +54 -56
- data/spec/request_drivers/httpi_spec.rb +42 -48
- data/spec/request_drivers/net_http_spec.rb +51 -53
- data/spec/request_drivers/rack_spec.rb +58 -60
- data/spec/request_drivers/rest_client_spec.rb +86 -89
- data/spec/spec_helper.rb +9 -9
- metadata +4 -11
- data/Gemfile.lock +0 -115
- data/gemfiles/rails_23.gemfile.lock +0 -70
- data/gemfiles/rails_30.gemfile.lock +0 -92
- data/gemfiles/rails_31.gemfile.lock +0 -98
- data/gemfiles/rails_32.gemfile.lock +0 -97
- data/gemfiles/rails_4.gemfile.lock +0 -94
- data/gemfiles/rails_41.gemfile.lock +0 -98
- data/gemfiles/rails_42.gemfile.lock +0 -115
data/lib/api_auth/errors.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
# :nodoc:
|
4
3
|
class ApiAuthError < StandardError; end
|
5
|
-
|
4
|
+
|
6
5
|
# Raised when the HTTP request object passed is not supported
|
7
6
|
class UnknownHTTPRequest < ApiAuthError; end
|
8
|
-
|
7
|
+
|
8
|
+
# Raised when the client request digest is not the same as the server
|
9
|
+
class InvalidRequestDigest < ApiAuthError; end
|
9
10
|
end
|
data/lib/api_auth/headers.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
# Builds the canonical string given a request object.
|
4
3
|
class Headers
|
5
|
-
|
6
4
|
include RequestDrivers
|
7
5
|
|
8
6
|
def initialize(request)
|
@@ -36,46 +34,32 @@ module ApiAuth
|
|
36
34
|
HttpiRequest.new(request)
|
37
35
|
when /Faraday::Request/
|
38
36
|
FaradayRequest.new(request)
|
39
|
-
else
|
40
|
-
nil
|
41
37
|
end
|
42
38
|
|
43
39
|
return new_request if new_request
|
44
|
-
return RackRequest.new(request) if request.
|
45
|
-
raise UnknownHTTPRequest, "#{request.class
|
40
|
+
return RackRequest.new(request) if request.is_a?(Rack::Request)
|
41
|
+
raise UnknownHTTPRequest, "#{request.class} is not yet supported."
|
46
42
|
end
|
47
43
|
private :initialize_request_driver
|
48
44
|
|
49
45
|
# Returns the request timestamp
|
50
46
|
def timestamp
|
51
|
-
|
47
|
+
@request.timestamp
|
52
48
|
end
|
53
49
|
|
54
|
-
|
55
|
-
def canonical_string_without_http_method
|
56
|
-
[ @request.content_type,
|
57
|
-
@request.content_md5,
|
58
|
-
parse_uri(@request.request_uri),
|
59
|
-
@request.timestamp
|
60
|
-
].join(",")
|
61
|
-
end
|
62
|
-
|
63
|
-
# temp backwards compatibility
|
64
|
-
alias_method :canonical_string, :canonical_string_without_http_method
|
65
|
-
|
66
|
-
def canonical_string_with_http_method(override_method = nil)
|
50
|
+
def canonical_string(override_method = nil)
|
67
51
|
request_method = override_method || @request.http_method
|
68
52
|
|
69
53
|
if request_method.nil?
|
70
|
-
raise ArgumentError,
|
54
|
+
raise ArgumentError, 'unable to determine the http method from the request, please supply an override'
|
71
55
|
end
|
72
56
|
|
73
|
-
[
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
].join(
|
57
|
+
[request_method.upcase,
|
58
|
+
@request.content_type,
|
59
|
+
@request.content_md5,
|
60
|
+
parse_uri(@request.request_uri),
|
61
|
+
@request.timestamp
|
62
|
+
].join(',')
|
79
63
|
end
|
80
64
|
|
81
65
|
# Returns the authorization header from the request's headers
|
data/lib/api_auth/helpers.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
module Helpers # :nodoc:
|
4
|
-
|
5
3
|
def b64_encode(string)
|
6
4
|
if Base64.respond_to?(:strict_encode64)
|
7
5
|
Base64.strict_encode64(string)
|
8
6
|
else
|
9
7
|
# Fall back to stripping out newlines on Ruby 1.8.
|
10
|
-
Base64.encode64(string).
|
8
|
+
Base64.encode64(string).delete("\n")
|
11
9
|
end
|
12
10
|
end
|
13
11
|
|
@@ -22,10 +20,8 @@ module ApiAuth
|
|
22
20
|
# Capitalizes the keys of a hash
|
23
21
|
def capitalize_keys(hsh)
|
24
22
|
capitalized_hash = {}
|
25
|
-
hsh.each_pair {|k,v| capitalized_hash[k.to_s.upcase] = v }
|
23
|
+
hsh.each_pair { |k, v| capitalized_hash[k.to_s.upcase] = v }
|
26
24
|
capitalized_hash
|
27
25
|
end
|
28
|
-
|
29
26
|
end
|
30
|
-
|
31
27
|
end
|
data/lib/api_auth/railtie.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
# Integration with Rails
|
4
3
|
#
|
5
4
|
class Rails # :nodoc:
|
6
|
-
|
7
5
|
module ControllerMethods # :nodoc:
|
8
|
-
|
9
6
|
module InstanceMethods # :nodoc:
|
10
|
-
|
11
7
|
def get_api_access_id_from_request
|
12
8
|
ApiAuth.access_id(request)
|
13
9
|
end
|
@@ -15,31 +11,15 @@ module ApiAuth
|
|
15
11
|
def api_authenticated?(secret_key)
|
16
12
|
ApiAuth.authentic?(request, secret_key)
|
17
13
|
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
unless defined?(ActionController)
|
22
|
-
begin
|
23
|
-
require 'rubygems'
|
24
|
-
gem 'actionpack'
|
25
|
-
gem 'activesupport'
|
26
|
-
require 'action_controller'
|
27
|
-
require 'active_support'
|
28
|
-
rescue LoadError
|
29
|
-
nil
|
30
|
-
end
|
31
14
|
end
|
32
15
|
|
33
16
|
if defined?(ActionController::Base)
|
34
17
|
ActionController::Base.send(:include, ControllerMethods::InstanceMethods)
|
35
18
|
end
|
36
|
-
|
37
19
|
end # ControllerMethods
|
38
20
|
|
39
21
|
module ActiveResourceExtension # :nodoc:
|
40
|
-
|
41
22
|
module ActiveResourceApiAuth # :nodoc:
|
42
|
-
|
43
23
|
def self.included(base)
|
44
24
|
base.extend(ClassMethods)
|
45
25
|
|
@@ -47,24 +27,17 @@ module ApiAuth
|
|
47
27
|
base.class_attribute :hmac_access_id
|
48
28
|
base.class_attribute :hmac_secret_key
|
49
29
|
base.class_attribute :use_hmac
|
50
|
-
base.class_attribute :sign_with_http_method
|
51
30
|
else
|
52
31
|
base.class_inheritable_accessor :hmac_access_id
|
53
32
|
base.class_inheritable_accessor :hmac_secret_key
|
54
33
|
base.class_inheritable_accessor :use_hmac
|
55
|
-
base.class_inheritable_accessor :sign_with_http_method
|
56
34
|
end
|
57
|
-
|
58
35
|
end
|
59
36
|
|
60
37
|
module ClassMethods
|
61
|
-
|
62
38
|
def with_api_auth(access_id, secret_key, options = {})
|
63
|
-
sign_with_http_method = options[:sign_with_http_method] || false
|
64
|
-
|
65
39
|
self.hmac_access_id = access_id
|
66
40
|
self.hmac_secret_key = secret_key
|
67
|
-
self.sign_with_http_method = sign_with_http_method
|
68
41
|
self.use_hmac = true
|
69
42
|
|
70
43
|
class << self
|
@@ -74,26 +47,22 @@ module ApiAuth
|
|
74
47
|
|
75
48
|
def connection_with_auth(refresh = false)
|
76
49
|
c = connection_without_auth(refresh)
|
77
|
-
c.hmac_access_id =
|
78
|
-
c.hmac_secret_key =
|
79
|
-
c.use_hmac =
|
80
|
-
c.sign_with_http_method = self.sign_with_http_method
|
50
|
+
c.hmac_access_id = hmac_access_id
|
51
|
+
c.hmac_secret_key = hmac_secret_key
|
52
|
+
c.use_hmac = use_hmac
|
81
53
|
c
|
82
54
|
end
|
83
|
-
|
84
55
|
end # class methods
|
85
56
|
|
86
57
|
module InstanceMethods
|
87
58
|
end
|
88
|
-
|
89
59
|
end # BaseApiAuth
|
90
60
|
|
91
61
|
module Connection
|
92
|
-
|
93
62
|
def self.included(base)
|
94
63
|
base.send :alias_method_chain, :request, :auth
|
95
64
|
base.class_eval do
|
96
|
-
attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac
|
65
|
+
attr_accessor :hmac_secret_key, :hmac_access_id, :use_hmac
|
97
66
|
end
|
98
67
|
end
|
99
68
|
|
@@ -102,7 +71,7 @@ module ApiAuth
|
|
102
71
|
h = arguments.last
|
103
72
|
tmp = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(path, h)
|
104
73
|
tmp.body = arguments[0] if arguments.length > 1
|
105
|
-
ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key
|
74
|
+
ApiAuth.sign!(tmp, hmac_access_id, hmac_secret_key)
|
106
75
|
arguments.last['Content-MD5'] = tmp['Content-MD5'] if tmp['Content-MD5']
|
107
76
|
arguments.last['DATE'] = tmp['DATE']
|
108
77
|
arguments.last['Authorization'] = tmp['Authorization']
|
@@ -110,26 +79,12 @@ module ApiAuth
|
|
110
79
|
|
111
80
|
request_without_auth(method, path, *arguments)
|
112
81
|
end
|
113
|
-
|
114
82
|
end # Connection
|
115
83
|
|
116
|
-
unless defined?(ActiveResource)
|
117
|
-
begin
|
118
|
-
require 'rubygems'
|
119
|
-
gem 'activeresource'
|
120
|
-
require 'active_resource'
|
121
|
-
rescue LoadError
|
122
|
-
nil
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
84
|
if defined?(ActiveResource)
|
127
85
|
ActiveResource::Base.send(:include, ActiveResourceApiAuth)
|
128
86
|
ActiveResource::Connection.send(:include, Connection)
|
129
87
|
end
|
130
|
-
|
131
88
|
end # ActiveResourceExtension
|
132
|
-
|
133
89
|
end # Rails
|
134
|
-
|
135
90
|
end # ApiAuth
|
@@ -1,9 +1,6 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
module RequestDrivers # :nodoc:
|
4
|
-
|
5
3
|
class ActionControllerRequest # :nodoc:
|
6
|
-
|
7
4
|
include ApiAuth::Helpers
|
8
5
|
|
9
6
|
def initialize(request)
|
@@ -13,7 +10,7 @@ module ApiAuth
|
|
13
10
|
end
|
14
11
|
|
15
12
|
def set_auth_header(header)
|
16
|
-
@request.env[
|
13
|
+
@request.env['Authorization'] = header
|
17
14
|
fetch_headers
|
18
15
|
@request
|
19
16
|
end
|
@@ -25,7 +22,7 @@ module ApiAuth
|
|
25
22
|
|
26
23
|
def populate_content_md5
|
27
24
|
if @request.put? || @request.post?
|
28
|
-
@request.env[
|
25
|
+
@request.env['Content-MD5'] = calculated_md5
|
29
26
|
fetch_headers
|
30
27
|
end
|
31
28
|
end
|
@@ -48,12 +45,12 @@ module ApiAuth
|
|
48
45
|
|
49
46
|
def content_type
|
50
47
|
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
51
|
-
value.nil? ?
|
48
|
+
value.nil? ? '' : value
|
52
49
|
end
|
53
50
|
|
54
51
|
def content_md5
|
55
52
|
value = find_header(%w(CONTENT-MD5 CONTENT_MD5 HTTP_CONTENT_MD5))
|
56
|
-
value.nil? ?
|
53
|
+
value.nil? ? '' : value
|
57
54
|
end
|
58
55
|
|
59
56
|
def request_uri
|
@@ -67,21 +64,18 @@ module ApiAuth
|
|
67
64
|
|
68
65
|
def timestamp
|
69
66
|
value = find_header(%w(DATE HTTP_DATE))
|
70
|
-
value.nil? ?
|
67
|
+
value.nil? ? '' : value
|
71
68
|
end
|
72
69
|
|
73
70
|
def authorization_header
|
74
71
|
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
75
72
|
end
|
76
73
|
|
77
|
-
|
74
|
+
private
|
78
75
|
|
79
76
|
def find_header(keys)
|
80
|
-
keys.map {|key| @headers[key] }.compact.first
|
77
|
+
keys.map { |key| @headers[key] }.compact.first
|
81
78
|
end
|
82
|
-
|
83
79
|
end
|
84
|
-
|
85
80
|
end
|
86
|
-
|
87
81
|
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
module RequestDrivers # :nodoc:
|
4
|
-
|
5
3
|
class CurbRequest # :nodoc:
|
6
|
-
|
7
4
|
include ApiAuth::Helpers
|
8
5
|
|
9
6
|
def initialize(request)
|
@@ -13,13 +10,13 @@ module ApiAuth
|
|
13
10
|
end
|
14
11
|
|
15
12
|
def set_auth_header(header)
|
16
|
-
@request.headers
|
13
|
+
@request.headers['Authorization'] = header
|
17
14
|
fetch_headers
|
18
15
|
@request
|
19
16
|
end
|
20
17
|
|
21
18
|
def populate_content_md5
|
22
|
-
nil #doesn't appear to be possible
|
19
|
+
nil # doesn't appear to be possible
|
23
20
|
end
|
24
21
|
|
25
22
|
def md5_mismatch?
|
@@ -36,12 +33,12 @@ module ApiAuth
|
|
36
33
|
|
37
34
|
def content_type
|
38
35
|
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
39
|
-
value.nil? ?
|
36
|
+
value.nil? ? '' : value
|
40
37
|
end
|
41
38
|
|
42
39
|
def content_md5
|
43
40
|
value = find_header(%w(CONTENT-MD5 CONTENT_MD5))
|
44
|
-
value.nil? ?
|
41
|
+
value.nil? ? '' : value
|
45
42
|
end
|
46
43
|
|
47
44
|
def request_uri
|
@@ -49,27 +46,24 @@ module ApiAuth
|
|
49
46
|
end
|
50
47
|
|
51
48
|
def set_date
|
52
|
-
@request.headers
|
49
|
+
@request.headers['DATE'] = Time.now.utc.httpdate
|
53
50
|
fetch_headers
|
54
51
|
end
|
55
52
|
|
56
53
|
def timestamp
|
57
54
|
value = find_header(%w(DATE HTTP_DATE))
|
58
|
-
value.nil? ?
|
55
|
+
value.nil? ? '' : value
|
59
56
|
end
|
60
57
|
|
61
58
|
def authorization_header
|
62
59
|
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
63
60
|
end
|
64
61
|
|
65
|
-
|
62
|
+
private
|
66
63
|
|
67
64
|
def find_header(keys)
|
68
|
-
keys.map {|key| @headers[key] }.compact.first
|
65
|
+
keys.map { |key| @headers[key] }.compact.first
|
69
66
|
end
|
70
|
-
|
71
67
|
end
|
72
|
-
|
73
68
|
end
|
74
|
-
|
75
69
|
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
module ApiAuth
|
2
|
-
|
3
2
|
module RequestDrivers # :nodoc:
|
4
|
-
|
5
3
|
class FaradayRequest # :nodoc:
|
6
|
-
|
7
4
|
include ApiAuth::Helpers
|
8
5
|
|
9
6
|
def initialize(request)
|
@@ -13,29 +10,25 @@ module ApiAuth
|
|
13
10
|
end
|
14
11
|
|
15
12
|
def set_auth_header(header)
|
16
|
-
@request.headers
|
13
|
+
@request.headers['Authorization'] = header
|
17
14
|
fetch_headers
|
18
15
|
@request
|
19
16
|
end
|
20
17
|
|
21
18
|
def calculated_md5
|
22
|
-
|
23
|
-
body = @request.body
|
24
|
-
else
|
25
|
-
body = ''
|
26
|
-
end
|
19
|
+
body = @request.body ? @request.body : ''
|
27
20
|
md5_base64digest(body)
|
28
21
|
end
|
29
22
|
|
30
23
|
def populate_content_md5
|
31
|
-
if
|
32
|
-
@request.headers[
|
24
|
+
if %w(POST PUT).include?(@request.method.to_s.upcase)
|
25
|
+
@request.headers['Content-MD5'] = calculated_md5
|
33
26
|
fetch_headers
|
34
27
|
end
|
35
28
|
end
|
36
29
|
|
37
30
|
def md5_mismatch?
|
38
|
-
if
|
31
|
+
if %w(POST PUT).include?(@request.method.to_s.upcase)
|
39
32
|
calculated_md5 != content_md5
|
40
33
|
else
|
41
34
|
false
|
@@ -52,12 +45,12 @@ module ApiAuth
|
|
52
45
|
|
53
46
|
def content_type
|
54
47
|
value = find_header(%w(CONTENT-TYPE CONTENT_TYPE HTTP_CONTENT_TYPE))
|
55
|
-
value.nil? ?
|
48
|
+
value.nil? ? '' : value
|
56
49
|
end
|
57
50
|
|
58
51
|
def content_md5
|
59
52
|
value = find_header(%w(CONTENT-MD5 CONTENT_MD5 HTTP-CONTENT-MD5 HTTP_CONTENT_MD5))
|
60
|
-
value.nil? ?
|
53
|
+
value.nil? ? '' : value
|
61
54
|
end
|
62
55
|
|
63
56
|
def request_uri
|
@@ -68,27 +61,24 @@ module ApiAuth
|
|
68
61
|
end
|
69
62
|
|
70
63
|
def set_date
|
71
|
-
@request.headers
|
64
|
+
@request.headers['DATE'] = Time.now.utc.httpdate
|
72
65
|
fetch_headers
|
73
66
|
end
|
74
67
|
|
75
68
|
def timestamp
|
76
69
|
value = find_header(%w(DATE HTTP_DATE))
|
77
|
-
value.nil? ?
|
70
|
+
value.nil? ? '' : value
|
78
71
|
end
|
79
72
|
|
80
73
|
def authorization_header
|
81
74
|
find_header %w(Authorization AUTHORIZATION HTTP_AUTHORIZATION)
|
82
75
|
end
|
83
76
|
|
84
|
-
|
77
|
+
private
|
85
78
|
|
86
79
|
def find_header(keys)
|
87
|
-
keys.map {|key| @headers[key] }.compact.first
|
80
|
+
keys.map { |key| @headers[key] }.compact.first
|
88
81
|
end
|
89
|
-
|
90
82
|
end
|
91
|
-
|
92
83
|
end
|
93
|
-
|
94
84
|
end
|