oauth 0.2.7 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oauth might be problematic. Click here for more details.
- data/History.txt +14 -0
- data/Manifest.txt +19 -3
- data/{README.txt → README.rdoc} +0 -0
- data/Rakefile +34 -4
- data/TODO +14 -0
- data/bin/oauth +5 -0
- data/lib/oauth.rb +3 -3
- data/lib/oauth/cli.rb +130 -0
- data/lib/oauth/client/helper.rb +3 -2
- data/lib/oauth/consumer.rb +1 -1
- data/lib/oauth/helper.rb +3 -0
- data/lib/oauth/oauth_test_helper.rb +26 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +2 -4
- data/lib/oauth/request_proxy/base.rb +31 -0
- data/lib/oauth/request_proxy/jabber_request.rb +42 -0
- data/lib/oauth/request_proxy/mock_request.rb +36 -0
- data/lib/oauth/request_proxy/net_http.rb +0 -2
- data/lib/oauth/request_proxy/rack_request.rb +1 -3
- data/lib/oauth/signature/base.rb +20 -7
- data/lib/oauth/signature/plaintext.rb +1 -1
- data/lib/oauth/token.rb +3 -3
- data/lib/oauth/version.rb +2 -8
- data/oauth.gemspec +43 -0
- data/script/txt2html +1 -1
- data/specs.txt +13 -0
- data/test/cases/oauth_case.rb +19 -0
- data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
- data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
- data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
- data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
- data/test/keys/rsa.cert +11 -0
- data/test/keys/rsa.pem +16 -0
- data/test/test_action_controller_request_proxy.rb +2 -1
- data/test/test_consumer.rb +17 -18
- data/test/test_helper.rb +8 -0
- data/test/test_net_http_client.rb +7 -7
- data/test/test_net_http_request_proxy.rb +3 -3
- data/test/test_rack_request_proxy.rb +3 -3
- data/test/test_signature_plain_text.rb +31 -0
- data/website/index.html +1 -1
- metadata +43 -11
- data/config/hoe.rb +0 -71
- data/config/requirements.rb +0 -17
data/History.txt
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
Fix in plain text signatures to bug found by Andrew Arrow. Who contributed new new unit tests for plain text sigs.
|
2
|
+
|
3
|
+
== 0.3.0
|
4
|
+
|
5
|
+
* Support ActionController::Request from Edge Rails (László Bácsi)
|
6
|
+
* Correctly handle multi-valued parameters (Seth)
|
7
|
+
* Added #normalized_parameters to OAuth::RequestProxy::Base (Pelle)
|
8
|
+
* OAuth::Signature.sign and friends now yield the RequestProxy instead of the
|
9
|
+
token when the passed block's arity is 1. (Seth)
|
10
|
+
* Token requests are made to the configured URL rather than generating a
|
11
|
+
potentially incorrect one. (Kellan Elliott-McCrea)
|
12
|
+
* Command-line app for generating signatures. (Seth)
|
13
|
+
* Improved test-cases and compatibility for encoding issues. (Pelle)
|
14
|
+
|
1
15
|
== 0.2.7 2008-9-10 The lets fix the last release release
|
2
16
|
|
3
17
|
There was an error in the RSA requests using oauth tokens. Thanks to Philip Lipu Tsai for noticing this.
|
data/Manifest.txt
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
History.txt
|
2
2
|
License.txt
|
3
3
|
Manifest.txt
|
4
|
-
README.
|
4
|
+
README.rdoc
|
5
5
|
Rakefile
|
6
|
-
|
7
|
-
|
6
|
+
TODO
|
7
|
+
bin/oauth
|
8
8
|
lib/oauth.rb
|
9
|
+
lib/oauth/cli.rb
|
9
10
|
lib/oauth/client.rb
|
10
11
|
lib/oauth/client/action_controller_request.rb
|
11
12
|
lib/oauth/client/helper.rb
|
12
13
|
lib/oauth/client/net_http.rb
|
13
14
|
lib/oauth/consumer.rb
|
14
15
|
lib/oauth/helper.rb
|
16
|
+
lib/oauth/oauth_test_helper.rb
|
15
17
|
lib/oauth/request_proxy.rb
|
16
18
|
lib/oauth/request_proxy/action_controller_request.rb
|
17
19
|
lib/oauth/request_proxy/base.rb
|
20
|
+
lib/oauth/request_proxy/jabber_request.rb
|
21
|
+
lib/oauth/request_proxy/mock_request.rb
|
18
22
|
lib/oauth/request_proxy/net_http.rb
|
19
23
|
lib/oauth/request_proxy/rack_request.rb
|
20
24
|
lib/oauth/server.rb
|
@@ -31,13 +35,22 @@ lib/oauth/signature/rsa/sha1.rb
|
|
31
35
|
lib/oauth/signature/sha1.rb
|
32
36
|
lib/oauth/token.rb
|
33
37
|
lib/oauth/version.rb
|
38
|
+
oauth.gemspec
|
34
39
|
script/destroy
|
35
40
|
script/generate
|
36
41
|
script/txt2html
|
37
42
|
setup.rb
|
43
|
+
specs.txt
|
38
44
|
tasks/deployment.rake
|
39
45
|
tasks/environment.rake
|
40
46
|
tasks/website.rake
|
47
|
+
test/cases/oauth_case.rb
|
48
|
+
test/cases/spec/1_0-final/test_construct_request_url.rb
|
49
|
+
test/cases/spec/1_0-final/test_normalize_request_parameters.rb
|
50
|
+
test/cases/spec/1_0-final/test_parameter_encodings.rb
|
51
|
+
test/cases/spec/1_0-final/test_signature_base_strings.rb
|
52
|
+
test/keys/rsa.cert
|
53
|
+
test/keys/rsa.pem
|
41
54
|
test/test_action_controller_request_proxy.rb
|
42
55
|
test/test_consumer.rb
|
43
56
|
test/test_helper.rb
|
@@ -45,8 +58,11 @@ test/test_hmac_sha1.rb
|
|
45
58
|
test/test_net_http_client.rb
|
46
59
|
test/test_net_http_request_proxy.rb
|
47
60
|
test/test_rack_request_proxy.rb
|
61
|
+
test/test_rsa_sha1.rb
|
62
|
+
test/test_server.rb
|
48
63
|
test/test_signature.rb
|
49
64
|
test/test_signature_base.rb
|
65
|
+
test/test_signature_plain_text.rb
|
50
66
|
test/test_token.rb
|
51
67
|
website/index.html
|
52
68
|
website/index.txt
|
data/{README.txt → README.rdoc}
RENAMED
File without changes
|
data/Rakefile
CHANGED
@@ -1,4 +1,34 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
2
|
+
$LOAD_PATH << File.dirname(__FILE__) + '/lib'
|
3
|
+
require 'oauth'
|
4
|
+
require 'oauth/version'
|
5
|
+
|
6
|
+
# Generate all the Rake tasks
|
7
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
8
|
+
$hoe = Hoe.new('oauth', OAuth::VERSION) do |p|
|
9
|
+
p.author = ['Pelle Braendgaard','Blaine Cook','Larry Halff','Jesse Clark','Jon Crosby', 'Seth Fitzsimmons']
|
10
|
+
p.email = "pelleb@gmail.com"
|
11
|
+
p.description = "OAuth Core Ruby implementation"
|
12
|
+
p.summary = p.description
|
13
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
14
|
+
p.rubyforge_name = p.name # TODO this is default value
|
15
|
+
p.url = "http://oauth.rubyforge.org"
|
16
|
+
|
17
|
+
p.extra_deps = [
|
18
|
+
['ruby-hmac','>= 0.3.1']
|
19
|
+
]
|
20
|
+
p.extra_dev_deps = [
|
21
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
22
|
+
]
|
23
|
+
|
24
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log **/.*.sw? *.gem .config **/.DS_Store]
|
25
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
26
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
27
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
31
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
32
|
+
|
33
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
34
|
+
# task :default => [:spec, :features]
|
data/TODO
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Common use-cases should be streamlined:
|
2
|
+
|
3
|
+
* I have a URL that I want to sign (given consumer key/secret, optional
|
4
|
+
token/secret, optional nonce/timestamp).
|
5
|
+
* I have a URL that I want to sign AND I want to see what the components
|
6
|
+
(e.g. signature base string, etc.) are while it's being signed (i.e. verbose
|
7
|
+
signing).
|
8
|
+
* I have a URL that I want to sign and I only want the signature.
|
9
|
+
* I have a URL that I want to sign and I want something suitable to put in
|
10
|
+
{the header, the querystring, XMPP}.
|
11
|
+
* I want to make a query to an OAuth-enabled web service (with sensible
|
12
|
+
errors, if available).
|
13
|
+
* I want to host an OAuth-enabled web service.
|
14
|
+
* I want to test my OAuth-enabled web service (i.e. test helpers)
|
data/bin/oauth
ADDED
data/lib/oauth.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'oauth/client/helper'
|
2
|
+
require 'oauth/signature/hmac/sha1'
|
3
|
+
require 'oauth/request_proxy/mock_request'
|
data/lib/oauth/cli.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'oauth'
|
3
|
+
|
4
|
+
module OAuth
|
5
|
+
class CLI
|
6
|
+
SUPPORTED_COMMANDS = %w(sign)
|
7
|
+
|
8
|
+
attr_reader :command
|
9
|
+
attr_reader :options
|
10
|
+
attr_reader :stdout
|
11
|
+
|
12
|
+
def self.execute(stdout, arguments = [])
|
13
|
+
self.new.execute(stdout, arguments)
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute(stdout, arguments = [])
|
17
|
+
@stdout = stdout
|
18
|
+
extract_command_and_parse_options(arguments)
|
19
|
+
|
20
|
+
if sufficient_options? && valid_command?
|
21
|
+
case command
|
22
|
+
when "sign"
|
23
|
+
request = OAuth::RequestProxy.proxy \
|
24
|
+
"method" => options[:method],
|
25
|
+
"uri" => options[:uri],
|
26
|
+
"parameters" => prepare_parameters
|
27
|
+
|
28
|
+
# can't pass options unless they respond to :secret, so use this alternative
|
29
|
+
signature = OAuth::Signature.sign \
|
30
|
+
request,
|
31
|
+
:consumer_secret => options[:oauth_consumer_secret],
|
32
|
+
:token_secret => options[:oauth_token_secret] do |request|
|
33
|
+
|
34
|
+
# while we have access to the request being signed, display some internals
|
35
|
+
if verbose?
|
36
|
+
stdout.puts "Method: #{request.method}"
|
37
|
+
stdout.puts "URI: #{request.uri}"
|
38
|
+
stdout.puts "Normalized params: #{request.normalized_parameters}"
|
39
|
+
stdout.puts "Signature base string: #{request.signature_base_string}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if verbose?
|
44
|
+
stdout.puts "Signature: #{signature}"
|
45
|
+
stdout.puts "Escaped signature: #{OAuth::Helper.escape(signature)}"
|
46
|
+
else
|
47
|
+
stdout.puts signature
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
usage
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def extract_command_and_parse_options(arguments)
|
56
|
+
@command = arguments[-1]
|
57
|
+
parse_options(arguments[0..-1])
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_options(arguments)
|
61
|
+
@options = {}
|
62
|
+
OptionParser.new do |opts|
|
63
|
+
opts.banner = "Usage: #{$0} [options] <command>"
|
64
|
+
|
65
|
+
# defaults
|
66
|
+
options[:oauth_signature_method] = "HMAC-SHA1"
|
67
|
+
|
68
|
+
opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
|
69
|
+
options[:oauth_consumer_key] = v
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
|
73
|
+
options[:oauth_consumer_secret] = v
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
|
77
|
+
options[:method] = v
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
|
81
|
+
options[:params] = v
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
|
85
|
+
options[:oauth_signature_method] = v
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
|
89
|
+
options[:oauth_token_secret] = v
|
90
|
+
end
|
91
|
+
|
92
|
+
opts.on("--token TOKEN", "Specifies the token to use.") do |v|
|
93
|
+
options[:oauth_token] = v
|
94
|
+
end
|
95
|
+
|
96
|
+
opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
|
97
|
+
options[:uri] = v
|
98
|
+
end
|
99
|
+
|
100
|
+
opts.on("-v", "--verbose", "Be verbose.") do
|
101
|
+
options[:verbose] = true
|
102
|
+
end
|
103
|
+
end.parse!(arguments)
|
104
|
+
end
|
105
|
+
|
106
|
+
def prepare_parameters
|
107
|
+
{
|
108
|
+
"oauth_consumer_key" => options[:oauth_consumer_key],
|
109
|
+
"oauth_token" => options[:oauth_token],
|
110
|
+
"oauth_signature_method" => options[:oauth_signature_method]
|
111
|
+
}.merge(CGI.parse(options[:params]))
|
112
|
+
end
|
113
|
+
|
114
|
+
def sufficient_options?
|
115
|
+
options[:oauth_consumer_key] && options[:oauth_consumer_secret] && options[:method] && options[:uri]
|
116
|
+
end
|
117
|
+
|
118
|
+
def usage
|
119
|
+
stdout.puts "Should be generated by OptionParser"
|
120
|
+
end
|
121
|
+
|
122
|
+
def valid_command?
|
123
|
+
SUPPORTED_COMMANDS.include?(command)
|
124
|
+
end
|
125
|
+
|
126
|
+
def verbose?
|
127
|
+
options[:verbose]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/oauth/client/helper.rb
CHANGED
@@ -38,7 +38,7 @@ module OAuth::Client
|
|
38
38
|
'oauth_timestamp' => timestamp,
|
39
39
|
'oauth_nonce' => nonce,
|
40
40
|
'oauth_version' => '1.0'
|
41
|
-
}
|
41
|
+
}.reject { |k,v| v == "" }
|
42
42
|
end
|
43
43
|
|
44
44
|
def signature(extra_options = {})
|
@@ -60,7 +60,8 @@ module OAuth::Client
|
|
60
60
|
|
61
61
|
header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
|
62
62
|
|
63
|
-
|
63
|
+
realm = "realm=\"#{options[:realm]}\", " if options[:realm]
|
64
|
+
"OAuth #{realm}#{header_params_str}"
|
64
65
|
end
|
65
66
|
|
66
67
|
def parameters
|
data/lib/oauth/consumer.rb
CHANGED
@@ -91,7 +91,7 @@ module OAuth
|
|
91
91
|
# @request_token=@consumer.get_request_token
|
92
92
|
#
|
93
93
|
def get_request_token(request_options={}, *arguments)
|
94
|
-
response=token_request(http_method,
|
94
|
+
response=token_request(http_method,request_token_url, nil, request_options, *arguments)
|
95
95
|
OAuth::RequestToken.new(self,response[:oauth_token],response[:oauth_token_secret])
|
96
96
|
end
|
97
97
|
|
data/lib/oauth/helper.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
require 'action_controller/test_process'
|
3
|
+
module OAuth
|
4
|
+
module OAuthTestHelper
|
5
|
+
|
6
|
+
def mock_incoming_request_with_query(request)
|
7
|
+
incoming=ActionController::TestRequest.new(request.to_hash)
|
8
|
+
incoming.request_uri=request.path
|
9
|
+
incoming.env["SERVER_PORT"]=request.uri.port
|
10
|
+
incoming.host=request.uri.host
|
11
|
+
incoming.env['REQUEST_METHOD']=request.http_method
|
12
|
+
incoming
|
13
|
+
end
|
14
|
+
|
15
|
+
def mock_incoming_request_with_authorize_header(request)
|
16
|
+
incoming=ActionController::TestRequest.new
|
17
|
+
incoming.env["HTTP_AUTHORIZATION"]=request.to_auth_string
|
18
|
+
incoming.request_uri=request.path
|
19
|
+
incoming.env["SERVER_PORT"]=request.uri.port
|
20
|
+
incoming.host=request.uri.host
|
21
|
+
incoming.env['REQUEST_METHOD']=request.http_method
|
22
|
+
incoming
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -6,16 +6,14 @@ require 'uri'
|
|
6
6
|
|
7
7
|
module OAuth::RequestProxy
|
8
8
|
class ActionControllerRequest < OAuth::RequestProxy::Base
|
9
|
-
proxies ActionController::AbstractRequest
|
9
|
+
proxies(defined?(ActionController::AbstractRequest) ? ActionController::AbstractRequest : ActionController::Request)
|
10
10
|
|
11
11
|
def method
|
12
12
|
request.method.to_s.upcase
|
13
13
|
end
|
14
14
|
|
15
15
|
def uri
|
16
|
-
|
17
|
-
uri.query = nil
|
18
|
-
uri.to_s
|
16
|
+
request.url
|
19
17
|
end
|
20
18
|
|
21
19
|
def parameters
|
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'oauth/request_proxy'
|
2
|
+
require 'oauth/helper'
|
2
3
|
|
3
4
|
module OAuth::RequestProxy
|
4
5
|
class Base
|
6
|
+
include OAuth::Helper
|
7
|
+
|
5
8
|
def self.proxies(klass)
|
6
9
|
OAuth::RequestProxy.available_proxies[klass] = self
|
7
10
|
end
|
@@ -47,6 +50,34 @@ module OAuth::RequestProxy
|
|
47
50
|
parameters['oauth_signature'] || ""
|
48
51
|
end
|
49
52
|
|
53
|
+
# See 9.1.2 in specs
|
54
|
+
def normalized_uri
|
55
|
+
u=URI.parse(uri)
|
56
|
+
"#{u.scheme.downcase}://#{u.host.downcase}#{(u.scheme.downcase=='http'&&u.port!=80)||(u.scheme.downcase=='https'&&u.port!=443) ? ":#{u.port}" : ""}#{(u.path&&u.path!='') ? u.path : '/'}"
|
57
|
+
end
|
58
|
+
|
59
|
+
# See 9.1.1. in specs Normalize Request Parameters
|
60
|
+
def normalized_parameters
|
61
|
+
parameters_for_signature.sort.map do |k, values|
|
62
|
+
|
63
|
+
if values.is_a?(Array)
|
64
|
+
# multiple values were provided for a single key
|
65
|
+
values.sort.collect do |v|
|
66
|
+
[escape(k),escape(v)] * "="
|
67
|
+
end
|
68
|
+
else
|
69
|
+
[escape(k),escape(values)] * "="
|
70
|
+
end
|
71
|
+
end * "&"
|
72
|
+
end
|
73
|
+
|
74
|
+
# See 9.1 in specs
|
75
|
+
def signature_base_string
|
76
|
+
base = [method, normalized_uri, normalized_parameters]
|
77
|
+
base.map { |v| escape(v) }.join("&")
|
78
|
+
end
|
79
|
+
|
80
|
+
|
50
81
|
protected
|
51
82
|
|
52
83
|
def header_params
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'xmpp4r'
|
2
|
+
require 'oauth/request_proxy/base'
|
3
|
+
|
4
|
+
module OAuth
|
5
|
+
module RequestProxy
|
6
|
+
class JabberRequest < OAuth::RequestProxy::Base
|
7
|
+
proxies Jabber::Iq
|
8
|
+
proxies Jabber::Presence
|
9
|
+
proxies Jabber::Message
|
10
|
+
|
11
|
+
def parameters
|
12
|
+
return @params if @params
|
13
|
+
|
14
|
+
@params = {}
|
15
|
+
|
16
|
+
oauth = @request.get_elements('//oauth').first
|
17
|
+
return @params unless oauth
|
18
|
+
|
19
|
+
%w( oauth_token oauth_consumer_key oauth_signature_method oauth_signature
|
20
|
+
oauth_timestamp oauth_nonce oauth_version ).each do |param|
|
21
|
+
next unless element = oauth.first_element(param)
|
22
|
+
@params[param] = element.text
|
23
|
+
end
|
24
|
+
|
25
|
+
@params
|
26
|
+
end
|
27
|
+
|
28
|
+
def method
|
29
|
+
@request.name
|
30
|
+
end
|
31
|
+
|
32
|
+
def uri
|
33
|
+
[@request.from.strip.to_s, @request.to.strip.to_s].join("&")
|
34
|
+
end
|
35
|
+
|
36
|
+
def normalized_uri
|
37
|
+
uri
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|