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/consumer.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "net/http"
|
|
2
4
|
require "net/https"
|
|
3
5
|
require "oauth/oauth"
|
|
@@ -6,7 +8,22 @@ require "oauth/errors"
|
|
|
6
8
|
require "cgi"
|
|
7
9
|
|
|
8
10
|
module OAuth
|
|
11
|
+
# Consumer credentials and request configuration for OAuth 1.0 / 1.0a flows.
|
|
12
|
+
#
|
|
13
|
+
# Includes {OAuth::AUTH_SANITIZER::FilteredAttributes} so inspect output redacts the
|
|
14
|
+
# consumer secret while leaving non-sensitive configuration visible.
|
|
9
15
|
class Consumer
|
|
16
|
+
include OAuth::AUTH_SANITIZER::FilteredAttributes
|
|
17
|
+
|
|
18
|
+
# Instance attributes exposed by the consumer.
|
|
19
|
+
#
|
|
20
|
+
# @!attribute [rw] options
|
|
21
|
+
# @return [Hash] Consumer configuration options
|
|
22
|
+
# @!attribute [rw] key
|
|
23
|
+
# @return [String] OAuth consumer key
|
|
24
|
+
# @!attribute [rw] secret
|
|
25
|
+
# @return [String] OAuth consumer secret (redacted in `#inspect`)
|
|
26
|
+
|
|
10
27
|
# determine the certificate authority path to verify SSL certs
|
|
11
28
|
if ENV["SSL_CERT_FILE"]
|
|
12
29
|
if File.exist?(ENV["SSL_CERT_FILE"])
|
|
@@ -17,7 +34,11 @@ module OAuth
|
|
|
17
34
|
end
|
|
18
35
|
|
|
19
36
|
unless defined?(CA_FILE)
|
|
20
|
-
CA_FILES = %w[
|
|
37
|
+
CA_FILES = %w[
|
|
38
|
+
/etc/ssl/certs/ca-certificates.crt
|
|
39
|
+
/etc/pki/tls/certs/ca-bundle.crt
|
|
40
|
+
/usr/share/curl/curl-ca-bundle.crt
|
|
41
|
+
].freeze
|
|
21
42
|
CA_FILES.each do |ca_file|
|
|
22
43
|
if File.exist?(ca_file)
|
|
23
44
|
CA_FILE = ca_file
|
|
@@ -27,45 +48,59 @@ module OAuth
|
|
|
27
48
|
end
|
|
28
49
|
CA_FILE = nil unless defined?(CA_FILE)
|
|
29
50
|
|
|
30
|
-
@@default_options =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
@@default_options = SnakyHash::SymbolKeyed.new(
|
|
52
|
+
{
|
|
53
|
+
# Signature method used by server. Defaults to HMAC-SHA1
|
|
54
|
+
signature_method: "HMAC-SHA1",
|
|
55
|
+
|
|
56
|
+
# default paths on site. These are the same as the defaults set up by the generators
|
|
57
|
+
request_token_path: "/oauth/request_token",
|
|
58
|
+
authenticate_path: "/oauth/authenticate",
|
|
59
|
+
authorize_path: "/oauth/authorize",
|
|
60
|
+
access_token_path: "/oauth/access_token",
|
|
61
|
+
|
|
62
|
+
proxy: nil,
|
|
63
|
+
# How do we send the oauth values to the server see
|
|
64
|
+
# https://oauth.net/core/1.0/#consumer_req_param for more info
|
|
65
|
+
#
|
|
66
|
+
# Possible values:
|
|
67
|
+
#
|
|
68
|
+
# :header - via the Authorize header (Default) ( option 1. in spec)
|
|
69
|
+
# :body - url form encoded in body of POST request ( option 2. in spec)
|
|
70
|
+
# :query_string - via the query part of the url ( option 3. in spec)
|
|
71
|
+
scheme: :header,
|
|
72
|
+
|
|
73
|
+
# Default http method used for OAuth Token Requests (defaults to :post)
|
|
74
|
+
http_method: :post,
|
|
75
|
+
|
|
76
|
+
# Add a custom ca_file for consumer
|
|
77
|
+
# :ca_file => '/etc/certs.pem'
|
|
78
|
+
|
|
79
|
+
# Possible values:
|
|
80
|
+
#
|
|
81
|
+
# nil, false - no debug output
|
|
82
|
+
# true - uses $stdout
|
|
83
|
+
# some_value - uses some_value
|
|
84
|
+
debug_output: nil,
|
|
85
|
+
|
|
86
|
+
# Defaults to producing a body_hash as part of the signature but
|
|
87
|
+
# can be disabled since it's not officially part of the OAuth 1.0
|
|
88
|
+
# spec. Possible values are true and false
|
|
89
|
+
body_hash_enabled: true,
|
|
90
|
+
|
|
91
|
+
oauth_version: "1.0",
|
|
92
|
+
|
|
93
|
+
# Token endpoint redirects are followed only within the same origin by
|
|
94
|
+
# default. Cross-origin redirects can re-sign token requests for an
|
|
95
|
+
# attacker-controlled endpoint, so they require explicit opt-in.
|
|
96
|
+
token_request_max_redirects: 10,
|
|
97
|
+
token_request_cross_origin_redirects: false,
|
|
98
|
+
},
|
|
99
|
+
)
|
|
66
100
|
|
|
67
101
|
attr_accessor :options, :key, :secret
|
|
68
|
-
|
|
102
|
+
filtered_attributes :secret
|
|
103
|
+
attr_writer :site, :http
|
|
69
104
|
|
|
70
105
|
# Create a new consumer instance by passing it a configuration hash:
|
|
71
106
|
#
|
|
@@ -75,7 +110,8 @@ module OAuth
|
|
|
75
110
|
# :http_method => :post,
|
|
76
111
|
# :request_token_path => "/oauth/example/request_token.php",
|
|
77
112
|
# :access_token_path => "/oauth/example/access_token.php",
|
|
78
|
-
# :authorize_path => "/oauth/example/authorize.php"
|
|
113
|
+
# :authorize_path => "/oauth/example/authorize.php",
|
|
114
|
+
# :body_hash_enabled => false
|
|
79
115
|
# })
|
|
80
116
|
#
|
|
81
117
|
# Start the process by requesting a token
|
|
@@ -90,13 +126,12 @@ module OAuth
|
|
|
90
126
|
# @photos=@access_token.get('/photos.xml')
|
|
91
127
|
#
|
|
92
128
|
def initialize(consumer_key, consumer_secret, options = {})
|
|
93
|
-
@key
|
|
129
|
+
@key = consumer_key
|
|
94
130
|
@secret = consumer_secret
|
|
95
131
|
|
|
96
132
|
# ensure that keys are symbols
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
end)
|
|
133
|
+
snaky_options = SnakyHash::SymbolKeyed.new(options)
|
|
134
|
+
@options = @@default_options.merge(snaky_options)
|
|
100
135
|
end
|
|
101
136
|
|
|
102
137
|
# The default http method
|
|
@@ -105,14 +140,12 @@ module OAuth
|
|
|
105
140
|
end
|
|
106
141
|
|
|
107
142
|
def debug_output
|
|
108
|
-
@debug_output ||=
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
@options[:debug_output]
|
|
115
|
-
end
|
|
143
|
+
@debug_output ||= case @options[:debug_output]
|
|
144
|
+
when nil, false
|
|
145
|
+
when true
|
|
146
|
+
$stdout
|
|
147
|
+
else
|
|
148
|
+
@options[:debug_output]
|
|
116
149
|
end
|
|
117
150
|
end
|
|
118
151
|
|
|
@@ -124,49 +157,93 @@ module OAuth
|
|
|
124
157
|
# Contains the root URI for this site
|
|
125
158
|
def uri(custom_uri = nil)
|
|
126
159
|
if custom_uri
|
|
127
|
-
@uri
|
|
160
|
+
@uri = custom_uri
|
|
128
161
|
@http = create_http # yike, oh well. less intrusive this way
|
|
129
162
|
else # if no custom passed, we use existing, which, if unset, is set to site uri
|
|
130
163
|
@uri ||= URI.parse(site)
|
|
131
164
|
end
|
|
132
165
|
end
|
|
133
166
|
|
|
167
|
+
# Exchanges a verified Request Token for an Access Token.
|
|
168
|
+
#
|
|
169
|
+
# OAuth 1.0 vs 1.0a:
|
|
170
|
+
# - 1.0a requires including oauth_verifier (as returned by the Provider after
|
|
171
|
+
# user authorization) when performing this exchange in a 3‑legged flow.
|
|
172
|
+
# - 1.0 flows did not include oauth_verifier.
|
|
173
|
+
#
|
|
174
|
+
# Usage (3‑legged):
|
|
175
|
+
# access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
|
|
176
|
+
#
|
|
177
|
+
# @param request_token [OAuth::RequestToken] The authorized request token
|
|
178
|
+
# @param request_options [Hash] OAuth or request options (include :oauth_verifier for 1.0a)
|
|
179
|
+
# @param arguments [Array] Optional POST body and headers
|
|
180
|
+
# @yield [response_body] If a block is given, yields the raw response body.
|
|
181
|
+
# @return [OAuth::AccessToken]
|
|
134
182
|
def get_access_token(request_token, request_options = {}, *arguments, &block)
|
|
135
|
-
response = token_request(
|
|
183
|
+
response = token_request(
|
|
184
|
+
http_method,
|
|
185
|
+
(access_token_url? ? access_token_url : access_token_path),
|
|
186
|
+
request_token,
|
|
187
|
+
request_options,
|
|
188
|
+
*arguments,
|
|
189
|
+
&block
|
|
190
|
+
)
|
|
136
191
|
OAuth::AccessToken.from_hash(self, response)
|
|
137
192
|
end
|
|
138
193
|
|
|
139
194
|
# Makes a request to the service for a new OAuth::RequestToken
|
|
140
195
|
#
|
|
141
|
-
#
|
|
196
|
+
# Example:
|
|
197
|
+
# @request_token = @consumer.get_request_token
|
|
142
198
|
#
|
|
143
199
|
# To include OAuth parameters:
|
|
144
|
-
#
|
|
145
|
-
#
|
|
146
|
-
#
|
|
200
|
+
# @request_token = @consumer.get_request_token(
|
|
201
|
+
# oauth_callback: "http://example.com/cb"
|
|
202
|
+
# )
|
|
147
203
|
#
|
|
148
204
|
# To include application-specific parameters:
|
|
205
|
+
# @request_token = @consumer.get_request_token({}, foo: "bar")
|
|
149
206
|
#
|
|
150
|
-
#
|
|
207
|
+
# OAuth 1.0 vs 1.0a:
|
|
208
|
+
# - In 1.0a, the Consumer SHOULD send oauth_callback when obtaining a request token
|
|
209
|
+
# (or explicitly use OUT_OF_BAND) and the Provider MUST include
|
|
210
|
+
# oauth_callback_confirmed=true in the response.
|
|
211
|
+
# - This library defaults oauth_callback to OUT_OF_BAND ("oob") when not provided,
|
|
212
|
+
# which works for both 1.0 and 1.0a, and mirrors common provider behavior.
|
|
213
|
+
# - The oauth_callback_confirmed response is parsed by the token classes; it is not
|
|
214
|
+
# part of the signature base string and thus is not signed.
|
|
151
215
|
#
|
|
152
|
-
# TODO oauth_callback
|
|
216
|
+
# TODO: In a future major release, oauth_callback may be made mandatory unless
|
|
217
|
+
# request_options[:exclude_callback] is set, to reflect 1.0a guidance.
|
|
218
|
+
#
|
|
219
|
+
# @param request_options [Hash] OAuth options for the request. Notably
|
|
220
|
+
# :oauth_callback can be set to a URL, or OAuth::OUT_OF_BAND ("oob").
|
|
221
|
+
# @param arguments [Array] Optional POST body and headers
|
|
222
|
+
# @yield [response_body] If a block is given, yields the raw response body.
|
|
223
|
+
# @return [OAuth::RequestToken]
|
|
153
224
|
def get_request_token(request_options = {}, *arguments, &block)
|
|
154
225
|
# if oauth_callback wasn't provided, it is assumed that oauth_verifiers
|
|
155
226
|
# will be exchanged out of band
|
|
156
227
|
request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
|
|
157
228
|
|
|
158
|
-
response = if
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
229
|
+
response = if block
|
|
230
|
+
token_request(
|
|
231
|
+
http_method,
|
|
232
|
+
(request_token_url? ? request_token_url : request_token_path),
|
|
233
|
+
nil,
|
|
234
|
+
request_options,
|
|
235
|
+
*arguments,
|
|
236
|
+
&block
|
|
237
|
+
)
|
|
238
|
+
else
|
|
239
|
+
token_request(
|
|
240
|
+
http_method,
|
|
241
|
+
(request_token_url? ? request_token_url : request_token_path),
|
|
242
|
+
nil,
|
|
243
|
+
request_options,
|
|
244
|
+
*arguments,
|
|
245
|
+
)
|
|
246
|
+
end
|
|
170
247
|
OAuth::RequestToken.from_hash(self, response)
|
|
171
248
|
end
|
|
172
249
|
|
|
@@ -181,22 +258,23 @@ module OAuth
|
|
|
181
258
|
# @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
|
|
182
259
|
#
|
|
183
260
|
def request(http_method, path, token = nil, request_options = {}, *arguments)
|
|
184
|
-
|
|
261
|
+
unless %r{^/} =~ path
|
|
185
262
|
@http = create_http(path)
|
|
186
|
-
|
|
187
|
-
path = "#{
|
|
263
|
+
uri = URI.parse(path)
|
|
264
|
+
path = "#{uri.path}#{"?#{uri.query}" if uri.query}"
|
|
188
265
|
end
|
|
189
266
|
|
|
190
267
|
# override the request with your own, this is useful for file uploads which Net::HTTP does not do
|
|
191
268
|
req = create_signed_request(http_method, path, token, request_options, *arguments)
|
|
192
|
-
return
|
|
269
|
+
return if block_given? && (yield(req) == :done)
|
|
270
|
+
|
|
193
271
|
rsp = http.request(req)
|
|
194
272
|
# check for an error reported by the Problem Reporting extension
|
|
195
273
|
# (https://wiki.oauth.net/ProblemReporting)
|
|
196
274
|
# note: a 200 may actually be an error; check for an oauth_problem key to be sure
|
|
197
275
|
if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
|
|
198
|
-
|
|
199
|
-
|
|
276
|
+
(h = headers.grep(/^OAuth /)).any? &&
|
|
277
|
+
h.first.include?("oauth_problem")
|
|
200
278
|
|
|
201
279
|
# puts "Header: #{h.first}"
|
|
202
280
|
|
|
@@ -222,37 +300,34 @@ module OAuth
|
|
|
222
300
|
end
|
|
223
301
|
|
|
224
302
|
# Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
|
|
225
|
-
def token_request(http_method, path, token = nil, request_options = {}, *arguments)
|
|
226
|
-
request_options
|
|
227
|
-
response = request(http_method, path, token, request_options, *arguments)
|
|
303
|
+
def token_request(http_method, path, token = nil, request_options = {}, *arguments, &block)
|
|
304
|
+
response = request(http_method, path, token, token_request_options(request_options), *arguments)
|
|
228
305
|
case response.code.to_i
|
|
229
306
|
|
|
230
307
|
when (200..299)
|
|
231
|
-
if
|
|
232
|
-
|
|
308
|
+
if block
|
|
309
|
+
block.call(response.body)
|
|
233
310
|
else
|
|
234
311
|
# symbolize keys
|
|
235
312
|
# TODO this could be considered unexpected behavior; symbols or not?
|
|
236
313
|
# TODO this also drops subsequent values from multi-valued keys
|
|
237
314
|
CGI.parse(response.body).each_with_object({}) do |(k, v), h|
|
|
238
315
|
h[k.strip.to_sym] = v.first
|
|
239
|
-
h[k.strip]
|
|
316
|
+
h[k.strip] = v.first
|
|
240
317
|
end
|
|
241
318
|
end
|
|
242
319
|
when (300..399)
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
# Guard against infinite redirects
|
|
248
|
-
response.error! if uri.path == path && our_uri.host == uri.host
|
|
320
|
+
current_uri = token_request_uri(path)
|
|
321
|
+
redirected_uri = token_request_redirect_uri(current_uri, response)
|
|
322
|
+
response.error! unless redirected_uri
|
|
249
323
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
324
|
+
redirect_count = request_options[:token_request_redirect_count].to_i + 1
|
|
325
|
+
response.error! if redirect_count > token_request_max_redirects(request_options)
|
|
326
|
+
response.error! if token_request_cross_origin?(current_uri, redirected_uri) &&
|
|
327
|
+
!token_request_cross_origin_redirects?(request_options)
|
|
254
328
|
|
|
255
|
-
|
|
329
|
+
redirect_options = request_options.merge(token_request_redirect_count: redirect_count)
|
|
330
|
+
token_request(http_method, token_request_redirect_path(current_uri, redirected_uri), token, redirect_options, *arguments, &block)
|
|
256
331
|
when (400..499)
|
|
257
332
|
raise OAuth::Unauthorized, response
|
|
258
333
|
else
|
|
@@ -260,6 +335,55 @@ module OAuth
|
|
|
260
335
|
end
|
|
261
336
|
end
|
|
262
337
|
|
|
338
|
+
def token_request_options(request_options)
|
|
339
|
+
request_options.merge(token_request: true).tap do |options|
|
|
340
|
+
options.delete(:token_request_redirect_count)
|
|
341
|
+
options.delete(:token_request_max_redirects)
|
|
342
|
+
options.delete(:token_request_cross_origin_redirects)
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def token_request_uri(path)
|
|
347
|
+
uri = URI.parse(path)
|
|
348
|
+
return uri if uri.absolute?
|
|
349
|
+
|
|
350
|
+
URI.parse(site).merge(path)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def token_request_redirect_uri(current_uri, response)
|
|
354
|
+
location = response["location"]
|
|
355
|
+
return if location.nil? || location.to_s.empty?
|
|
356
|
+
|
|
357
|
+
current_uri.merge(location)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def token_request_redirect_path(current_uri, redirected_uri)
|
|
361
|
+
return redirected_uri.to_s if token_request_cross_origin?(current_uri, redirected_uri)
|
|
362
|
+
|
|
363
|
+
redirected_uri.request_uri
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def token_request_max_redirects(request_options)
|
|
367
|
+
request_options[:token_request_max_redirects] || options[:token_request_max_redirects]
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def token_request_cross_origin_redirects?(request_options)
|
|
371
|
+
request_options.fetch(:token_request_cross_origin_redirects, options[:token_request_cross_origin_redirects])
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def token_request_cross_origin?(current_uri, redirected_uri)
|
|
375
|
+
current_uri.scheme.to_s.downcase != redirected_uri.scheme.to_s.downcase ||
|
|
376
|
+
current_uri.host.to_s.downcase != redirected_uri.host.to_s.downcase ||
|
|
377
|
+
token_request_effective_port(current_uri) != token_request_effective_port(redirected_uri)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def token_request_effective_port(uri)
|
|
381
|
+
return uri.port if uri.port
|
|
382
|
+
return 443 if uri.scheme == "https"
|
|
383
|
+
|
|
384
|
+
80 if uri.scheme == "http"
|
|
385
|
+
end
|
|
386
|
+
|
|
263
387
|
# Sign the Request object. Use this if you have an externally generated http request object you want to sign.
|
|
264
388
|
def sign!(request, token = nil, request_options = {})
|
|
265
389
|
request.oauth!(http, self, token, options.merge(request_options))
|
|
@@ -275,7 +399,8 @@ module OAuth
|
|
|
275
399
|
end
|
|
276
400
|
|
|
277
401
|
def request_endpoint
|
|
278
|
-
return
|
|
402
|
+
return if @options[:request_endpoint].nil?
|
|
403
|
+
|
|
279
404
|
@options[:request_endpoint].to_s
|
|
280
405
|
end
|
|
281
406
|
|
|
@@ -301,7 +426,7 @@ module OAuth
|
|
|
301
426
|
|
|
302
427
|
# TODO: this is ugly, rewrite
|
|
303
428
|
def request_token_url
|
|
304
|
-
@options[:request_token_url] || site + request_token_path
|
|
429
|
+
@options[:request_token_url] || (site + request_token_path)
|
|
305
430
|
end
|
|
306
431
|
|
|
307
432
|
def request_token_url?
|
|
@@ -309,7 +434,7 @@ module OAuth
|
|
|
309
434
|
end
|
|
310
435
|
|
|
311
436
|
def authenticate_url
|
|
312
|
-
@options[:authenticate_url] || site + authenticate_path
|
|
437
|
+
@options[:authenticate_url] || (site + authenticate_path)
|
|
313
438
|
end
|
|
314
439
|
|
|
315
440
|
def authenticate_url?
|
|
@@ -317,7 +442,7 @@ module OAuth
|
|
|
317
442
|
end
|
|
318
443
|
|
|
319
444
|
def authorize_url
|
|
320
|
-
@options[:authorize_url] || site + authorize_path
|
|
445
|
+
@options[:authorize_url] || (site + authorize_path)
|
|
321
446
|
end
|
|
322
447
|
|
|
323
448
|
def authorize_url?
|
|
@@ -325,7 +450,7 @@ module OAuth
|
|
|
325
450
|
end
|
|
326
451
|
|
|
327
452
|
def access_token_url
|
|
328
|
-
@options[:access_token_url] || site + access_token_path
|
|
453
|
+
@options[:access_token_url] || (site + access_token_path)
|
|
329
454
|
end
|
|
330
455
|
|
|
331
456
|
def access_token_url?
|
|
@@ -339,27 +464,34 @@ module OAuth
|
|
|
339
464
|
protected
|
|
340
465
|
|
|
341
466
|
# Instantiates the http object
|
|
342
|
-
def create_http(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
our_uri = if
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
467
|
+
def create_http(url = nil)
|
|
468
|
+
url = request_endpoint unless request_endpoint.nil?
|
|
469
|
+
|
|
470
|
+
our_uri = if url.nil? || url[0] =~ %r{^/}
|
|
471
|
+
URI.parse(site)
|
|
472
|
+
else
|
|
473
|
+
your_uri = URI.parse(url)
|
|
474
|
+
if your_uri.host.nil?
|
|
475
|
+
# If the _url is a path, missing the leading slash, then it won't have a host,
|
|
476
|
+
# and our_uri *must* have a host, so we parse site instead.
|
|
477
|
+
URI.parse(site)
|
|
478
|
+
else
|
|
479
|
+
your_uri
|
|
480
|
+
end
|
|
481
|
+
end
|
|
357
482
|
|
|
358
483
|
if proxy.nil?
|
|
359
484
|
http_object = Net::HTTP.new(our_uri.host, our_uri.port)
|
|
360
485
|
else
|
|
361
486
|
proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
|
|
362
|
-
http_object = Net::HTTP.new(
|
|
487
|
+
http_object = Net::HTTP.new(
|
|
488
|
+
our_uri.host,
|
|
489
|
+
our_uri.port,
|
|
490
|
+
proxy_uri.host,
|
|
491
|
+
proxy_uri.port,
|
|
492
|
+
proxy_uri.user,
|
|
493
|
+
proxy_uri.password,
|
|
494
|
+
)
|
|
363
495
|
end
|
|
364
496
|
|
|
365
497
|
http_object.use_ssl = (our_uri.scheme == "https")
|
|
@@ -377,7 +509,7 @@ module OAuth
|
|
|
377
509
|
http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
|
|
378
510
|
http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
|
|
379
511
|
http_object.cert = @options[:ssl_client_cert] if @options[:ssl_client_cert]
|
|
380
|
-
http_object.key
|
|
512
|
+
http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
|
|
381
513
|
http_object.set_debug_output(debug_output) if debug_output
|
|
382
514
|
|
|
383
515
|
http_object
|
|
@@ -392,7 +524,7 @@ module OAuth
|
|
|
392
524
|
# if the base site contains a path, add it now
|
|
393
525
|
# only add if the site host matches the current http object's host
|
|
394
526
|
# (in case we've specified a full url for token requests)
|
|
395
|
-
uri
|
|
527
|
+
uri = URI.parse(site)
|
|
396
528
|
path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
|
|
397
529
|
|
|
398
530
|
headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
|
|
@@ -440,7 +572,7 @@ module OAuth
|
|
|
440
572
|
end
|
|
441
573
|
|
|
442
574
|
def marshal_dump(*_args)
|
|
443
|
-
{
|
|
575
|
+
{key: @key, secret: @secret, options: @options}
|
|
444
576
|
end
|
|
445
577
|
|
|
446
578
|
def marshal_load(data)
|
data/lib/oauth/errors/error.rb
CHANGED
data/lib/oauth/errors/problem.rb
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module OAuth
|
|
2
4
|
class Problem < OAuth::Unauthorized
|
|
3
5
|
attr_reader :problem, :params
|
|
6
|
+
|
|
4
7
|
def initialize(problem, request = nil, params = {})
|
|
5
8
|
super(request)
|
|
6
9
|
@problem = problem
|
|
7
|
-
@params
|
|
10
|
+
@params = params
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
def to_s
|