oauth 0.5.14 → 1.1.6
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
- checksums.yaml.gz.sig +1 -0
- data/CHANGELOG.md +663 -239
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +79 -29
- data/CONTRIBUTING.md +264 -15
- data/FUNDING.md +74 -0
- data/LICENSE.md +71 -0
- data/README.md +642 -297
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +11 -12
- data/certs/pboling.pem +27 -0
- data/lib/oauth/auth_sanitizer.rb +36 -0
- data/lib/oauth/client/action_controller_request.rb +24 -12
- data/lib/oauth/client/em_http.rb +107 -100
- data/lib/oauth/client/helper.rb +80 -72
- data/lib/oauth/client/net_http.rb +139 -106
- data/lib/oauth/client.rb +2 -0
- data/lib/oauth/consumer.rb +250 -118
- data/lib/oauth/errors/error.rb +2 -0
- data/lib/oauth/errors/problem.rb +4 -1
- data/lib/oauth/errors/unauthorized.rb +4 -0
- data/lib/oauth/errors.rb +2 -0
- data/lib/oauth/helper.rb +34 -8
- data/lib/oauth/oauth.rb +32 -8
- data/lib/oauth/oauth_test_helper.rb +2 -0
- data/lib/oauth/optional.rb +20 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +14 -31
- data/lib/oauth/request_proxy/action_dispatch_request.rb +34 -0
- data/lib/oauth/request_proxy/base.rb +42 -31
- data/lib/oauth/request_proxy/em_http_request.rb +53 -52
- data/lib/oauth/request_proxy/jabber_request.rb +9 -2
- data/lib/oauth/request_proxy/mock_request.rb +1 -1
- data/lib/oauth/request_proxy/net_http.rb +6 -8
- data/lib/oauth/request_proxy/rack_request.rb +0 -4
- data/lib/oauth/request_proxy/rest_client_request.rb +6 -4
- data/lib/oauth/request_proxy.rb +20 -13
- data/lib/oauth/server.rb +14 -6
- data/lib/oauth/signature/base.rb +82 -66
- data/lib/oauth/signature/hmac/sha1.rb +15 -9
- data/lib/oauth/signature/hmac/sha256.rb +15 -9
- data/lib/oauth/signature/plaintext.rb +18 -20
- data/lib/oauth/signature/rsa/sha1.rb +53 -38
- data/lib/oauth/signature.rb +40 -33
- data/lib/oauth/token.rb +2 -0
- data/lib/oauth/tokens/access_token.rb +3 -1
- data/lib/oauth/tokens/consumer_token.rb +10 -6
- data/lib/oauth/tokens/request_token.rb +12 -4
- data/lib/oauth/tokens/server_token.rb +2 -0
- data/lib/oauth/tokens/token.rb +15 -1
- data/lib/oauth/version.rb +6 -1
- data/lib/oauth.rb +11 -2
- data/sig/oauth/consumer.rbs +9 -0
- data/sig/oauth/signature/base.rbs +12 -0
- data/sig/oauth/tokens/token.rbs +8 -0
- data/sig/oauth/version.rbs +6 -0
- data.tar.gz.sig +0 -0
- metadata +349 -90
- metadata.gz.sig +0 -0
- data/LICENSE +0 -21
- data/TODO +0 -32
- data/bin/oauth +0 -11
- data/lib/oauth/cli/authorize_command.rb +0 -69
- data/lib/oauth/cli/base_command.rb +0 -210
- data/lib/oauth/cli/help_command.rb +0 -22
- data/lib/oauth/cli/query_command.rb +0 -25
- data/lib/oauth/cli/sign_command.rb +0 -78
- data/lib/oauth/cli/version_command.rb +0 -7
- data/lib/oauth/cli.rb +0 -56
data/lib/oauth/helper.rb
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "time"
|
|
1
4
|
require "openssl"
|
|
2
5
|
require "base64"
|
|
3
6
|
|
|
4
7
|
module OAuth
|
|
5
8
|
module Helper
|
|
6
|
-
|
|
9
|
+
module_function
|
|
7
10
|
|
|
8
11
|
# Escape +value+ by URL encoding all non-reserved character.
|
|
9
12
|
#
|
|
@@ -15,11 +18,33 @@ module OAuth
|
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
def _escape(string)
|
|
18
|
-
|
|
21
|
+
# Percent-encode per RFC 3986 (unreserved: A-Z a-z 0-9 - . _ ~)
|
|
22
|
+
# Encode by byte to ensure stable behavior across Ruby versions and encodings.
|
|
23
|
+
bytes = string.to_s.b.bytes
|
|
24
|
+
bytes.map do |b|
|
|
25
|
+
ch = b.chr
|
|
26
|
+
if ch =~ OAuth::RESERVED_CHARACTERS
|
|
27
|
+
"%%%02X" % b
|
|
28
|
+
else
|
|
29
|
+
ch
|
|
30
|
+
end
|
|
31
|
+
end.join
|
|
19
32
|
end
|
|
20
33
|
|
|
21
34
|
def unescape(value)
|
|
22
|
-
|
|
35
|
+
# Do NOT treat "+" as space; OAuth treats '+' as a literal plus unless percent-encoded.
|
|
36
|
+
str = value.to_s.gsub("+", "%2B")
|
|
37
|
+
# Decode %HH sequences; leave malformed sequences intact.
|
|
38
|
+
decoded = str.gsub(/%([0-9A-Fa-f]{2})/) { Regexp.last_match(1).to_i(16).chr }
|
|
39
|
+
# Prefer UTF-8 when the decoded bytes form valid UTF-8; otherwise, return as binary.
|
|
40
|
+
begin
|
|
41
|
+
utf8 = decoded.dup
|
|
42
|
+
utf8.force_encoding(Encoding::UTF_8)
|
|
43
|
+
decoded = utf8 if utf8.valid_encoding?
|
|
44
|
+
rescue NameError
|
|
45
|
+
# Older Rubies without Encoding constants: keep original encoding.
|
|
46
|
+
end
|
|
47
|
+
decoded
|
|
23
48
|
end
|
|
24
49
|
|
|
25
50
|
# Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
|
|
@@ -28,9 +53,9 @@ module OAuth
|
|
|
28
53
|
Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, "")
|
|
29
54
|
end
|
|
30
55
|
|
|
31
|
-
|
|
56
|
+
alias_method :generate_nonce, :generate_key
|
|
32
57
|
|
|
33
|
-
def generate_timestamp
|
|
58
|
+
def generate_timestamp # :nodoc:
|
|
34
59
|
Time.now.to_i.to_s
|
|
35
60
|
end
|
|
36
61
|
|
|
@@ -43,7 +68,8 @@ module OAuth
|
|
|
43
68
|
# See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
|
|
44
69
|
def normalize(params)
|
|
45
70
|
params.sort.map do |k, values|
|
|
46
|
-
|
|
71
|
+
case values
|
|
72
|
+
when Array
|
|
47
73
|
# make sure the array has an element so we don't lose the key
|
|
48
74
|
values << nil if values.empty?
|
|
49
75
|
# multiple values were provided for a single key
|
|
@@ -54,7 +80,7 @@ module OAuth
|
|
|
54
80
|
[escape(k), escape(v)].join("=")
|
|
55
81
|
end
|
|
56
82
|
end
|
|
57
|
-
|
|
83
|
+
when Hash
|
|
58
84
|
normalize_nested_query(values, k)
|
|
59
85
|
else
|
|
60
86
|
[escape(k), escape(values)].join("=")
|
|
@@ -99,7 +125,7 @@ module OAuth
|
|
|
99
125
|
# strip and unescape
|
|
100
126
|
val = unescape(v.strip)
|
|
101
127
|
# strip quotes
|
|
102
|
-
val.sub(
|
|
128
|
+
val.sub(/^"(.*)"$/, '\1')
|
|
103
129
|
end
|
|
104
130
|
|
|
105
131
|
# convert into a Hash
|
data/lib/oauth/oauth.rb
CHANGED
|
@@ -1,13 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module OAuth
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
|
|
4
|
+
# Out-Of-Band callback token value.
|
|
5
|
+
# OAuth 1.0 and 1.0a both support out-of-band flows, where callbacks cannot be used.
|
|
6
|
+
# See RFC 5849 (OAuth 1.0), Section 6.1.1: Obtaining an Unauthorized Request Token
|
|
7
|
+
# and the 1.0a errata. Providers treating "oob" as the callback URL indicate that
|
|
8
|
+
# the verifier (for 1.0a) will be communicated out of band to the Consumer.
|
|
9
|
+
OUT_OF_BAND = "oob"
|
|
5
10
|
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
# OAuth parameter keys this library recognizes when normalizing/signing requests.
|
|
12
|
+
# Notes on 1.0 vs 1.0a:
|
|
13
|
+
# - oauth_verifier: Introduced by OAuth 1.0a. Returned to the Consumer after user
|
|
14
|
+
# authorization and required when exchanging a Request Token for an Access Token
|
|
15
|
+
# (Section 6.3.1 in RFC 5849 / 1.0a change).
|
|
16
|
+
# - oauth_callback: Present in 1.0; 1.0a clarified that the Consumer MUST send it when
|
|
17
|
+
# obtaining a Request Token (or use "oob") and that the Service Provider MUST return
|
|
18
|
+
# oauth_callback_confirmed=true with the Request Token response to prevent session
|
|
19
|
+
# fixation attacks. Note that oauth_callback_confirmed is a response parameter, not
|
|
20
|
+
# a request signing parameter, and thus is not listed here.
|
|
21
|
+
# Other keys are common to both 1.0 and 1.0a.
|
|
22
|
+
PARAMETERS = %w[
|
|
23
|
+
oauth_callback
|
|
24
|
+
oauth_consumer_key
|
|
25
|
+
oauth_token
|
|
26
|
+
oauth_signature_method
|
|
27
|
+
oauth_timestamp
|
|
28
|
+
oauth_nonce
|
|
29
|
+
oauth_verifier
|
|
30
|
+
oauth_version
|
|
31
|
+
oauth_signature
|
|
32
|
+
oauth_body_hash
|
|
33
|
+
].freeze
|
|
10
34
|
|
|
11
35
|
# reserved character regexp, per section 5.1
|
|
12
|
-
RESERVED_CHARACTERS = /[^a-zA-Z0-9
|
|
36
|
+
RESERVED_CHARACTERS = /[^a-zA-Z0-9\-._~]/.freeze
|
|
13
37
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OAuth
|
|
4
|
+
# Helpers for optional, lazily loaded integrations.
|
|
5
|
+
module Optional
|
|
6
|
+
class << self
|
|
7
|
+
# Try to load EventMachine HTTP client support provided by em-http-request.
|
|
8
|
+
#
|
|
9
|
+
# Returns true if available, false if the dependency is not installed.
|
|
10
|
+
# Never raises LoadError.
|
|
11
|
+
def em_http_available?
|
|
12
|
+
# em-http-request provides "em-http" entrypoint
|
|
13
|
+
require "em-http"
|
|
14
|
+
true
|
|
15
|
+
rescue LoadError
|
|
16
|
+
false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -1,56 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "active_support"
|
|
4
|
-
require "active_support/version"
|
|
5
4
|
require "action_controller"
|
|
6
5
|
require "uri"
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
# rails 2.x
|
|
10
|
-
require "action_controller/request"
|
|
11
|
-
unless ActionController::Request::HTTP_METHODS.include?("patch")
|
|
12
|
-
ActionController::Request::HTTP_METHODS << "patch"
|
|
13
|
-
ActionController::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
|
|
14
|
-
ActionController::Request::HTTP_METHOD_LOOKUP["patch"] = :patch
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
elsif Gem::Version.new(ActiveSupport::VERSION::STRING) < Gem::Version.new("4")
|
|
18
|
-
# rails 3.x
|
|
19
|
-
require "action_dispatch/http/request"
|
|
20
|
-
unless ActionDispatch::Request::HTTP_METHODS.include?("patch")
|
|
21
|
-
ActionDispatch::Request::HTTP_METHODS << "patch"
|
|
22
|
-
ActionDispatch::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
|
|
23
|
-
ActionDispatch::Request::HTTP_METHOD_LOOKUP["patch"] = :patch
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
else # rails 4.x and later - already has patch
|
|
27
|
-
require "action_dispatch/http/request"
|
|
28
|
-
end
|
|
7
|
+
require "action_dispatch/http/request"
|
|
29
8
|
|
|
30
9
|
module OAuth
|
|
31
10
|
module RequestProxy
|
|
32
11
|
class ActionControllerRequest < OAuth::RequestProxy::Base
|
|
33
|
-
proxies(
|
|
12
|
+
proxies(::ActionDispatch::Request)
|
|
34
13
|
|
|
35
14
|
def method
|
|
36
15
|
request.method.to_s.upcase
|
|
37
16
|
end
|
|
38
17
|
|
|
39
18
|
def uri
|
|
40
|
-
request.url
|
|
19
|
+
options[:uri] || request.url
|
|
41
20
|
end
|
|
42
21
|
|
|
43
22
|
def parameters
|
|
44
23
|
if options[:clobber_request]
|
|
45
24
|
options[:parameters] || {}
|
|
46
25
|
else
|
|
47
|
-
params
|
|
26
|
+
# Rails proxies should expose array-style values for params to align with
|
|
27
|
+
# historical oauth gem behavior / specs. Header params remain scalars.
|
|
28
|
+
rq = wrap_values(request_params)
|
|
29
|
+
qq = wrap_values(query_params)
|
|
30
|
+
params = rq.merge(qq).merge(header_params)
|
|
48
31
|
params.stringify_keys! if params.respond_to?(:stringify_keys!)
|
|
49
32
|
params.merge(options[:parameters] || {})
|
|
50
33
|
end
|
|
51
34
|
end
|
|
52
35
|
|
|
53
|
-
# Override from OAuth::RequestProxy::Base to avoid
|
|
36
|
+
# Override from OAuth::RequestProxy::Base to avoid round-trip
|
|
54
37
|
# conversion to Hash or Array and thus preserve the original
|
|
55
38
|
# parameter names
|
|
56
39
|
def parameters_for_signature
|
|
@@ -64,11 +47,11 @@ module OAuth
|
|
|
64
47
|
params << request.raw_post if raw_post_signature?
|
|
65
48
|
end
|
|
66
49
|
|
|
67
|
-
params
|
|
68
|
-
join("&").split("&")
|
|
69
|
-
reject { |s| s.match(/\A\s*\z/) }
|
|
70
|
-
map { |p| p.split("=").map { |esc| CGI.unescape(esc) } }
|
|
71
|
-
reject { |kv| kv[0] == "oauth_signature" }
|
|
50
|
+
params
|
|
51
|
+
.join("&").split("&")
|
|
52
|
+
.reject { |s| s.match(/\A\s*\z/) }
|
|
53
|
+
.map { |p| p.split("=").map { |esc| CGI.unescape(esc) } }
|
|
54
|
+
.reject { |kv| kv[0] == "oauth_signature" }
|
|
72
55
|
end
|
|
73
56
|
|
|
74
57
|
def raw_post_signature?
|
|
@@ -6,6 +6,40 @@ module OAuth
|
|
|
6
6
|
module RequestProxy
|
|
7
7
|
class ActionDispatchRequest < OAuth::RequestProxy::RackRequest
|
|
8
8
|
proxies ::ActionDispatch::Request
|
|
9
|
+
|
|
10
|
+
# Prefer the explicitly provided URI, which carries scheme/host info
|
|
11
|
+
# when ActionDispatch env may be minimal in tests.
|
|
12
|
+
def uri
|
|
13
|
+
options[:uri] || super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Rails' ActionDispatch proxy should expose array-style parameters
|
|
17
|
+
# for request/query params to align with legacy oauth gem expectations.
|
|
18
|
+
def parameters
|
|
19
|
+
if options[:clobber_request]
|
|
20
|
+
options[:parameters] || {}
|
|
21
|
+
else
|
|
22
|
+
rq = wrap_values(request_params)
|
|
23
|
+
qq = wrap_values(query_params)
|
|
24
|
+
params = rq.merge(qq).merge(header_params)
|
|
25
|
+
params.merge(options[:parameters] || {})
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
protected
|
|
30
|
+
|
|
31
|
+
def query_params
|
|
32
|
+
# ActionDispatch::Request responds to GET
|
|
33
|
+
request.GET
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def request_params
|
|
37
|
+
if request.content_type && request.content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded")
|
|
38
|
+
request.POST
|
|
39
|
+
else
|
|
40
|
+
{}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
9
43
|
end
|
|
10
44
|
end
|
|
11
45
|
end
|
|
@@ -8,8 +8,10 @@ module OAuth
|
|
|
8
8
|
class Base
|
|
9
9
|
include OAuth::Helper
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
class << self
|
|
12
|
+
def proxies(klass)
|
|
13
|
+
OAuth::RequestProxy.available_proxies[klass] = self
|
|
14
|
+
end
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
attr_accessor :request, :options, :unsigned_parameters
|
|
@@ -23,15 +25,15 @@ module OAuth
|
|
|
23
25
|
## OAuth parameters
|
|
24
26
|
|
|
25
27
|
def oauth_callback
|
|
26
|
-
parameters["oauth_callback"]
|
|
28
|
+
[parameters["oauth_callback"]].flatten.first
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def oauth_consumer_key
|
|
30
|
-
parameters["oauth_consumer_key"]
|
|
32
|
+
[parameters["oauth_consumer_key"]].flatten.first
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def oauth_nonce
|
|
34
|
-
parameters["oauth_nonce"]
|
|
36
|
+
[parameters["oauth_nonce"]].flatten.first
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def oauth_signature
|
|
@@ -40,37 +42,35 @@ module OAuth
|
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
def oauth_signature_method
|
|
43
|
-
|
|
44
|
-
when Array
|
|
45
|
-
parameters["oauth_signature_method"].first
|
|
46
|
-
else
|
|
47
|
-
parameters["oauth_signature_method"]
|
|
48
|
-
end
|
|
45
|
+
[parameters["oauth_signature_method"]].flatten.first
|
|
49
46
|
end
|
|
50
47
|
|
|
51
48
|
def oauth_timestamp
|
|
52
|
-
parameters["oauth_timestamp"]
|
|
49
|
+
[parameters["oauth_timestamp"]].flatten.first
|
|
53
50
|
end
|
|
54
51
|
|
|
55
52
|
def oauth_token
|
|
56
|
-
parameters["oauth_token"]
|
|
53
|
+
[parameters["oauth_token"]].flatten.first
|
|
57
54
|
end
|
|
58
55
|
|
|
56
|
+
# OAuth 1.0a only: value returned to the Consumer after user authorization
|
|
57
|
+
# and required when exchanging a Request Token for an Access Token.
|
|
58
|
+
# Not present in OAuth 1.0 flows.
|
|
59
59
|
def oauth_verifier
|
|
60
|
-
parameters["oauth_verifier"]
|
|
60
|
+
[parameters["oauth_verifier"]].flatten.first
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
def oauth_version
|
|
64
|
-
parameters["oauth_version"]
|
|
64
|
+
[parameters["oauth_version"]].flatten.first
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# TODO: deprecate these
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
alias_method :consumer_key, :oauth_consumer_key
|
|
69
|
+
alias_method :token, :oauth_token
|
|
70
|
+
alias_method :nonce, :oauth_nonce
|
|
71
|
+
alias_method :timestamp, :oauth_timestamp
|
|
72
|
+
alias_method :signature, :oauth_signature
|
|
73
|
+
alias_method :signature_method, :oauth_signature_method
|
|
74
74
|
|
|
75
75
|
## Parameter accessors
|
|
76
76
|
|
|
@@ -79,15 +79,15 @@ module OAuth
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def parameters_for_signature
|
|
82
|
-
parameters.
|
|
82
|
+
parameters.select { |k, _v| !signature_and_unsigned_parameters.include?(k) }
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def oauth_parameters
|
|
86
|
-
parameters.select { |k,
|
|
86
|
+
parameters.select { |k, v| OAuth::PARAMETERS.include?(k) && !v.nil? && v != "" }
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def non_oauth_parameters
|
|
90
|
-
parameters.
|
|
90
|
+
parameters.select { |k, _v| !OAuth::PARAMETERS.include?(k) }
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
def signature_and_unsigned_parameters
|
|
@@ -97,7 +97,7 @@ module OAuth
|
|
|
97
97
|
# See 9.1.2 in specs
|
|
98
98
|
def normalized_uri
|
|
99
99
|
u = URI.parse(uri)
|
|
100
|
-
"#{u.scheme.downcase}://#{u.host.downcase}#{(u.scheme.casecmp("http").zero? && u.port != 80) || (u.scheme.casecmp("https").zero? && u.port != 443)
|
|
100
|
+
"#{u.scheme.downcase}://#{u.host.downcase}#{":#{u.port}" if (u.scheme.casecmp("http").zero? && u.port != 80) || (u.scheme.casecmp("https").zero? && u.port != 443)}#{(u.path && u.path != "") ? u.path : "/"}"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
# See 9.1.1. in specs Normalize Request Parameters
|
|
@@ -127,17 +127,17 @@ module OAuth
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
# URI, including OAuth parameters
|
|
130
|
-
def signed_uri(with_oauth
|
|
130
|
+
def signed_uri(with_oauth: true)
|
|
131
131
|
if signed?
|
|
132
132
|
params = if with_oauth
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
parameters
|
|
134
|
+
else
|
|
135
|
+
non_oauth_parameters
|
|
136
|
+
end
|
|
137
137
|
|
|
138
138
|
[uri, normalize(params)].join("?")
|
|
139
139
|
else
|
|
140
|
-
warn
|
|
140
|
+
warn("This request has not yet been signed!")
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
|
|
@@ -177,6 +177,17 @@ module OAuth
|
|
|
177
177
|
|
|
178
178
|
{}
|
|
179
179
|
end
|
|
180
|
+
|
|
181
|
+
# Utility to make parameter values array-style (or keep nil) so that
|
|
182
|
+
# subclasses can rely on array values for parameter merging/signing.
|
|
183
|
+
# Mirrors the implementation previously present in
|
|
184
|
+
# ActionDispatchRequest#wrap_values.
|
|
185
|
+
def wrap_values(hash)
|
|
186
|
+
return {} unless hash
|
|
187
|
+
hash.each_with_object({}) do |(k, v), acc|
|
|
188
|
+
acc[k] = (v.is_a?(Array) || v.nil?) ? v : [v]
|
|
189
|
+
end
|
|
190
|
+
end
|
|
180
191
|
end
|
|
181
192
|
end
|
|
182
193
|
end
|
|
@@ -1,74 +1,75 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "oauth/request_proxy/base"
|
|
4
|
-
|
|
5
|
-
require "em-http"
|
|
4
|
+
require "oauth/optional"
|
|
6
5
|
require "cgi"
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
module
|
|
10
|
-
module
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
if OAuth::Optional.em_http_available?
|
|
8
|
+
module OAuth
|
|
9
|
+
module RequestProxy
|
|
10
|
+
module EventMachine
|
|
11
|
+
class HttpRequest < OAuth::RequestProxy::Base
|
|
12
|
+
# A Proxy for use when you need to sign EventMachine::HttpClient instances.
|
|
13
|
+
# It needs to be called once the client is construct but before data is sent.
|
|
14
|
+
# Also see oauth/client/em-http
|
|
15
|
+
proxies ::EventMachine::HttpClient
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# Request in this con
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
def method
|
|
20
|
+
request.req[:method]
|
|
21
|
+
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
def uri
|
|
24
|
+
request.conn.normalize.to_s
|
|
25
|
+
end
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
def parameters
|
|
28
|
+
if options[:clobber_request]
|
|
29
|
+
options[:parameters]
|
|
30
|
+
else
|
|
31
|
+
all_parameters
|
|
32
|
+
end
|
|
32
33
|
end
|
|
33
|
-
end
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
protected
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
def all_parameters
|
|
38
|
+
merged_parameters({}, post_parameters, query_parameters, options[:parameters])
|
|
39
|
+
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
def query_parameters
|
|
42
|
+
quer = request.req[:query]
|
|
43
|
+
hash_quer = if quer.respond_to?(:merge)
|
|
44
|
+
quer
|
|
45
|
+
else
|
|
46
|
+
CGI.parse(quer.to_s)
|
|
47
|
+
end
|
|
48
|
+
CGI.parse(request.conn.query.to_s).merge(hash_quer)
|
|
49
|
+
end
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
def post_parameters
|
|
52
|
+
headers = request.req[:head] || {}
|
|
53
|
+
form_encoded = headers["Content-Type"].to_s.downcase.start_with?("application/x-www-form-urlencoded")
|
|
54
|
+
if %w[POST PUT].include?(method) && form_encoded
|
|
55
|
+
CGI.parse(request.normalize_body(request.req[:body]).to_s)
|
|
56
|
+
else
|
|
57
|
+
{}
|
|
58
|
+
end
|
|
58
59
|
end
|
|
59
|
-
end
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
def merged_parameters(params, *extra_params)
|
|
62
|
+
extra_params.compact.each do |params_pairs|
|
|
63
|
+
params_pairs.each_pair do |key, value|
|
|
64
|
+
if params.key?(key)
|
|
65
|
+
params[key.to_s] += value
|
|
66
|
+
else
|
|
67
|
+
params[key.to_s] = [value].flatten
|
|
68
|
+
end
|
|
68
69
|
end
|
|
69
70
|
end
|
|
71
|
+
params
|
|
70
72
|
end
|
|
71
|
-
params
|
|
72
73
|
end
|
|
73
74
|
end
|
|
74
75
|
end
|
|
@@ -18,8 +18,15 @@ module OAuth
|
|
|
18
18
|
oauth = @request.get_elements("//oauth").first
|
|
19
19
|
return @params unless oauth
|
|
20
20
|
|
|
21
|
-
%w[
|
|
22
|
-
|
|
21
|
+
%w[
|
|
22
|
+
oauth_token
|
|
23
|
+
oauth_consumer_key
|
|
24
|
+
oauth_signature_method
|
|
25
|
+
oauth_signature
|
|
26
|
+
oauth_timestamp
|
|
27
|
+
oauth_nonce
|
|
28
|
+
oauth_version
|
|
29
|
+
].each do |param|
|
|
23
30
|
next unless (element = oauth.first_element(param))
|
|
24
31
|
|
|
25
32
|
@params[param] = element.text
|
|
@@ -38,13 +38,11 @@ module OAuth
|
|
|
38
38
|
request_params = CGI.parse(query_string)
|
|
39
39
|
# request_params.each{|k,v| request_params[k] = [nil] if v == []}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
request_params[k] = [v]
|
|
47
|
-
end
|
|
41
|
+
options[:parameters]&.each do |k, v|
|
|
42
|
+
if request_params.key?(k) && v
|
|
43
|
+
request_params[k] << v
|
|
44
|
+
else
|
|
45
|
+
request_params[k] = [v]
|
|
48
46
|
end
|
|
49
47
|
end
|
|
50
48
|
request_params
|
|
@@ -71,7 +69,7 @@ module OAuth
|
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
def auth_header_params
|
|
74
|
-
return
|
|
72
|
+
return unless request["Authorization"] && request["Authorization"][0, 5] == "OAuth"
|
|
75
73
|
|
|
76
74
|
request["Authorization"]
|
|
77
75
|
end
|
|
@@ -34,11 +34,13 @@ module OAuth
|
|
|
34
34
|
query ? CGI.parse(query) : {}
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def request_params
|
|
37
|
+
def request_params
|
|
38
|
+
end
|
|
38
39
|
|
|
39
40
|
def post_parameters
|
|
40
41
|
# Post params are only used if posting form data
|
|
41
|
-
|
|
42
|
+
is_form_data = request.payload && request.payload.headers["Content-Type"] == "application/x-www-form-urlencoded"
|
|
43
|
+
if is_form_data && (method == "POST" || method == "PUT")
|
|
42
44
|
OAuth::Helper.stringify_keys(query_string_to_hash(request.payload.to_s) || {})
|
|
43
45
|
else
|
|
44
46
|
{}
|
|
@@ -51,9 +53,9 @@ module OAuth
|
|
|
51
53
|
query.split("&").inject({}) do |result, q|
|
|
52
54
|
k, v = q.split("=")
|
|
53
55
|
if !v.nil?
|
|
54
|
-
result.merge(k => v)
|
|
56
|
+
result.merge({k => v})
|
|
55
57
|
elsif !result.key?(k)
|
|
56
|
-
result.merge(k => true)
|
|
58
|
+
result.merge({k => true})
|
|
57
59
|
else
|
|
58
60
|
result
|
|
59
61
|
end
|