oauth 1.1.0 → 1.1.1
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 +4 -0
- data/CHANGELOG.md +317 -41
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +79 -29
- data/CONTRIBUTING.md +213 -24
- data/FUNDING.md +77 -0
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +543 -275
- data/REEK +0 -0
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +27 -11
- data/lib/oauth/client/action_controller_request.rb +14 -9
- data/lib/oauth/client/em_http.rb +106 -99
- data/lib/oauth/client/helper.rb +15 -11
- data/lib/oauth/client/net_http.rb +39 -13
- data/lib/oauth/consumer.rb +105 -54
- data/lib/oauth/errors/problem.rb +1 -1
- data/lib/oauth/helper.rb +25 -3
- data/lib/oauth/oauth.rb +28 -6
- data/lib/oauth/optional.rb +20 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +11 -7
- data/lib/oauth/request_proxy/action_dispatch_request.rb +41 -0
- data/lib/oauth/request_proxy/base.rb +15 -12
- 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/net_http.rb +1 -1
- data/lib/oauth/request_proxy/rest_client_request.rb +4 -3
- data/lib/oauth/server.rb +12 -8
- data/lib/oauth/signature/base.rb +1 -1
- data/lib/oauth/signature/rsa/sha1.rb +11 -4
- data/lib/oauth/tokens/access_token.rb +1 -1
- data/lib/oauth/tokens/consumer_token.rb +2 -2
- data/lib/oauth/tokens/request_token.rb +9 -4
- data/lib/oauth/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +246 -81
- metadata.gz.sig +3 -0
- data/TODO +0 -32
data/lib/oauth/consumer.rb
CHANGED
@@ -19,8 +19,11 @@ module OAuth
|
|
19
19
|
end
|
20
20
|
|
21
21
|
unless defined?(CA_FILE)
|
22
|
-
CA_FILES = %w[
|
23
|
-
|
22
|
+
CA_FILES = %w[
|
23
|
+
/etc/ssl/certs/ca-certificates.crt
|
24
|
+
/etc/pki/tls/certs/ca-bundle.crt
|
25
|
+
/usr/share/curl/curl-ca-bundle.crt
|
26
|
+
].freeze
|
24
27
|
CA_FILES.each do |ca_file|
|
25
28
|
if File.exist?(ca_file)
|
26
29
|
CA_FILE = ca_file
|
@@ -70,12 +73,12 @@ module OAuth
|
|
70
73
|
# spec. Possible values are true and false
|
71
74
|
body_hash_enabled: true,
|
72
75
|
|
73
|
-
oauth_version: "1.0"
|
74
|
-
}
|
76
|
+
oauth_version: "1.0",
|
77
|
+
},
|
75
78
|
)
|
76
79
|
|
77
80
|
attr_accessor :options, :key, :secret
|
78
|
-
attr_writer
|
81
|
+
attr_writer :site, :http
|
79
82
|
|
80
83
|
# Create a new consumer instance by passing it a configuration hash:
|
81
84
|
#
|
@@ -101,7 +104,7 @@ module OAuth
|
|
101
104
|
# @photos=@access_token.get('/photos.xml')
|
102
105
|
#
|
103
106
|
def initialize(consumer_key, consumer_secret, options = {})
|
104
|
-
@key
|
107
|
+
@key = consumer_key
|
105
108
|
@secret = consumer_secret
|
106
109
|
|
107
110
|
# ensure that keys are symbols
|
@@ -116,12 +119,12 @@ module OAuth
|
|
116
119
|
|
117
120
|
def debug_output
|
118
121
|
@debug_output ||= case @options[:debug_output]
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
122
|
+
when nil, false
|
123
|
+
when true
|
124
|
+
$stdout
|
125
|
+
else
|
126
|
+
@options[:debug_output]
|
127
|
+
end
|
125
128
|
end
|
126
129
|
|
127
130
|
# The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
|
@@ -132,51 +135,93 @@ module OAuth
|
|
132
135
|
# Contains the root URI for this site
|
133
136
|
def uri(custom_uri = nil)
|
134
137
|
if custom_uri
|
135
|
-
@uri
|
138
|
+
@uri = custom_uri
|
136
139
|
@http = create_http # yike, oh well. less intrusive this way
|
137
140
|
else # if no custom passed, we use existing, which, if unset, is set to site uri
|
138
141
|
@uri ||= URI.parse(site)
|
139
142
|
end
|
140
143
|
end
|
141
144
|
|
145
|
+
# Exchanges a verified Request Token for an Access Token.
|
146
|
+
#
|
147
|
+
# OAuth 1.0 vs 1.0a:
|
148
|
+
# - 1.0a requires including oauth_verifier (as returned by the Provider after
|
149
|
+
# user authorization) when performing this exchange in a 3‑legged flow.
|
150
|
+
# - 1.0 flows did not include oauth_verifier.
|
151
|
+
#
|
152
|
+
# Usage (3‑legged):
|
153
|
+
# access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
|
154
|
+
#
|
155
|
+
# @param request_token [OAuth::RequestToken] The authorized request token
|
156
|
+
# @param request_options [Hash] OAuth or request options (include :oauth_verifier for 1.0a)
|
157
|
+
# @param arguments [Array] Optional POST body and headers
|
158
|
+
# @yield [response_body] If a block is given, yields the raw response body.
|
159
|
+
# @return [OAuth::AccessToken]
|
142
160
|
def get_access_token(request_token, request_options = {}, *arguments, &block)
|
143
|
-
response = token_request(
|
144
|
-
|
161
|
+
response = token_request(
|
162
|
+
http_method,
|
163
|
+
(access_token_url? ? access_token_url : access_token_path),
|
164
|
+
request_token,
|
165
|
+
request_options,
|
166
|
+
*arguments,
|
167
|
+
&block
|
168
|
+
)
|
145
169
|
OAuth::AccessToken.from_hash(self, response)
|
146
170
|
end
|
147
171
|
|
148
172
|
# Makes a request to the service for a new OAuth::RequestToken
|
149
173
|
#
|
150
|
-
#
|
174
|
+
# Example:
|
175
|
+
# @request_token = @consumer.get_request_token
|
151
176
|
#
|
152
177
|
# To include OAuth parameters:
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
178
|
+
# @request_token = @consumer.get_request_token(
|
179
|
+
# oauth_callback: "http://example.com/cb"
|
180
|
+
# )
|
156
181
|
#
|
157
182
|
# To include application-specific parameters:
|
183
|
+
# @request_token = @consumer.get_request_token({}, foo: "bar")
|
158
184
|
#
|
159
|
-
#
|
185
|
+
# OAuth 1.0 vs 1.0a:
|
186
|
+
# - In 1.0a, the Consumer SHOULD send oauth_callback when obtaining a request token
|
187
|
+
# (or explicitly use OUT_OF_BAND) and the Provider MUST include
|
188
|
+
# oauth_callback_confirmed=true in the response.
|
189
|
+
# - This library defaults oauth_callback to OUT_OF_BAND ("oob") when not provided,
|
190
|
+
# which works for both 1.0 and 1.0a, and mirrors common provider behavior.
|
191
|
+
# - The oauth_callback_confirmed response is parsed by the token classes; it is not
|
192
|
+
# part of the signature base string and thus is not signed.
|
160
193
|
#
|
161
|
-
# TODO oauth_callback
|
194
|
+
# TODO: In a future major release, oauth_callback may be made mandatory unless
|
195
|
+
# request_options[:exclude_callback] is set, to reflect 1.0a guidance.
|
196
|
+
#
|
197
|
+
# @param request_options [Hash] OAuth options for the request. Notably
|
198
|
+
# :oauth_callback can be set to a URL, or OAuth::OUT_OF_BAND ("oob").
|
199
|
+
# @param arguments [Array] Optional POST body and headers
|
200
|
+
# @yield [response_body] If a block is given, yields the raw response body.
|
201
|
+
# @return [OAuth::RequestToken]
|
162
202
|
def get_request_token(request_options = {}, *arguments, &block)
|
163
203
|
# if oauth_callback wasn't provided, it is assumed that oauth_verifiers
|
164
204
|
# will be exchanged out of band
|
165
205
|
request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
|
166
206
|
|
167
207
|
response = if block
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
208
|
+
token_request(
|
209
|
+
http_method,
|
210
|
+
(request_token_url? ? request_token_url : request_token_path),
|
211
|
+
nil,
|
212
|
+
request_options,
|
213
|
+
*arguments,
|
214
|
+
&block
|
215
|
+
)
|
216
|
+
else
|
217
|
+
token_request(
|
218
|
+
http_method,
|
219
|
+
(request_token_url? ? request_token_url : request_token_path),
|
220
|
+
nil,
|
221
|
+
request_options,
|
222
|
+
*arguments,
|
223
|
+
)
|
224
|
+
end
|
180
225
|
OAuth::RequestToken.from_hash(self, response)
|
181
226
|
end
|
182
227
|
|
@@ -191,23 +236,23 @@ module OAuth
|
|
191
236
|
# @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
|
192
237
|
#
|
193
238
|
def request(http_method, path, token = nil, request_options = {}, *arguments)
|
194
|
-
unless %r{^/}
|
239
|
+
unless %r{^/} =~ path
|
195
240
|
@http = create_http(path)
|
196
241
|
_uri = URI.parse(path)
|
197
|
-
path = "#{_uri.path}#{
|
242
|
+
path = "#{_uri.path}#{"?#{_uri.query}" if _uri.query}"
|
198
243
|
end
|
199
244
|
|
200
245
|
# override the request with your own, this is useful for file uploads which Net::HTTP does not do
|
201
246
|
req = create_signed_request(http_method, path, token, request_options, *arguments)
|
202
|
-
return
|
247
|
+
return if block_given? && (yield(req) == :done)
|
203
248
|
|
204
249
|
rsp = http.request(req)
|
205
250
|
# check for an error reported by the Problem Reporting extension
|
206
251
|
# (https://wiki.oauth.net/ProblemReporting)
|
207
252
|
# note: a 200 may actually be an error; check for an oauth_problem key to be sure
|
208
253
|
if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
|
209
|
-
|
210
|
-
|
254
|
+
(h = headers.grep(/^OAuth /)).any? &&
|
255
|
+
h.first.include?("oauth_problem")
|
211
256
|
|
212
257
|
# puts "Header: #{h.first}"
|
213
258
|
|
@@ -247,7 +292,7 @@ module OAuth
|
|
247
292
|
# TODO this also drops subsequent values from multi-valued keys
|
248
293
|
CGI.parse(response.body).each_with_object({}) do |(k, v), h|
|
249
294
|
h[k.strip.to_sym] = v.first
|
250
|
-
h[k.strip]
|
295
|
+
h[k.strip] = v.first
|
251
296
|
end
|
252
297
|
end
|
253
298
|
when (300..399)
|
@@ -286,7 +331,7 @@ module OAuth
|
|
286
331
|
end
|
287
332
|
|
288
333
|
def request_endpoint
|
289
|
-
return
|
334
|
+
return if @options[:request_endpoint].nil?
|
290
335
|
|
291
336
|
@options[:request_endpoint].to_s
|
292
337
|
end
|
@@ -355,24 +400,30 @@ module OAuth
|
|
355
400
|
_url = request_endpoint unless request_endpoint.nil?
|
356
401
|
|
357
402
|
our_uri = if _url.nil? || _url[0] =~ %r{^/}
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
403
|
+
URI.parse(site)
|
404
|
+
else
|
405
|
+
your_uri = URI.parse(_url)
|
406
|
+
if your_uri.host.nil?
|
407
|
+
# If the _url is a path, missing the leading slash, then it won't have a host,
|
408
|
+
# and our_uri *must* have a host, so we parse site instead.
|
409
|
+
URI.parse(site)
|
410
|
+
else
|
411
|
+
your_uri
|
412
|
+
end
|
413
|
+
end
|
369
414
|
|
370
415
|
if proxy.nil?
|
371
416
|
http_object = Net::HTTP.new(our_uri.host, our_uri.port)
|
372
417
|
else
|
373
418
|
proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
|
374
|
-
http_object = Net::HTTP.new(
|
375
|
-
|
419
|
+
http_object = Net::HTTP.new(
|
420
|
+
our_uri.host,
|
421
|
+
our_uri.port,
|
422
|
+
proxy_uri.host,
|
423
|
+
proxy_uri.port,
|
424
|
+
proxy_uri.user,
|
425
|
+
proxy_uri.password,
|
426
|
+
)
|
376
427
|
end
|
377
428
|
|
378
429
|
http_object.use_ssl = (our_uri.scheme == "https")
|
@@ -453,7 +504,7 @@ module OAuth
|
|
453
504
|
end
|
454
505
|
|
455
506
|
def marshal_dump(*_args)
|
456
|
-
{
|
507
|
+
{key: @key, secret: @secret, options: @options}
|
457
508
|
end
|
458
509
|
|
459
510
|
def marshal_load(data)
|
data/lib/oauth/errors/problem.rb
CHANGED
data/lib/oauth/helper.rb
CHANGED
@@ -18,11 +18,33 @@ module OAuth
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def _escape(string)
|
21
|
-
|
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
|
22
32
|
end
|
23
33
|
|
24
34
|
def unescape(value)
|
25
|
-
|
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
|
26
48
|
end
|
27
49
|
|
28
50
|
# Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
|
@@ -31,7 +53,7 @@ module OAuth
|
|
31
53
|
Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, "")
|
32
54
|
end
|
33
55
|
|
34
|
-
|
56
|
+
alias_method :generate_nonce, :generate_key
|
35
57
|
|
36
58
|
def generate_timestamp # :nodoc:
|
37
59
|
Time.now.to_i.to_s
|
data/lib/oauth/oauth.rb
CHANGED
@@ -1,14 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module OAuth
|
4
|
-
#
|
5
|
-
#
|
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.
|
6
9
|
OUT_OF_BAND = "oob"
|
7
10
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
12
34
|
|
13
35
|
# reserved character regexp, per section 5.1
|
14
36
|
RESERVED_CHARACTERS = /[^a-zA-Z0-9\-._~]/.freeze
|
@@ -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
|
@@ -16,14 +16,18 @@ module OAuth
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def uri
|
19
|
-
request.url
|
19
|
+
options[:uri] || request.url
|
20
20
|
end
|
21
21
|
|
22
22
|
def parameters
|
23
23
|
if options[:clobber_request]
|
24
24
|
options[:parameters] || {}
|
25
25
|
else
|
26
|
-
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)
|
27
31
|
params.stringify_keys! if params.respond_to?(:stringify_keys!)
|
28
32
|
params.merge(options[:parameters] || {})
|
29
33
|
end
|
@@ -43,11 +47,11 @@ module OAuth
|
|
43
47
|
params << request.raw_post if raw_post_signature?
|
44
48
|
end
|
45
49
|
|
46
|
-
params
|
47
|
-
join("&").split("&")
|
48
|
-
reject { |s| s.match(/\A\s*\z/) }
|
49
|
-
map { |p| p.split("=").map { |esc| CGI.unescape(esc) } }
|
50
|
-
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" }
|
51
55
|
end
|
52
56
|
|
53
57
|
def raw_post_signature?
|
@@ -6,6 +6,47 @@ 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
|
43
|
+
|
44
|
+
def wrap_values(hash)
|
45
|
+
return {} unless hash
|
46
|
+
hash.each_with_object({}) do |(k, v), acc|
|
47
|
+
acc[k] = (v.is_a?(Array) || v.nil?) ? v : [v]
|
48
|
+
end
|
49
|
+
end
|
9
50
|
end
|
10
51
|
end
|
11
52
|
end
|
@@ -56,6 +56,9 @@ module OAuth
|
|
56
56
|
parameters["oauth_token"]
|
57
57
|
end
|
58
58
|
|
59
|
+
# OAuth 1.0a only: value returned to the Consumer after user authorization
|
60
|
+
# and required when exchanging a Request Token for an Access Token.
|
61
|
+
# Not present in OAuth 1.0 flows.
|
59
62
|
def oauth_verifier
|
60
63
|
parameters["oauth_verifier"]
|
61
64
|
end
|
@@ -65,12 +68,12 @@ module OAuth
|
|
65
68
|
end
|
66
69
|
|
67
70
|
# TODO: deprecate these
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
alias_method :consumer_key, :oauth_consumer_key
|
72
|
+
alias_method :token, :oauth_token
|
73
|
+
alias_method :nonce, :oauth_nonce
|
74
|
+
alias_method :timestamp, :oauth_timestamp
|
75
|
+
alias_method :signature, :oauth_signature
|
76
|
+
alias_method :signature_method, :oauth_signature_method
|
74
77
|
|
75
78
|
## Parameter accessors
|
76
79
|
|
@@ -97,7 +100,7 @@ module OAuth
|
|
97
100
|
# See 9.1.2 in specs
|
98
101
|
def normalized_uri
|
99
102
|
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)
|
103
|
+
"#{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
104
|
end
|
102
105
|
|
103
106
|
# See 9.1.1. in specs Normalize Request Parameters
|
@@ -130,14 +133,14 @@ module OAuth
|
|
130
133
|
def signed_uri(with_oauth: true)
|
131
134
|
if signed?
|
132
135
|
params = if with_oauth
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
136
|
+
parameters
|
137
|
+
else
|
138
|
+
non_oauth_parameters
|
139
|
+
end
|
137
140
|
|
138
141
|
[uri, normalize(params)].join("?")
|
139
142
|
else
|
140
|
-
warn
|
143
|
+
warn("This request has not yet been signed!")
|
141
144
|
end
|
142
145
|
end
|
143
146
|
|
@@ -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
|