oauth 0.5.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +136 -115
  3. data/CODE_OF_CONDUCT.md +0 -0
  4. data/CONTRIBUTING.md +19 -2
  5. data/LICENSE +2 -1
  6. data/README.md +267 -67
  7. data/SECURITY.md +18 -8
  8. data/TODO +0 -0
  9. data/lib/oauth/client/action_controller_request.rb +17 -15
  10. data/lib/oauth/client/em_http.rb +30 -30
  11. data/lib/oauth/client/helper.rb +76 -75
  12. data/lib/oauth/client/net_http.rb +109 -102
  13. data/lib/oauth/client.rb +2 -0
  14. data/lib/oauth/consumer.rb +113 -110
  15. data/lib/oauth/errors/error.rb +2 -0
  16. data/lib/oauth/errors/problem.rb +3 -0
  17. data/lib/oauth/errors/unauthorized.rb +4 -0
  18. data/lib/oauth/errors.rb +2 -0
  19. data/lib/oauth/helper.rb +16 -12
  20. data/lib/oauth/oauth.rb +6 -4
  21. data/lib/oauth/oauth_test_helper.rb +2 -0
  22. data/lib/oauth/request_proxy/action_controller_request.rb +3 -24
  23. data/lib/oauth/request_proxy/action_dispatch_request.rb +0 -0
  24. data/lib/oauth/request_proxy/base.rb +2 -2
  25. data/lib/oauth/request_proxy/curb_request.rb +0 -0
  26. data/lib/oauth/request_proxy/em_http_request.rb +0 -0
  27. data/lib/oauth/request_proxy/jabber_request.rb +0 -0
  28. data/lib/oauth/request_proxy/mock_request.rb +1 -1
  29. data/lib/oauth/request_proxy/net_http.rb +5 -7
  30. data/lib/oauth/request_proxy/rack_request.rb +0 -0
  31. data/lib/oauth/request_proxy/rest_client_request.rb +2 -1
  32. data/lib/oauth/request_proxy/typhoeus_request.rb +0 -0
  33. data/lib/oauth/request_proxy.rb +7 -4
  34. data/lib/oauth/server.rb +12 -10
  35. data/lib/oauth/signature/base.rb +71 -66
  36. data/lib/oauth/signature/hmac/sha1.rb +15 -9
  37. data/lib/oauth/signature/hmac/sha256.rb +15 -9
  38. data/lib/oauth/signature/plaintext.rb +18 -20
  39. data/lib/oauth/signature/rsa/sha1.rb +46 -38
  40. data/lib/oauth/signature.rb +8 -5
  41. data/lib/oauth/token.rb +2 -0
  42. data/lib/oauth/tokens/access_token.rb +2 -0
  43. data/lib/oauth/tokens/consumer_token.rb +4 -2
  44. data/lib/oauth/tokens/request_token.rb +12 -10
  45. data/lib/oauth/tokens/server_token.rb +2 -1
  46. data/lib/oauth/tokens/token.rb +2 -0
  47. data/lib/oauth/version.rb +5 -1
  48. data/lib/oauth.rb +9 -2
  49. metadata +87 -35
  50. data/bin/oauth +0 -11
  51. data/lib/oauth/cli/authorize_command.rb +0 -71
  52. data/lib/oauth/cli/base_command.rb +0 -208
  53. data/lib/oauth/cli/help_command.rb +0 -22
  54. data/lib/oauth/cli/query_command.rb +0 -25
  55. data/lib/oauth/cli/sign_command.rb +0 -81
  56. data/lib/oauth/cli/version_command.rb +0 -7
  57. data/lib/oauth/cli.rb +0 -56
@@ -1,101 +1,102 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "oauth/client"
2
4
  require "oauth/consumer"
3
5
  require "oauth/helper"
4
6
  require "oauth/token"
5
7
  require "oauth/signature/hmac/sha1"
6
8
 
7
- module OAuth::Client
8
- class Helper
9
- include OAuth::Helper
9
+ module OAuth
10
+ module Client
11
+ class Helper
12
+ include OAuth::Helper
10
13
 
11
- def initialize(request, options = {})
12
- @request = request
13
- @options = options
14
- @options[:signature_method] ||= "HMAC-SHA1"
15
- end
14
+ def initialize(request, options = {})
15
+ @request = request
16
+ @options = options
17
+ @options[:signature_method] ||= "HMAC-SHA1"
18
+ end
16
19
 
17
- def options
18
- @options
19
- end
20
+ attr_reader :options
20
21
 
21
- def nonce
22
- options[:nonce] ||= generate_key
23
- end
22
+ def nonce
23
+ options[:nonce] ||= generate_key
24
+ end
24
25
 
25
- def timestamp
26
- options[:timestamp] ||= generate_timestamp
27
- end
26
+ def timestamp
27
+ options[:timestamp] ||= generate_timestamp
28
+ end
28
29
 
29
- def oauth_parameters
30
- out = {
31
- "oauth_body_hash" => options[:body_hash],
32
- "oauth_callback" => options[:oauth_callback],
33
- "oauth_consumer_key" => options[:consumer].key,
34
- "oauth_token" => options[:token] ? options[:token].token : "",
35
- "oauth_signature_method" => options[:signature_method],
36
- "oauth_timestamp" => timestamp,
37
- "oauth_nonce" => nonce,
38
- "oauth_verifier" => options[:oauth_verifier],
39
- "oauth_version" => (options[:oauth_version] || "1.0"),
40
- "oauth_session_handle" => options[:oauth_session_handle]
41
- }
42
- allowed_empty_params = options[:allow_empty_params]
43
- if allowed_empty_params != true && !allowed_empty_params.kind_of?(Array)
44
- allowed_empty_params = allowed_empty_params == false ? [] : [allowed_empty_params]
30
+ def oauth_parameters
31
+ out = {
32
+ "oauth_body_hash" => options[:body_hash],
33
+ "oauth_callback" => options[:oauth_callback],
34
+ "oauth_consumer_key" => options[:consumer].key,
35
+ "oauth_token" => options[:token] ? options[:token].token : "",
36
+ "oauth_signature_method" => options[:signature_method],
37
+ "oauth_timestamp" => timestamp,
38
+ "oauth_nonce" => nonce,
39
+ "oauth_verifier" => options[:oauth_verifier],
40
+ "oauth_version" => (options[:oauth_version] || "1.0"),
41
+ "oauth_session_handle" => options[:oauth_session_handle]
42
+ }
43
+ allowed_empty_params = options[:allow_empty_params]
44
+ if allowed_empty_params != true && !allowed_empty_params.is_a?(Array)
45
+ allowed_empty_params = allowed_empty_params == false ? [] : [allowed_empty_params]
46
+ end
47
+ out.select! { |k, v| v.to_s != "" || allowed_empty_params == true || allowed_empty_params.include?(k) }
48
+ out
45
49
  end
46
- out.select! { |k,v| v.to_s != "" || allowed_empty_params == true || allowed_empty_params.include?(k) }
47
- out
48
- end
49
50
 
50
- def signature(extra_options = {})
51
- OAuth::Signature.sign(@request, { :uri => options[:request_uri],
52
- :consumer => options[:consumer],
53
- :token => options[:token],
54
- :unsigned_parameters => options[:unsigned_parameters]
55
- }.merge(extra_options) )
56
- end
51
+ def signature(extra_options = {})
52
+ OAuth::Signature.sign(@request, { uri: options[:request_uri],
53
+ consumer: options[:consumer],
54
+ token: options[:token],
55
+ unsigned_parameters: options[:unsigned_parameters] }.merge(extra_options))
56
+ end
57
57
 
58
- def signature_base_string(extra_options = {})
59
- OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
60
- :consumer => options[:consumer],
61
- :token => options[:token],
62
- :parameters => oauth_parameters}.merge(extra_options) )
63
- end
58
+ def signature_base_string(extra_options = {})
59
+ OAuth::Signature.signature_base_string(@request, { uri: options[:request_uri],
60
+ consumer: options[:consumer],
61
+ token: options[:token],
62
+ parameters: oauth_parameters }.merge(extra_options))
63
+ end
64
64
 
65
- def token_request?
66
- @options[:token_request].eql?(true)
67
- end
65
+ def token_request?
66
+ @options[:token_request].eql?(true)
67
+ end
68
68
 
69
- def hash_body
70
- @options[:body_hash] = OAuth::Signature.body_hash(@request, :parameters => oauth_parameters)
71
- end
69
+ def hash_body
70
+ @options[:body_hash] = OAuth::Signature.body_hash(@request, parameters: oauth_parameters)
71
+ end
72
72
 
73
- def amend_user_agent_header(headers)
74
- @oauth_ua_string ||= "OAuth gem v#{OAuth::VERSION}"
75
- # Net::HTTP in 1.9 appends Ruby
76
- if headers["User-Agent"] && headers["User-Agent"] != "Ruby"
77
- headers["User-Agent"] += " (#{@oauth_ua_string})"
78
- else
79
- headers["User-Agent"] = @oauth_ua_string
73
+ def amend_user_agent_header(headers)
74
+ @oauth_ua_string ||= "OAuth gem v#{OAuth::Version::VERSION}"
75
+ # Net::HTTP in 1.9 appends Ruby
76
+ if headers["User-Agent"] && headers["User-Agent"] != "Ruby"
77
+ headers["User-Agent"] += " (#{@oauth_ua_string})"
78
+ else
79
+ headers["User-Agent"] = @oauth_ua_string
80
+ end
80
81
  end
81
- end
82
82
 
83
- def header
84
- parameters = oauth_parameters
85
- parameters.merge!("oauth_signature" => signature(options.merge(:parameters => parameters)))
83
+ def header
84
+ parameters = oauth_parameters
85
+ parameters["oauth_signature"] = signature(options.merge(parameters: parameters))
86
86
 
87
- header_params_str = parameters.sort.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(", ")
87
+ header_params_str = parameters.sort.map { |k, v| "#{k}=\"#{escape(v)}\"" }.join(", ")
88
88
 
89
- realm = "realm=\"#{options[:realm]}\", " if options[:realm]
90
- "OAuth #{realm}#{header_params_str}"
91
- end
89
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
90
+ "OAuth #{realm}#{header_params_str}"
91
+ end
92
92
 
93
- def parameters
94
- OAuth::RequestProxy.proxy(@request).parameters
95
- end
93
+ def parameters
94
+ OAuth::RequestProxy.proxy(@request).parameters
95
+ end
96
96
 
97
- def parameters_with_oauth
98
- oauth_parameters.merge(parameters)
97
+ def parameters_with_oauth
98
+ oauth_parameters.merge(parameters)
99
+ end
99
100
  end
100
101
  end
101
102
  end
@@ -1,121 +1,128 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "oauth/helper"
2
4
  require "oauth/request_proxy/net_http"
3
5
 
4
- class Net::HTTPGenericRequest
5
- include OAuth::Helper
6
-
7
- attr_reader :oauth_helper
8
-
9
- # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
10
- # this may add a header, additional query string parameters, or additional POST body parameters.
11
- # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
12
- # header.
13
- #
14
- # * http - Configured Net::HTTP instance
15
- # * consumer - OAuth::Consumer instance
16
- # * token - OAuth::Token instance
17
- # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
18
- # +signature_method+, +nonce+, +timestamp+)
19
- #
20
- # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
21
- #
22
- # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1],
23
- # {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html,
24
- # http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include]
25
- def oauth!(http, consumer = nil, token = nil, options = {})
26
- helper_options = oauth_helper_options(http, consumer, token, options)
27
- @oauth_helper = OAuth::Client::Helper.new(self, helper_options)
28
- @oauth_helper.amend_user_agent_header(self)
29
- @oauth_helper.hash_body if oauth_body_hash_required?
30
- self.send("set_oauth_#{helper_options[:scheme]}")
31
- end
6
+ module Net
7
+ class HTTPGenericRequest
8
+ include OAuth::Helper
9
+
10
+ attr_reader :oauth_helper
11
+
12
+ # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
13
+ # this may add a header, additional query string parameters, or additional POST body parameters.
14
+ # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
15
+ # header.
16
+ #
17
+ # * http - Configured Net::HTTP instance
18
+ # * consumer - OAuth::Consumer instance
19
+ # * token - OAuth::Token instance
20
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
21
+ # +signature_method+, +nonce+, +timestamp+, +body_hash+)
22
+ #
23
+ # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
24
+ #
25
+ # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1],
26
+ # {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html,
27
+ # http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include]
28
+ def oauth!(http, consumer = nil, token = nil, options = {})
29
+ helper_options = oauth_helper_options(http, consumer, token, options)
30
+ @oauth_helper = OAuth::Client::Helper.new(self, helper_options)
31
+ @oauth_helper.amend_user_agent_header(self)
32
+ @oauth_helper.hash_body if oauth_body_hash_required?(helper_options)
33
+ send("set_oauth_#{helper_options[:scheme]}")
34
+ end
32
35
 
33
- # Create a string suitable for signing for an HTTP request. This process involves parameter
34
- # normalization as specified in the OAuth specification. The exact normalization also depends
35
- # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
36
- # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
37
- # header.
38
- #
39
- # * http - Configured Net::HTTP instance
40
- # * consumer - OAuth::Consumer instance
41
- # * token - OAuth::Token instance
42
- # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
43
- # +signature_method+, +nonce+, +timestamp+)
44
- #
45
- # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1],
46
- # {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html,
47
- # http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include]
48
- def signature_base_string(http, consumer = nil, token = nil, options = {})
49
- helper_options = oauth_helper_options(http, consumer, token, options)
50
- @oauth_helper = OAuth::Client::Helper.new(self, helper_options)
51
- @oauth_helper.hash_body if oauth_body_hash_required?
52
- @oauth_helper.signature_base_string
53
- end
36
+ # Create a string suitable for signing for an HTTP request. This process involves parameter
37
+ # normalization as specified in the OAuth specification. The exact normalization also depends
38
+ # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
39
+ # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
40
+ # header.
41
+ #
42
+ # * http - Configured Net::HTTP instance
43
+ # * consumer - OAuth::Consumer instance
44
+ # * token - OAuth::Token instance
45
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
46
+ # +signature_method+, +nonce+, +timestamp+)
47
+ #
48
+ # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1],
49
+ # {OAuth Request Body Hash 1.0 Draft 4}[http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/drafts/4/spec.html,
50
+ # http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include]
51
+ def signature_base_string(http, consumer = nil, token = nil, options = {})
52
+ helper_options = oauth_helper_options(http, consumer, token, options)
53
+ @oauth_helper = OAuth::Client::Helper.new(self, helper_options)
54
+ @oauth_helper.hash_body if oauth_body_hash_required?(helper_options)
55
+ @oauth_helper.signature_base_string
56
+ end
57
+
58
+ private
59
+
60
+ def oauth_helper_options(http, consumer, token, options)
61
+ { request_uri: oauth_full_request_uri(http, options),
62
+ consumer: consumer,
63
+ token: token,
64
+ scheme: "header",
65
+ signature_method: nil,
66
+ nonce: nil,
67
+ timestamp: nil,
68
+ body_hash_enabled: true }.merge(options)
69
+ end
54
70
 
55
- private
71
+ def oauth_full_request_uri(http, options)
72
+ uri = URI.parse(path)
73
+ uri.host = http.address
74
+ uri.port = http.port
56
75
 
57
- def oauth_helper_options(http, consumer, token, options)
58
- { :request_uri => oauth_full_request_uri(http,options),
59
- :consumer => consumer,
60
- :token => token,
61
- :scheme => "header",
62
- :signature_method => nil,
63
- :nonce => nil,
64
- :timestamp => nil }.merge(options)
65
- end
76
+ if options[:request_endpoint] && options[:site]
77
+ is_https = options[:site].match(%r{^https://})
78
+ uri.host = options[:site].gsub(%r{^https?://}, "")
79
+ uri.port ||= is_https ? 443 : 80
80
+ end
66
81
 
67
- def oauth_full_request_uri(http,options)
68
- uri = URI.parse(self.path)
69
- uri.host = http.address
70
- uri.port = http.port
82
+ uri.scheme = if http.respond_to?(:use_ssl?) && http.use_ssl?
83
+ "https"
84
+ else
85
+ "http"
86
+ end
71
87
 
72
- if options[:request_endpoint] && options[:site]
73
- is_https = options[:site].match(%r(^https://))
74
- uri.host = options[:site].gsub(%r(^https?://), "")
75
- uri.port ||= is_https ? 443 : 80
88
+ uri.to_s
76
89
  end
77
90
 
78
- if http.respond_to?(:use_ssl?) && http.use_ssl?
79
- uri.scheme = "https"
80
- else
81
- uri.scheme = "http"
91
+ def oauth_body_hash_required?(options)
92
+ !@oauth_helper.token_request? && request_body_permitted? && !content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded") && options[:body_hash_enabled]
82
93
  end
83
94
 
84
- uri.to_s
85
- end
95
+ def set_oauth_header
96
+ self["Authorization"] = @oauth_helper.header
97
+ end
86
98
 
87
- def oauth_body_hash_required?
88
- !@oauth_helper.token_request? && request_body_permitted? && !content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded")
89
- end
99
+ # FIXME: if you're using a POST body and query string parameters, this method
100
+ # will move query string parameters into the body unexpectedly. This may
101
+ # cause problems with non-x-www-form-urlencoded bodies submitted to URLs
102
+ # containing query string params. If duplicate parameters are present in both
103
+ # places, all instances should be included when calculating the signature
104
+ # base string.
105
+
106
+ def set_oauth_body
107
+ # NOTE: OAuth::Helper and @oauth_helper are not the same, despite sharing all methods defined in OAuth::Helper
108
+ # see: https://stackoverflow.com/a/53447775/213191
109
+ set_form_data(OAuth::Helper.stringify_keys(@oauth_helper.parameters_with_oauth))
110
+ params_with_sig = @oauth_helper.parameters.merge(oauth_signature: @oauth_helper.signature)
111
+ set_form_data(OAuth::Helper.stringify_keys(params_with_sig))
112
+ end
90
113
 
91
- def set_oauth_header
92
- self["Authorization"] = @oauth_helper.header
93
- end
114
+ def set_oauth_query_string
115
+ oauth_params_str = @oauth_helper.oauth_parameters.map { |k, v| [escape(k), escape(v)].join("=") }.join("&")
116
+ uri = URI.parse(path)
117
+ uri.query = if uri.query.to_s == ""
118
+ oauth_params_str
119
+ else
120
+ "#{uri.query}&#{oauth_params_str}"
121
+ end
94
122
 
95
- # FIXME: if you're using a POST body and query string parameters, this method
96
- # will move query string parameters into the body unexpectedly. This may
97
- # cause problems with non-x-www-form-urlencoded bodies submitted to URLs
98
- # containing query string params. If duplicate parameters are present in both
99
- # places, all instances should be included when calculating the signature
100
- # base string.
101
-
102
- def set_oauth_body
103
- self.set_form_data(@oauth_helper.stringify_keys(@oauth_helper.parameters_with_oauth))
104
- params_with_sig = @oauth_helper.parameters.merge(:oauth_signature => @oauth_helper.signature)
105
- self.set_form_data(@oauth_helper.stringify_keys(params_with_sig))
106
- end
123
+ @path = uri.to_s
107
124
 
108
- def set_oauth_query_string
109
- oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| [escape(k), escape(v)] * "=" }.join("&")
110
- uri = URI.parse(path)
111
- if uri.query.to_s == ""
112
- uri.query = oauth_params_str
113
- else
114
- uri.query = uri.query + "&" + oauth_params_str
125
+ @path << "&oauth_signature=#{escape(oauth_helper.signature)}"
115
126
  end
116
-
117
- @path = uri.to_s
118
-
119
- @path << "&oauth_signature=#{escape(oauth_helper.signature)}"
120
127
  end
121
128
  end
data/lib/oauth/client.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  module Client
3
5
  end