oauth 0.1.1 → 0.2.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.

Files changed (47) hide show
  1. data/History.txt +9 -0
  2. data/License.txt +1 -1
  3. data/Manifest.txt +25 -7
  4. data/config/hoe.rb +1 -1
  5. data/lib/oauth.rb +1 -12
  6. data/lib/oauth/client.rb +4 -0
  7. data/lib/oauth/client/action_controller_request.rb +51 -0
  8. data/lib/oauth/client/helper.rb +74 -0
  9. data/lib/oauth/client/net_http.rb +72 -0
  10. data/lib/oauth/consumer.rb +112 -43
  11. data/lib/oauth/{key.rb → helper.rb} +6 -7
  12. data/lib/oauth/request_proxy.rb +24 -0
  13. data/lib/oauth/request_proxy/action_controller_request.rb +65 -0
  14. data/lib/oauth/request_proxy/base.rb +50 -0
  15. data/lib/oauth/request_proxy/net_http.rb +64 -0
  16. data/lib/oauth/server.rb +12 -9
  17. data/lib/oauth/signature.rb +15 -142
  18. data/lib/oauth/signature/base.rb +69 -0
  19. data/lib/oauth/signature/hmac/base.rb +12 -0
  20. data/lib/oauth/signature/hmac/md5.rb +9 -0
  21. data/lib/oauth/signature/hmac/rmd160.rb +9 -0
  22. data/lib/oauth/signature/hmac/sha1.rb +10 -0
  23. data/lib/oauth/signature/hmac/sha2.rb +9 -0
  24. data/lib/oauth/signature/md5.rb +13 -0
  25. data/lib/oauth/signature/plaintext.rb +19 -0
  26. data/lib/oauth/signature/rsa/sha1.rb +20 -0
  27. data/lib/oauth/signature/sha1.rb +13 -0
  28. data/lib/oauth/token.rb +54 -14
  29. data/lib/oauth/version.rb +2 -2
  30. data/test/test_action_controller_request_proxy.rb +10 -0
  31. data/test/test_consumer.rb +144 -57
  32. data/test/test_helper.rb +4 -0
  33. data/test/test_hmac_sha1.rb +21 -0
  34. data/test/test_net_http_client.rb +139 -0
  35. data/test/test_net_http_request_proxy.rb +38 -0
  36. data/test/test_server.rb +1 -8
  37. data/test/test_signature.rb +11 -113
  38. data/test/test_signature_base.rb +32 -0
  39. data/test/test_token.rb +14 -0
  40. data/website/index.html +9 -8
  41. data/website/index.txt +5 -6
  42. metadata +37 -13
  43. data/lib/oauth/consumer_credentials.rb +0 -12
  44. data/lib/oauth/oauth_test_helper.rb +0 -24
  45. data/lib/oauth/request.rb +0 -258
  46. data/test/test_oauth.rb +0 -11
  47. data/test/test_request.rb +0 -282
@@ -1,15 +1,14 @@
1
1
  require 'openssl'
2
2
  require 'base64'
3
3
  module OAuth
4
- module Key
5
- def generate_key(size=32)
6
- Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/,'')
7
- end
8
-
9
- # Based on Blaine's example from the Oauth mailing list
4
+ module Helper
10
5
  def escape(value)
11
- CGI.escape(value.to_s).gsub("%7E", "~").gsub("+", "%20")
6
+ CGI.escape(value.to_s).gsub("%7E", '~').gsub("+", "%20")
12
7
  end
13
8
 
9
+ def generate_key(size=32)
10
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/,'')
11
+ end
12
+
14
13
  end
15
14
  end
@@ -0,0 +1,24 @@
1
+ module OAuth
2
+ module RequestProxy
3
+ def self.available_proxies #:nodoc:
4
+ @available_proxies ||= {}
5
+ end
6
+
7
+ def self.proxy(request, options = {})
8
+ return request if request.kind_of?(OAuth::RequestProxy::Base)
9
+
10
+ klass = available_proxies[request.class]
11
+
12
+ # Search for possible superclass matches.
13
+ if klass.nil?
14
+ request_parent = available_proxies.keys.find { |rc| request.kind_of?(rc) }
15
+ klass = available_proxies[request_parent]
16
+ end
17
+
18
+ raise UnknownRequestType, request.class.to_s unless klass
19
+ klass.new(request, options)
20
+ end
21
+
22
+ class UnknownRequestType < Exception; end
23
+ end
24
+ end
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'action_controller/request'
4
+ require 'oauth/request_proxy/base'
5
+ require 'uri'
6
+
7
+ module OAuth::RequestProxy
8
+ class ActionControllerRequest < OAuth::RequestProxy::Base
9
+ proxies ActionController::AbstractRequest
10
+
11
+ def method
12
+ request.method.to_s.upcase
13
+ end
14
+
15
+ def uri
16
+ uri = URI.parse(request.protocol + request.host + request.port_string + request.path)
17
+ uri.query = nil
18
+ uri.to_s
19
+ end
20
+
21
+ def parameters
22
+ if options[:clobber_request]
23
+ options[:parameters] || {}
24
+ else
25
+ params = request_params.merge(query_params).merge(header_params)
26
+ params.stringify_keys! if params.respond_to?(:stringify_keys!)
27
+ params.merge(options[:parameters] || {})
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def header_params
34
+ %w( X-HTTP_AUTHORIZATION Authorization HTTP_AUTHORIZATION ).each do |header|
35
+ next unless request.env.include?(header)
36
+
37
+ header = request.env[header]
38
+ next unless header[0,6] == 'OAuth '
39
+
40
+ oauth_param_string = header[6,header.length].split(/[,=]/)
41
+ oauth_param_string.map! { |v| unescape(v.strip) }
42
+ oauth_param_string.map! { |v| v =~ /^\".*\"$/ ? v[1..-2] : v }
43
+ oauth_params = Hash[*oauth_param_string.flatten]
44
+ oauth_params.reject! { |k,v| k !~ /^oauth_/ }
45
+
46
+ return oauth_params
47
+ end
48
+
49
+ return {}
50
+ end
51
+
52
+ def query_params
53
+ request.query_parameters
54
+ end
55
+
56
+ def request_params
57
+ request.request_parameters
58
+ end
59
+
60
+ def unescape(value)
61
+ URI.unescape(value.gsub('+', '%2B'))
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,50 @@
1
+ require 'oauth/request_proxy'
2
+
3
+ module OAuth::RequestProxy
4
+ class Base
5
+ def self.proxies(klass)
6
+ OAuth::RequestProxy.available_proxies[klass] = self
7
+ end
8
+
9
+ attr_accessor :request, :options
10
+
11
+ def initialize(request, options = {})
12
+ @request = request
13
+ @options = options
14
+ end
15
+
16
+ def token
17
+ parameters['oauth_token']
18
+ end
19
+
20
+ def consumer_key
21
+ parameters['oauth_consumer_key']
22
+ end
23
+
24
+ def parameters_for_signature
25
+ p = parameters.dup
26
+ p.delete("oauth_signature")
27
+ p
28
+ end
29
+
30
+ def nonce
31
+ parameters['oauth_nonce']
32
+ end
33
+
34
+ def timestamp
35
+ parameters['oauth_timestamp']
36
+ end
37
+
38
+ def signature_method
39
+ case parameters['oauth_signature_method']
40
+ when Array: parameters['oauth_signature_method'].first
41
+ else
42
+ parameters['oauth_signature_method']
43
+ end
44
+ end
45
+
46
+ def signature
47
+ parameters['oauth_signature'] || ""
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,64 @@
1
+ require 'oauth/request_proxy/base'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'cgi'
5
+
6
+ module OAuth::RequestProxy::Net
7
+ module HTTP
8
+ class HTTPRequest < OAuth::RequestProxy::Base
9
+ proxies ::Net::HTTPRequest
10
+
11
+ def method
12
+ request.method
13
+ end
14
+
15
+ def uri
16
+ uri = options[:uri]
17
+ uri = URI.parse(uri) unless uri.kind_of?(URI)
18
+ uri.query = nil
19
+ uri.to_s
20
+ end
21
+
22
+ def parameters
23
+ if options[:clobber_request]
24
+ options[:parameters]
25
+ else
26
+ all_parameters
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def all_parameters
33
+ request_params = CGI.parse(query_string)
34
+ if options[:parameters]
35
+ options[:parameters].each do |k,v|
36
+ if request_params.has_key?(k)
37
+ request_params[k] << v
38
+ else
39
+ request_params[k] = [v].flatten
40
+ end
41
+ end
42
+ end
43
+ request_params
44
+ end
45
+
46
+ def query_string
47
+ [ query_params, post_params, auth_header_params ].compact.join('&')
48
+ end
49
+
50
+ def query_params
51
+ URI.parse(request.path).query
52
+ end
53
+
54
+ def post_params
55
+ request.body
56
+ end
57
+
58
+ def auth_header_params
59
+ return nil unless request['Authorization'] && request['Authorization'][0,5] == 'OAuth'
60
+ auth_params = request['Authorization']
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,7 +1,9 @@
1
+ require 'oauth/helper'
2
+ require 'oauth/consumer'
1
3
  module OAuth
2
4
  # This is mainly used to create consumer credentials and can pretty much be ignored if you want to create your own
3
5
  class Server
4
- include OAuth::Key
6
+ include OAuth::Helper
5
7
  attr_accessor :base_url
6
8
 
7
9
  @@server_paths={
@@ -20,19 +22,20 @@ module OAuth
20
22
  end
21
23
 
22
24
  def generate_consumer_credentials(params={})
23
- ConsumerCredentials.new( *generate_credentials)
25
+ Consumer.new( *generate_credentials)
24
26
  end
25
27
 
26
28
  # mainly for testing purposes
27
29
  def create_consumer
28
30
  credentials=generate_credentials
29
- Consumer.new( {
30
- :site=>base_url,
31
- :consumer_key=>credentials[0],
32
- :consumer_secret=>credentials[1],
33
- :request_token_path=>request_token_path,
34
- :authorize_path=>authorize_path,
35
- :access_token_path=>access_token_path
31
+ Consumer.new(
32
+ credentials[0],
33
+ credentials[1],
34
+ {
35
+ :site=>base_url,
36
+ :request_token_path=>request_token_path,
37
+ :authorize_path=>authorize_path,
38
+ :access_token_path=>access_token_path
36
39
  })
37
40
  end
38
41
 
@@ -1,155 +1,28 @@
1
- require 'cgi'
2
- require 'hmac' # make sure to install: sudo gem install ruby-hmac
3
- require 'hmac-sha1'
4
- require 'hmac-md5'
5
- require 'hmac-sha2'
6
- require 'hmac-rmd160'
7
-
8
- require 'base64'
9
1
  module OAuth
10
- # Much of this code has been blatantly stolen fron Blaine Cooke of Twitter and Larry Halff of ma.gnolia.com
11
- # and lovingly hand modified with the utmost respect.
12
-
13
- # You should not need to use this directly as the request object encapsulates it in the sign and verify methods
14
2
  module Signature
15
- def self.create(oauth_request,consumer_secret,token_secret=nil)
16
- klass = case oauth_request.signature_method.downcase
17
- when 'hmac-md5': OAuth::Signature::HashedMessageAuth::MD5
18
- when 'hmac-sha1': OAuth::Signature::HashedMessageAuth::SHA1
19
- when 'hmac-sha2': OAuth::Signature::HashedMessageAuth::SHA2
20
- when 'hmac-rmd160': OAuth::Signature::HashedMessageAuth::RMD160
21
- when 'plaintext':
22
- if oauth_request.uri.scheme=="https"
23
- OAuth::Signature::PLAINTEXT
24
- else
25
- raise InsecureSignatureMethod
26
- end
27
- when 'rsa-sha1': OAuth::Signature::RSA::SHA1
28
- when 'sha1': raise InsecureSignatureMethod, oauth_request.signature_method
29
- when 'md5': raise InsecureSignatureMethod, oauth_request.signature_method
30
- else
31
- raise UnknownSignatureMethod, oauth_request.signature_method
32
- end
33
-
34
- klass.new(oauth_request,consumer_secret,token_secret)
3
+ def self.available_methods
4
+ @available_methods ||= {}
35
5
  end
36
6
 
37
- class UnknownSignatureMethod < Exception; end
38
-
39
- class InsecureSignatureMethod < Exception; end
40
-
41
- class Base
42
- include OAuth::Key
43
-
44
- attr_accessor :request
45
-
46
- def initialize(request,consumer_secret,token_secret=nil)
47
- @request=request
48
- @consumer_secret=consumer_secret
49
- @token_secret=token_secret
50
- end
51
-
52
- def base_string
53
- [@request.http_method,@request.normalized_url,@request.to_query_without_signature].collect{|p| @request.escape(p)}.join('&')
54
- end
55
-
56
- def key
57
- "#{@consumer_secret}&#{@token_secret}"
58
- end
59
-
60
- def consumer_secret
61
- @consumer_secret||=""
62
- end
63
-
64
- def token_secret
65
- @token_secret||=""
66
- end
67
-
68
- def sign
69
- Base64.encode64(digest).chomp
70
- end
71
-
72
- def sign!
73
- @request.signature=sign
74
- end
75
-
76
- def verify?
77
- return false unless @request.signed?
78
- @request.signature==sign
79
- end
80
-
81
- protected
82
-
83
- def digest
84
- digest_class.digest(base_string)
85
- end
7
+ def self.build(request, options = {}, &block)
8
+ request = OAuth::RequestProxy.proxy(request, options)
9
+ klass = available_methods[(request.signature_method || "").downcase]
10
+ raise UnknownSignatureMethod, request.signature_method unless klass
11
+ klass.new(request, options, &block)
86
12
  end
87
-
88
- class PLAINTEXT < Base
89
-
90
- def sign
91
- base_string
92
- end
93
-
94
- def base_string
95
- "#{escape(consumer_secret)}&#{escape(token_secret)}"
96
- end
97
-
98
- private
99
13
 
100
- def digest; signature_base_string; end
14
+ def self.sign(request, options = {}, &block)
15
+ self.build(request, options, &block).signature
101
16
  end
102
-
103
- module HashedMessageAuth
104
- class Base < OAuth::Signature::Base
105
17
 
106
- private
107
-
108
- def digest
109
- hmac_class.digest(secret, base_string)
110
- end
111
-
112
- def secret
113
- "#{escape(consumer_secret)}&#{escape(token_secret)}"
114
- end
115
- end
116
-
117
- class MD5 < Base
118
- private
119
- def hmac_class; HMAC::MD5; end
120
- end
121
-
122
- class RMD160 < Base
123
- private
124
- def hmac_class; HMAC::RMD160; end
125
- end
126
-
127
- class SHA1 < Base
128
- private
129
- def hmac_class; HMAC::SHA1; end
130
- end
131
-
132
- class SHA2 < Base
133
- private
134
- def hmac_class; HMAC::SHA1; end
135
- end
18
+ def self.verify(request, options = {}, &block)
19
+ self.build(request, options, &block).verify
136
20
  end
137
21
 
138
- module RSA
139
- class SHA1 < OAuth::Signature::Base
140
- def ==(cmp_signature)
141
- public_key = OpenSSL::PKey::RSA.new(consumer_secret)
142
- public_key.verify(OpenSSL::Digest::SHA1.new, cmp_signature, base_string)
143
- end
144
-
145
- private
146
-
147
- def digest
148
- private_key = OpenSSL::PKey::RSA.new(consumer_secret)
149
- private_key.sign(OpenSSL::Digest::SHA1.new, base_string)
150
- end
151
- end
22
+ def self.signature_base_string(request, options = {}, &block)
23
+ self.build(request, options, &block).signature_base_string
152
24
  end
153
-
25
+
26
+ class UnknownSignatureMethod < Exception; end
154
27
  end
155
28
  end
@@ -0,0 +1,69 @@
1
+ require 'oauth/signature'
2
+ require 'oauth/helper'
3
+ require 'oauth/request_proxy/base'
4
+ require 'base64'
5
+
6
+ module OAuth::Signature
7
+ class Base
8
+ include OAuth::Helper
9
+
10
+ def self.implements(signature_method)
11
+ OAuth::Signature.available_methods[signature_method] = self
12
+ end
13
+
14
+ def self.digest_class(digest_class = nil)
15
+ return @digest_class if digest_class.nil?
16
+ @digest_class = digest_class
17
+ end
18
+
19
+ attr_reader :token_secret, :consumer_secret, :request
20
+
21
+ def initialize(request, options = {}, &block)
22
+ raise TypeError unless request.kind_of?(OAuth::RequestProxy::Base)
23
+ @request = request
24
+ if block_given?
25
+ @token_secret, @consumer_secret = yield block.arity == 1 ? token : [token, consumer_key]
26
+ else
27
+ @consumer_secret = options[:consumer].secret
28
+ @token_secret = options[:token] ? options[:token].secret : ''
29
+ end
30
+ end
31
+
32
+ def signature
33
+ Base64.encode64(digest).chomp
34
+ end
35
+
36
+ def ==(cmp_signature)
37
+ Base64.decode64(signature) == Base64.decode64(cmp_signature)
38
+ end
39
+
40
+ def verify
41
+ self == self.request.signature
42
+ end
43
+
44
+ def signature_base_string
45
+ normalized_params = request.parameters_for_signature.sort.map { |k,v| [escape(k), escape(v)] * "=" }.join("&")
46
+ base = [request.method, request.uri, normalized_params]
47
+ sbs = base.map { |v| escape(v) }.join("&")
48
+ end
49
+
50
+ private
51
+
52
+ def token
53
+ request.token
54
+ end
55
+
56
+ def consumer_key
57
+ request.consumer_key
58
+ end
59
+
60
+ def secret
61
+ "#{escape(consumer_secret)}&#{escape(token_secret)}"
62
+ end
63
+
64
+ def digest
65
+ self.class.digest_class.digest(signature_base_string)
66
+ end
67
+
68
+ end
69
+ end