oauth 0.3.1 → 0.3.2
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 +35 -17
- data/Manifest.txt +13 -1
- data/README.rdoc +5 -7
- data/Rakefile +6 -4
- data/TODO +18 -0
- data/bin/oauth +1 -1
- data/examples/yql.rb +44 -0
- data/lib/oauth.rb +1 -0
- data/lib/oauth/cli.rb +201 -31
- data/lib/oauth/client/action_controller_request.rb +13 -12
- data/lib/oauth/client/helper.rb +10 -14
- data/lib/oauth/client/net_http.rb +25 -22
- data/lib/oauth/consumer.rb +164 -110
- data/lib/oauth/errors.rb +3 -0
- data/lib/oauth/errors/error.rb +4 -0
- data/lib/oauth/errors/problem.rb +14 -0
- data/lib/oauth/errors/unauthorized.rb +12 -0
- data/lib/oauth/helper.rb +44 -6
- data/lib/oauth/oauth.rb +7 -0
- data/lib/oauth/oauth_test_helper.rb +12 -13
- data/lib/oauth/request_proxy/action_controller_request.rb +5 -6
- data/lib/oauth/request_proxy/base.rb +95 -45
- data/lib/oauth/request_proxy/jabber_request.rb +1 -2
- data/lib/oauth/request_proxy/mock_request.rb +8 -0
- data/lib/oauth/request_proxy/net_http.rb +2 -2
- data/lib/oauth/request_proxy/rack_request.rb +7 -7
- data/lib/oauth/server.rb +31 -33
- data/lib/oauth/signature/base.rb +23 -21
- data/lib/oauth/signature/hmac/base.rb +1 -1
- data/lib/oauth/signature/hmac/sha1.rb +0 -1
- data/lib/oauth/signature/plaintext.rb +2 -2
- data/lib/oauth/signature/rsa/sha1.rb +5 -4
- data/lib/oauth/token.rb +6 -136
- data/lib/oauth/tokens/access_token.rb +68 -0
- data/lib/oauth/tokens/consumer_token.rb +32 -0
- data/lib/oauth/tokens/request_token.rb +28 -0
- data/lib/oauth/tokens/server_token.rb +9 -0
- data/lib/oauth/tokens/token.rb +17 -0
- data/lib/oauth/version.rb +1 -1
- data/oauth.gemspec +12 -6
- data/test/cases/spec/1_0-final/test_construct_request_url.rb +1 -1
- data/test/test_access_token.rb +28 -0
- data/test/test_action_controller_request_proxy.rb +17 -0
- data/test/test_consumer.rb +3 -4
- data/test/test_helper.rb +0 -5
- data/test/test_request_token.rb +53 -0
- data/test/test_server.rb +1 -1
- data/website/index.html +2 -2
- metadata +37 -4
- data/specs.txt +0 -13
data/lib/oauth/server.rb
CHANGED
@@ -1,68 +1,66 @@
|
|
1
1
|
require 'oauth/helper'
|
2
2
|
require 'oauth/consumer'
|
3
|
+
|
3
4
|
module OAuth
|
4
5
|
# This is mainly used to create consumer credentials and can pretty much be ignored if you want to create your own
|
5
6
|
class Server
|
6
7
|
include OAuth::Helper
|
7
8
|
attr_accessor :base_url
|
8
|
-
|
9
|
-
@@server_paths={
|
10
|
-
:request_token_path=>"/oauth/request_token",
|
11
|
-
:authorize_path=>"/oauth/authorize",
|
12
|
-
:access_token_path=>"/oauth/access_token"
|
9
|
+
|
10
|
+
@@server_paths = {
|
11
|
+
:request_token_path => "/oauth/request_token",
|
12
|
+
:authorize_path => "/oauth/authorize",
|
13
|
+
:access_token_path => "/oauth/access_token"
|
13
14
|
}
|
15
|
+
|
14
16
|
# Create a new server instance
|
15
|
-
def initialize(base_url,paths={})
|
16
|
-
@base_url=base_url
|
17
|
-
@paths
|
17
|
+
def initialize(base_url, paths = {})
|
18
|
+
@base_url = base_url
|
19
|
+
@paths = @@server_paths.merge(paths)
|
18
20
|
end
|
19
|
-
|
20
|
-
def generate_credentials
|
21
|
-
[generate_key(16),generate_key]
|
21
|
+
|
22
|
+
def generate_credentials
|
23
|
+
[generate_key(16), generate_key]
|
22
24
|
end
|
23
|
-
|
24
|
-
def generate_consumer_credentials(params={})
|
25
|
-
Consumer.new(
|
25
|
+
|
26
|
+
def generate_consumer_credentials(params = {})
|
27
|
+
Consumer.new(*generate_credentials)
|
26
28
|
end
|
27
29
|
|
28
30
|
# mainly for testing purposes
|
29
31
|
def create_consumer
|
30
|
-
|
31
|
-
Consumer.new(
|
32
|
-
credentials[0],
|
33
|
-
credentials[1],
|
32
|
+
creds = generate_credentials
|
33
|
+
Consumer.new(creds[0], creds[1],
|
34
34
|
{
|
35
|
-
:site=>base_url,
|
36
|
-
:request_token_path=>request_token_path,
|
37
|
-
:authorize_path=>authorize_path,
|
38
|
-
:access_token_path=>access_token_path
|
39
|
-
|
35
|
+
:site => base_url,
|
36
|
+
:request_token_path => request_token_path,
|
37
|
+
:authorize_path => authorize_path,
|
38
|
+
:access_token_path => access_token_path
|
39
|
+
})
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def request_token_path
|
43
43
|
@paths[:request_token_path]
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def request_token_url
|
47
|
-
base_url+request_token_path
|
47
|
+
base_url + request_token_path
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
def authorize_path
|
51
51
|
@paths[:authorize_path]
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def authorize_url
|
55
|
-
base_url+authorize_path
|
55
|
+
base_url + authorize_path
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
def access_token_path
|
59
59
|
@paths[:access_token_path]
|
60
60
|
end
|
61
61
|
|
62
62
|
def access_token_url
|
63
|
-
base_url+access_token_path
|
63
|
+
base_url + access_token_path
|
64
64
|
end
|
65
|
-
|
66
|
-
|
67
65
|
end
|
68
66
|
end
|
data/lib/oauth/signature/base.rb
CHANGED
@@ -6,9 +6,10 @@ require 'base64'
|
|
6
6
|
module OAuth::Signature
|
7
7
|
class Base
|
8
8
|
include OAuth::Helper
|
9
|
-
|
9
|
+
|
10
10
|
attr_accessor :options
|
11
|
-
|
11
|
+
attr_reader :token_secret, :consumer_secret, :request
|
12
|
+
|
12
13
|
def self.implements(signature_method)
|
13
14
|
OAuth::Signature.available_methods[signature_method] = self
|
14
15
|
end
|
@@ -18,32 +19,34 @@ module OAuth::Signature
|
|
18
19
|
@digest_class = digest_class
|
19
20
|
end
|
20
21
|
|
21
|
-
attr_reader :token_secret, :consumer_secret, :request
|
22
|
-
|
23
22
|
def initialize(request, options = {}, &block)
|
24
23
|
raise TypeError unless request.kind_of?(OAuth::RequestProxy::Base)
|
25
24
|
@request = request
|
26
25
|
@options = options
|
27
26
|
|
28
|
-
|
27
|
+
## consumer secret was determined beforehand
|
29
28
|
|
30
|
-
|
31
|
-
@token_secret, @consumer_secret = yield block.arity == 1 ? request : [token, consumer_key,nonce,request.timestamp]
|
29
|
+
@consumer_secret = options[:consumer].secret if options[:consumer]
|
32
30
|
|
33
|
-
|
34
|
-
|
31
|
+
# presence of :consumer_secret option will override any Consumer that's provided
|
32
|
+
@consumer_secret = options[:consumer_secret] if options[:consumer_secret]
|
35
33
|
|
36
|
-
|
34
|
+
## token secret was determined beforehand
|
37
35
|
|
38
|
-
|
39
|
-
@consumer_secret = options[:consumer_secret] if options[:consumer_secret]
|
36
|
+
@token_secret = options[:token].secret if options[:token]
|
40
37
|
|
41
|
-
|
38
|
+
# presence of :token_secret option will override any Token that's provided
|
39
|
+
@token_secret = options[:token_secret] if options[:token_secret]
|
42
40
|
|
43
|
-
@token_secret = options[:token].secret if options[:token]
|
44
41
|
|
45
|
-
|
46
|
-
|
42
|
+
# override secrets based on the values returned from the block (if any)
|
43
|
+
if block_given?
|
44
|
+
# consumer secret and token secret need to be looked up based on pieces of the request
|
45
|
+
secrets = yield block.arity == 1 ? request : [token, consumer_key, nonce, request.timestamp]
|
46
|
+
if secrets.is_a?(Array) && secrets.size == 2
|
47
|
+
@token_secret = secrets[0]
|
48
|
+
@consumer_secret = secrets[1]
|
49
|
+
end
|
47
50
|
end
|
48
51
|
end
|
49
52
|
|
@@ -62,17 +65,17 @@ module OAuth::Signature
|
|
62
65
|
def signature_base_string
|
63
66
|
request.signature_base_string
|
64
67
|
end
|
65
|
-
|
66
|
-
|
68
|
+
|
69
|
+
private
|
67
70
|
|
68
71
|
def token
|
69
72
|
request.token
|
70
73
|
end
|
71
|
-
|
74
|
+
|
72
75
|
def consumer_key
|
73
76
|
request.consumer_key
|
74
77
|
end
|
75
|
-
|
78
|
+
|
76
79
|
def nonce
|
77
80
|
request.nonce
|
78
81
|
end
|
@@ -84,6 +87,5 @@ module OAuth::Signature
|
|
84
87
|
def digest
|
85
88
|
self.class.digest_class.digest(signature_base_string)
|
86
89
|
end
|
87
|
-
|
88
90
|
end
|
89
91
|
end
|
@@ -18,9 +18,9 @@ module OAuth::Signature::RSA
|
|
18
18
|
consumer_secret
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
24
|
def decode_public_key
|
25
25
|
case consumer_secret
|
26
26
|
when /-----BEGIN CERTIFICATE-----/
|
@@ -29,7 +29,7 @@ module OAuth::Signature::RSA
|
|
29
29
|
OpenSSL::PKey::RSA.new( consumer_secret)
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def digest
|
34
34
|
private_key = OpenSSL::PKey::RSA.new(
|
35
35
|
if options[:private_key_file]
|
@@ -38,6 +38,7 @@ module OAuth::Signature::RSA
|
|
38
38
|
consumer_secret
|
39
39
|
end
|
40
40
|
)
|
41
|
+
|
41
42
|
private_key.sign(OpenSSL::Digest::SHA1.new, signature_base_string)
|
42
43
|
end
|
43
44
|
end
|
data/lib/oauth/token.rb
CHANGED
@@ -1,137 +1,7 @@
|
|
1
|
-
|
2
|
-
module OAuth
|
3
|
-
|
4
|
-
# Superclass for the various tokens used by OAuth
|
5
|
-
|
6
|
-
class Token
|
7
|
-
include OAuth::Helper
|
8
|
-
|
9
|
-
attr_accessor :token, :secret
|
1
|
+
# this exists for backwards-compatibility
|
10
2
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def to_query
|
17
|
-
"oauth_token=#{escape(token)}&oauth_secret=#{escape(secret)}"
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
# Used on the server for generating tokens
|
23
|
-
class ServerToken<Token
|
24
|
-
|
25
|
-
def initialize
|
26
|
-
super generate_key(16),generate_key
|
27
|
-
end
|
28
|
-
end
|
29
|
-
# Superclass for tokens used by OAuth Clients
|
30
|
-
class ConsumerToken<Token
|
31
|
-
attr_accessor :consumer
|
32
|
-
|
33
|
-
def initialize(consumer,token="",secret="")
|
34
|
-
super token,secret
|
35
|
-
@consumer=consumer
|
36
|
-
end
|
37
|
-
|
38
|
-
# Make a signed request using given http_method to the path
|
39
|
-
#
|
40
|
-
# @token.request(:get,'/people')
|
41
|
-
# @token.request(:post,'/people',@person.to_xml,{ 'Content-Type' => 'application/xml' })
|
42
|
-
#
|
43
|
-
def request(http_method,path,*arguments)
|
44
|
-
response=consumer.request(http_method,path,self,{},*arguments)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Sign a request generated elsewhere using Net:HTTP::Post.new or friends
|
48
|
-
def sign!(request,options = {})
|
49
|
-
consumer.sign!(request,self,options)
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
# The RequestToken is used for the initial Request.
|
55
|
-
# This is normally created by the Consumer object.
|
56
|
-
class RequestToken<ConsumerToken
|
57
|
-
|
58
|
-
# Returns the authorization url that you need to use for redirecting the user
|
59
|
-
def authorize_url
|
60
|
-
consumer.authorize_url+"?oauth_token="+CGI.escape(token)
|
61
|
-
end
|
62
|
-
|
63
|
-
# exchange for AccessToken on server
|
64
|
-
def get_access_token(options={})
|
65
|
-
response=consumer.token_request(consumer.http_method,(consumer.access_token_url? ? consumer.access_token_url : consumer.access_token_path),self,options)
|
66
|
-
OAuth::AccessToken.new(consumer,response[:oauth_token],response[:oauth_token_secret])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# The Access Token is used for the actual "real" web service calls thatyou perform against the server
|
71
|
-
class AccessToken<ConsumerToken
|
72
|
-
|
73
|
-
# The less intrusive way. Otherwise, if we are to do it correctly inside consumer,
|
74
|
-
# we need to restructure and touch more methods: request(), sign!(), etc.
|
75
|
-
def request(http_method, path, *arguments)
|
76
|
-
request_uri = URI.parse(path)
|
77
|
-
site_uri = consumer.uri
|
78
|
-
is_service_uri_different = (request_uri.absolute? && request_uri != site_uri)
|
79
|
-
consumer.uri(request_uri) if is_service_uri_different
|
80
|
-
resp = super(http_method, path, *arguments)
|
81
|
-
# NOTE: reset for wholesomeness? meaning that we admit only AccessToken service calls may use different URIs?
|
82
|
-
# so reset in case consumer is still used for other token-management tasks subsequently?
|
83
|
-
consumer.uri(site_uri) if is_service_uri_different
|
84
|
-
resp
|
85
|
-
end
|
86
|
-
|
87
|
-
# Make a regular get request using AccessToken
|
88
|
-
#
|
89
|
-
# @response=@token.get('/people')
|
90
|
-
# @response=@token.get('/people',{'Accept'=>'application/xml'})
|
91
|
-
#
|
92
|
-
def get(path,headers={})
|
93
|
-
request(:get,path,headers)
|
94
|
-
end
|
95
|
-
|
96
|
-
# Make a regular head request using AccessToken
|
97
|
-
#
|
98
|
-
# @response=@token.head('/people')
|
99
|
-
#
|
100
|
-
def head(path,headers={})
|
101
|
-
request(:head,path,headers)
|
102
|
-
end
|
103
|
-
|
104
|
-
# Make a regular post request using AccessToken
|
105
|
-
#
|
106
|
-
# @response=@token.post('/people')
|
107
|
-
# @response=@token.post('/people',{:name=>'Bob',:email=>'bob@mailinator.com'})
|
108
|
-
# @response=@token.post('/people',{:name=>'Bob',:email=>'bob@mailinator.com'},{'Accept'=>'application/xml'})
|
109
|
-
# @response=@token.post('/people',nil,{'Accept'=>'application/xml'})
|
110
|
-
# @response=@token.post('/people',@person.to_xml,{'Accept'=>'application/xml','Content-Type' => 'application/xml'})
|
111
|
-
#
|
112
|
-
def post(path, body = '',headers={})
|
113
|
-
request(:post,path,body,headers)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Make a regular put request using AccessToken
|
117
|
-
#
|
118
|
-
# @response=@token.put('/people/123')
|
119
|
-
# @response=@token.put('/people/123',{:name=>'Bob',:email=>'bob@mailinator.com'})
|
120
|
-
# @response=@token.put('/people/123',{:name=>'Bob',:email=>'bob@mailinator.com'},{'Accept'=>'application/xml'})
|
121
|
-
# @response=@token.put('/people/123',nil,{'Accept'=>'application/xml'})
|
122
|
-
# @response=@token.put('/people/123',@person.to_xml,{'Accept'=>'application/xml','Content-Type' => 'application/xml'})
|
123
|
-
#
|
124
|
-
def put(path, body = '', headers={})
|
125
|
-
request(:put,path,body,headers)
|
126
|
-
end
|
127
|
-
|
128
|
-
# Make a regular delete request using AccessToken
|
129
|
-
#
|
130
|
-
# @response=@token.delete('/people/123')
|
131
|
-
# @response=@token.delete('/people/123',{'Accept'=>'application/xml'})
|
132
|
-
#
|
133
|
-
def delete(path,headers={})
|
134
|
-
request(:delete,path,headers)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
3
|
+
require 'oauth/tokens/token'
|
4
|
+
require 'oauth/tokens/server_token'
|
5
|
+
require 'oauth/tokens/consumer_token'
|
6
|
+
require 'oauth/tokens/request_token'
|
7
|
+
require 'oauth/tokens/access_token'
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module OAuth
|
2
|
+
# The Access Token is used for the actual "real" web service calls that you perform against the server
|
3
|
+
class AccessToken < ConsumerToken
|
4
|
+
# The less intrusive way. Otherwise, if we are to do it correctly inside consumer,
|
5
|
+
# we need to restructure and touch more methods: request(), sign!(), etc.
|
6
|
+
def request(http_method, path, *arguments)
|
7
|
+
request_uri = URI.parse(path)
|
8
|
+
site_uri = consumer.uri
|
9
|
+
is_service_uri_different = (request_uri.absolute? && request_uri != site_uri)
|
10
|
+
consumer.uri(request_uri) if is_service_uri_different
|
11
|
+
@response = super(http_method, path, *arguments)
|
12
|
+
# NOTE: reset for wholesomeness? meaning that we admit only AccessToken service calls may use different URIs?
|
13
|
+
# so reset in case consumer is still used for other token-management tasks subsequently?
|
14
|
+
consumer.uri(site_uri) if is_service_uri_different
|
15
|
+
@response
|
16
|
+
end
|
17
|
+
|
18
|
+
# Make a regular GET request using AccessToken
|
19
|
+
#
|
20
|
+
# @response = @token.get('/people')
|
21
|
+
# @response = @token.get('/people', { 'Accept'=>'application/xml' })
|
22
|
+
#
|
23
|
+
def get(path, headers = {})
|
24
|
+
request(:get, path, headers)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Make a regular HEAD request using AccessToken
|
28
|
+
#
|
29
|
+
# @response = @token.head('/people')
|
30
|
+
#
|
31
|
+
def head(path, headers = {})
|
32
|
+
request(:head, path, headers)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Make a regular POST request using AccessToken
|
36
|
+
#
|
37
|
+
# @response = @token.post('/people')
|
38
|
+
# @response = @token.post('/people', { :name => 'Bob', :email => 'bob@mailinator.com' })
|
39
|
+
# @response = @token.post('/people', { :name => 'Bob', :email => 'bob@mailinator.com' }, { 'Accept' => 'application/xml' })
|
40
|
+
# @response = @token.post('/people', nil, {'Accept' => 'application/xml' })
|
41
|
+
# @response = @token.post('/people', @person.to_xml, { 'Accept'=>'application/xml', 'Content-Type' => 'application/xml' })
|
42
|
+
#
|
43
|
+
def post(path, body = '', headers = {})
|
44
|
+
request(:post, path, body, headers)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Make a regular PUT request using AccessToken
|
48
|
+
#
|
49
|
+
# @response = @token.put('/people/123')
|
50
|
+
# @response = @token.put('/people/123', { :name => 'Bob', :email => 'bob@mailinator.com' })
|
51
|
+
# @response = @token.put('/people/123', { :name => 'Bob', :email => 'bob@mailinator.com' }, { 'Accept' => 'application/xml' })
|
52
|
+
# @response = @token.put('/people/123', nil, { 'Accept' => 'application/xml' })
|
53
|
+
# @response = @token.put('/people/123', @person.to_xml, { 'Accept' => 'application/xml', 'Content-Type' => 'application/xml' })
|
54
|
+
#
|
55
|
+
def put(path, body = '', headers = {})
|
56
|
+
request(:put, path, body, headers)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Make a regular DELETE request using AccessToken
|
60
|
+
#
|
61
|
+
# @response = @token.delete('/people/123')
|
62
|
+
# @response = @token.delete('/people/123', { 'Accept' => 'application/xml' })
|
63
|
+
#
|
64
|
+
def delete(path, headers = {})
|
65
|
+
request(:delete, path, headers)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|