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,3 +1,12 @@
1
+ == 0.2 2007-1-19 All together now release
2
+
3
+ This is a big release, where we have merged the efforts of various parties into one common library. This means there are definitely some API changes you should be aware of. They should be minimal but please have a look at the unit tests.
4
+
5
+ == 0.1.2 2007-12-1
6
+
7
+ * 1 Fixed a problem where incoming request didn't check whether oauth parameters where missing. While not giving unauthorized access it did cause extra processing where not necessary.
8
+ * 2 Includes Pat's fix for getting the realm out.
9
+
1
10
  == 0.1.1 2007-11-26
2
11
 
3
12
  * 1 First release as a GEM
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 Pelle Braendgaard
1
+ Copyright (c) 2007 Blaine Cook, Larry Halff, Pelle Braendgaard
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -6,13 +6,28 @@ Rakefile
6
6
  config/hoe.rb
7
7
  config/requirements.rb
8
8
  lib/oauth.rb
9
+ lib/oauth/client.rb
10
+ lib/oauth/client/action_controller_request.rb
11
+ lib/oauth/client/helper.rb
12
+ lib/oauth/client/net_http.rb
9
13
  lib/oauth/consumer.rb
10
- lib/oauth/consumer_credentials.rb
11
- lib/oauth/key.rb
12
- lib/oauth/oauth_test_helper.rb
13
- lib/oauth/request.rb
14
+ lib/oauth/helper.rb
15
+ lib/oauth/request_proxy.rb
16
+ lib/oauth/request_proxy/action_controller_request.rb
17
+ lib/oauth/request_proxy/base.rb
18
+ lib/oauth/request_proxy/net_http.rb
14
19
  lib/oauth/server.rb
15
20
  lib/oauth/signature.rb
21
+ lib/oauth/signature/base.rb
22
+ lib/oauth/signature/hmac/base.rb
23
+ lib/oauth/signature/hmac/md5.rb
24
+ lib/oauth/signature/hmac/rmd160.rb
25
+ lib/oauth/signature/hmac/sha1.rb
26
+ lib/oauth/signature/hmac/sha2.rb
27
+ lib/oauth/signature/md5.rb
28
+ lib/oauth/signature/plaintext.rb
29
+ lib/oauth/signature/rsa/sha1.rb
30
+ lib/oauth/signature/sha1.rb
16
31
  lib/oauth/token.rb
17
32
  lib/oauth/version.rb
18
33
  script/destroy
@@ -22,12 +37,15 @@ setup.rb
22
37
  tasks/deployment.rake
23
38
  tasks/environment.rake
24
39
  tasks/website.rake
40
+ test/test_action_controller_request_proxy.rb
25
41
  test/test_consumer.rb
26
42
  test/test_helper.rb
27
- test/test_oauth.rb
28
- test/test_request.rb
29
- test/test_server.rb
43
+ test/test_hmac_sha1.rb
44
+ test/test_net_http_client.rb
45
+ test/test_net_http_request_proxy.rb
30
46
  test/test_signature.rb
47
+ test/test_signature_base.rb
48
+ test/test_token.rb
31
49
  website/index.html
32
50
  website/index.txt
33
51
  website/javascripts/rounded_corners_lite.inc.js
@@ -1,6 +1,6 @@
1
1
  require 'oauth/version'
2
2
 
3
- AUTHOR = 'Pelle Braendgaard' # can also be an array of Authors
3
+ AUTHOR = ['Pelle Braendgaard','Blaine Cook','Larry Halff'] # can also be an array of Authors
4
4
  EMAIL = "pelleb@gmail.com"
5
5
  DESCRIPTION = "OAuth Core Ruby implementation"
6
6
  GEM_NAME = 'oauth' # what ppl will type to install your gem
@@ -1,14 +1,3 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
- require 'rubygems'
3
- require 'oauth/key'
4
- require 'oauth/request'
5
- require 'oauth/signature'
6
- require 'oauth/consumer_credentials'
7
- require 'oauth/consumer'
8
- require 'oauth/server'
9
- require 'oauth/token'
10
- require 'oauth/oauth_test_helper'
11
2
 
12
- module OAuth
13
-
14
- end
3
+ module OAuth; end
@@ -0,0 +1,4 @@
1
+ module OAuth
2
+ module Client
3
+ end
4
+ end
@@ -0,0 +1,51 @@
1
+ require 'oauth/client/helper'
2
+ require 'oauth/request_proxy/action_controller_request'
3
+ require 'action_controller/test_process'
4
+
5
+ module ActionController
6
+ class Base
7
+ def process_with_oauth(request)
8
+ request.apply_oauth!
9
+ end
10
+
11
+ alias_method_chain :process, :oauth
12
+ end
13
+
14
+ class TestRequest
15
+ def self.use_oauth=(bool)
16
+ @use_oauth = bool
17
+ end
18
+
19
+ def self.use_oauth?
20
+ @use_oauth
21
+ end
22
+
23
+ def configure_oauth(consumer = nil, token = nil, options = {})
24
+ @options = { :consumer => consumer,
25
+ :token => token,
26
+ :scheme => 'header',
27
+ :signature_method => nil,
28
+ :nonce => nil,
29
+ :timestamp => nil }.merge(options)
30
+ end
31
+
32
+ def apply_oauth!
33
+ return unless ActionController::TestRequest.use_oauth?
34
+ @oauth_helper = OAuth::Client::Helper.new(self, @options.merge( { :request_uri => request_uri } ))
35
+
36
+ self.send("set_oauth_#{options[:scheme]}")
37
+ end
38
+
39
+ def set_oauth_header
40
+ env['Authorization'] = @oauth_helper.header
41
+ end
42
+
43
+ def set_oauth_parameters
44
+ @query_parameters = @oauth_helper.parameters_with_oauth
45
+ @query_parameters.merge!( { :oauth_signature => @oauth_helper.signature } )
46
+ end
47
+
48
+ def set_oauth_query_string
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,74 @@
1
+ require 'oauth/client'
2
+ require 'oauth/consumer'
3
+ require 'oauth/helper'
4
+ require 'oauth/token'
5
+ require 'oauth/signature/hmac/sha1'
6
+
7
+ module OAuth::Client
8
+ class Helper
9
+ include OAuth::Helper
10
+
11
+ def initialize(request, options = {})
12
+ @request = request
13
+ @options = options
14
+ @options[:signature_method] ||= 'HMAC-SHA1'
15
+ end
16
+
17
+ def options
18
+ @options
19
+ end
20
+
21
+ def nonce
22
+ options[:nonce] ||= generate_key
23
+ end
24
+
25
+ def timestamp
26
+ options[:timestamp] ||= generate_timestamp
27
+ end
28
+
29
+ def generate_timestamp
30
+ Time.now.to_i.to_s
31
+ end
32
+
33
+ def oauth_parameters
34
+ {
35
+ 'oauth_consumer_key' => options[:consumer].key,
36
+ 'oauth_token' => options[:token] ? options[:token].token : '',
37
+ 'oauth_signature_method' => options[:signature_method],
38
+ 'oauth_timestamp' => timestamp,
39
+ 'oauth_nonce' => nonce,
40
+ 'oauth_version' => '1.0'
41
+ }
42
+ end
43
+
44
+ def signature(extra_options = {})
45
+ OAuth::Signature.sign(@request, { :uri => options[:request_uri],
46
+ :consumer => options[:consumer],
47
+ :token => options[:token] }.merge(extra_options) )
48
+ end
49
+
50
+ def signature_base_string(extra_options = {})
51
+ OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
52
+ :consumer => options[:consumer],
53
+ :token => options[:token],
54
+ :parameters => oauth_parameters}.merge(extra_options) )
55
+ end
56
+
57
+ def header
58
+ parameters = oauth_parameters
59
+ parameters.merge!( { 'oauth_signature' => signature( { :parameters => parameters } ) } )
60
+
61
+ header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
62
+
63
+ return "OAuth realm=\"#{options[:realm]||''}\", #{header_params_str}"
64
+ end
65
+
66
+ def parameters
67
+ OAuth::RequestProxy.proxy(@request).parameters
68
+ end
69
+
70
+ def parameters_with_oauth
71
+ oauth_parameters.merge( parameters )
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,72 @@
1
+ require 'oauth/client/helper'
2
+ require 'oauth/request_proxy/net_http'
3
+
4
+ class Net::HTTPRequest
5
+ def oauth!(http, consumer = nil, token = nil, options = {})
6
+ options = { :request_uri => oauth_full_request_uri(http),
7
+ :consumer => consumer,
8
+ :token => token,
9
+ :scheme => 'header',
10
+ :signature_method => nil,
11
+ :nonce => nil,
12
+ :timestamp => nil }.merge(options)
13
+
14
+ @oauth_helper = OAuth::Client::Helper.new(self, options)
15
+ self.send("set_oauth_#{options[:scheme]}")
16
+ end
17
+
18
+ def signature_base_string(http, consumer = nil, token = nil, options = {})
19
+ options = { :request_uri => oauth_full_request_uri(http),
20
+ :consumer => consumer,
21
+ :token => token,
22
+ :scheme => 'header',
23
+ :signature_method => nil,
24
+ :nonce => nil,
25
+ :timestamp => nil }.merge(options)
26
+
27
+ OAuth::Client::Helper.new(self, options).signature_base_string
28
+ end
29
+
30
+ def oauth_helper
31
+ @oauth_helper
32
+ end
33
+ private
34
+
35
+ def oauth_full_request_uri(http)
36
+ uri = URI.parse(self.path)
37
+ uri.host = http.address
38
+ uri.port = http.port
39
+ if http.respond_to?(:use_ssl?)
40
+ uri.scheme = http.use_ssl? ? 'https' : 'http'
41
+ end
42
+ uri.to_s
43
+ end
44
+
45
+ def set_oauth_header
46
+ self['Authorization'] = @oauth_helper.header
47
+ end
48
+
49
+ # FIXME: if you're using a POST body and query string parameters, using this
50
+ # method will convert those parameters on the query string into parameters in
51
+ # the body. this is broken, and should be fixed.
52
+ def set_oauth_body
53
+ self.set_form_data(@oauth_helper.parameters_with_oauth)
54
+ params_with_sig = @oauth_helper.parameters.merge(:oauth_signature => @oauth_helper.signature)
55
+ self.set_form_data(params_with_sig)
56
+ end
57
+
58
+ def set_oauth_query_string
59
+ oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| "#{k}=#{v}" }.join("&")
60
+
61
+ uri = URI.parse(path)
62
+ if !uri.query || uri.query == ''
63
+ uri.query = oauth_params_str
64
+ else
65
+ uri.query = uri.query + "&" + oauth_params_str
66
+ end
67
+
68
+ @path = uri.to_s
69
+
70
+ @path << "&oauth_signature=#{@oauth_helper.signature}"
71
+ end
72
+ end
@@ -1,7 +1,9 @@
1
+ require 'net/http'
2
+ require 'oauth/client/net_http'
1
3
  module OAuth
2
- class Consumer<ConsumerCredentials
4
+ class Consumer
3
5
 
4
- @@default_params={
6
+ @@default_options={
5
7
  # Signature method used by server. Defaults to HMAC-SHA1
6
8
  :oauth_signature_method=>'HMAC-SHA1',
7
9
 
@@ -15,10 +17,10 @@ module OAuth
15
17
  #
16
18
  # Possible values:
17
19
  #
18
- # :authorize - via the Authorize header (Default) ( option 1. in spec)
19
- # :post - url form encoded in body of POST request ( option 2. in spec)
20
- # :query - via the query part of the url ( option 3. in spec)
21
- :auth_method=>:authorize,
20
+ # :header - via the Authorize header (Default) ( option 1. in spec)
21
+ # :body - url form encoded in body of POST request ( option 2. in spec)
22
+ # :query_string - via the query part of the url ( option 3. in spec)
23
+ :scheme=>:header,
22
24
 
23
25
  # Default http method used for OAuth Token Requests (defaults to :post)
24
26
  :http_method=>:post,
@@ -26,15 +28,14 @@ module OAuth
26
28
  :oauth_version=>"1.0"
27
29
  }
28
30
 
29
- attr_accessor :site,:params
31
+ attr_accessor :site,:options, :key, :secret,:http
32
+
30
33
 
31
34
  # Create a new consumer instance by passing it a configuration hash:
32
35
  #
33
- # @consumer=OAuth::Consumer.new( {
34
- # :consumer_key=>"key",
35
- # :consumer_secret=>"secret",
36
+ # @consumer=OAuth::Consumer.new( key,secret,{
36
37
  # :site=>"http://term.ie",
37
- # :auth_method=>:authorize,
38
+ # :scheme=>:header,
38
39
  # :http_method=>:post,
39
40
  # :request_token_path=>"/oauth/example/request_token.php",
40
41
  # :access_token_path=>"/oauth/example/access_token.php",
@@ -43,81 +44,149 @@ module OAuth
43
44
  #
44
45
  # Start the process by requesting a token
45
46
  #
46
- # @request_token=@consumer.request_token
47
+ # @request_token=@consumer.get_request_token
47
48
  # session[:request_token]=@request_token
48
49
  # redirect_to @request_token.authorize_url
49
50
  #
50
51
  # When user returns create an access_token
51
52
  #
52
- # @access_token=@request_token.access_token
53
- # @photos=@access_token.get('http://test.com/photos.xml')
53
+ # @access_token=@request_token.get_access_token
54
+ # @photos=@access_token.get('/photos.xml')
54
55
  #
55
56
  #
56
57
 
57
- def initialize(params)
58
+ def initialize(consumer_key,consumer_secret,options={})
58
59
  # ensure that keys are symbols
59
- @params=@@default_params.merge( params.inject({}) do |options, (key, value)|
60
+ @options=@@default_options.merge( options.inject({}) do |options, (key, value)|
60
61
  options[key.to_sym] = value
61
62
  options
62
63
  end)
63
- super @params[:consumer_key],@params[:consumer_secret]
64
- @site=@params[:site]
65
- raise ArgumentError, 'Missing site URI' unless @site
64
+ @key = consumer_key
65
+ @secret = consumer_secret
66
66
  end
67
67
 
68
68
  def http_method
69
- @http_method||=@params[:http_method]||:post
69
+ @http_method||=@options[:http_method]||:post
70
+ end
71
+
72
+ def http
73
+ @http ||= Net::HTTP.new(uri.host, uri.port)
74
+ end
75
+
76
+ # will change
77
+ def uri(url=nil)
78
+ @uri||=URI.parse(url||site)
70
79
  end
71
80
 
72
81
  # Get a Request Token
73
82
  def get_request_token
74
- request=create_request(http_method,request_token_path)
75
- response=request.perform_token_request(self.secret)
83
+ response=token_request(http_method,request_token_path)
76
84
  OAuth::RequestToken.new(self,response[:oauth_token],response[:oauth_token_secret])
77
85
  end
78
86
 
79
- def create_request(http_method,path, oauth_params={},*arguments)
80
- OAuth::Request.new(http_method,site,path,oauth_params.merge({
81
- :oauth_consumer_key=>self.key,
82
- :realm=>authorize_url,
83
- :oauth_signature_method=>params[:oauth_signature_method],
84
- :oauth_version=>params[:oauth_version],
85
- :auth_method=>auth_method
86
- }),*arguments)
87
+ # Creates, signs and performs an http request.
88
+ # It's recommended to use the Token classes to set this up correctly.
89
+ # The arguments parameters are a hash or string encoded set of parameters if it's a post request as well as optional http headers.
90
+ #
91
+ # @consumer.request(:get,'/people',@token,{:scheme=>:query_string})
92
+ # @consumer.request(:post,'/people',@token,{},@person.to_xml,{ 'Content-Type' => 'application/xml' })
93
+ #
94
+ def request(http_method,path, token=nil,request_options={},*arguments)
95
+ http.request(create_signed_request(http_method,path,token,request_options,*arguments))
96
+ end
97
+
98
+ # Creates and signs an http request.
99
+ # It's recommended to use the Token classes to set this up correctly
100
+ def create_signed_request(http_method,path, token=nil,request_options={},*arguments)
101
+ request=create_http_request(http_method,path,*arguments)
102
+ sign!(request,token,request_options)
103
+ request
104
+ end
105
+
106
+ # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
107
+ def token_request(http_method,path,token=nil,request_options={},*arguments)
108
+ response=request(http_method,path,token,request_options,*arguments)
109
+ if response.code=="200"
110
+ CGI.parse(response.body).inject({}){|h,(k,v)| h[k.to_sym]=v.first;h}
111
+ else
112
+ response.error!
113
+ end
87
114
  end
88
115
 
89
- def signed_request(http_method, path, oauth_params={},token_secret=nil,*arguments)
90
- request=create_request(http_method,path,oauth_params,*arguments)
91
- request.sign(self.secret,token_secret)
92
- request
116
+ # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
117
+ def sign!(request,token=nil, request_options = {})
118
+ request.oauth!(http,self,token,{:scheme=>scheme}.merge(request_options))
93
119
  end
94
120
 
95
- def auth_method
96
- @params[:auth_method]
121
+ # Return the signature_base_string
122
+ def signature_base_string(request,token=nil, request_options = {})
123
+ request.signature_base_string(http,self,token,{:scheme=>scheme}.merge(request_options))
124
+ end
125
+
126
+ def site
127
+ @options[:site]
128
+ end
129
+
130
+ def scheme
131
+ @options[:scheme]
97
132
  end
98
133
 
99
134
  def request_token_path
100
- @params[:request_token_path]
135
+ @options[:request_token_path]
101
136
  end
102
137
 
103
138
  def authorize_path
104
- @params[:authorize_path]
139
+ @options[:authorize_path]
105
140
  end
106
141
 
107
142
  def access_token_path
108
- @params[:access_token_path]
143
+ @options[:access_token_path]
109
144
  end
110
-
145
+
146
+ # TODO this is ugly, rewrite
111
147
  def request_token_url
112
- site+request_token_path
148
+ @options[:request_token_url]||site+request_token_path
113
149
  end
114
150
 
115
151
  def authorize_url
116
- site+authorize_path
152
+ @options[:authorize_url]||site+authorize_path
117
153
  end
118
154
 
119
155
  def access_token_url
120
- site+access_token_path
156
+ @options[:access_token_url]||site+access_token_path
121
157
  end
158
+
159
+ protected
160
+
161
+ # create the http request object for a given http_method and path
162
+ def create_http_request(http_method,path,*arguments)
163
+ http_method=http_method.to_sym
164
+ if [:post,:put].include?(http_method)
165
+ data=arguments.shift
166
+ end
167
+ headers=(arguments.first.is_a?(Hash) ? arguments.shift : {})
168
+ case http_method
169
+ when :post
170
+ request=Net::HTTP::Post.new(path,headers)
171
+ when :put
172
+ request=Net::HTTP::Put.new(path,headers)
173
+ when :get
174
+ request=Net::HTTP::Get.new(path,headers)
175
+ when :delete
176
+ request=Net::HTTP::Delete.new(path,headers)
177
+ when :head
178
+ request=Net::HTTP::Head.new(path,headers)
179
+ else
180
+ raise ArgumentError, "Don't know how to handle http_method: :#{http_method.to_s}"
181
+ end
182
+ if data.is_a?(Hash)
183
+ request.set_form_data(data)
184
+ elsif data
185
+ request.body=data.to_s
186
+ end
187
+ request
188
+ end
189
+
190
+
122
191
  end
123
192
  end