motionbox-oauth 0.4.5

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.
Files changed (88) hide show
  1. data/.gemtest +0 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +46 -0
  4. data/HISTORY +160 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +75 -0
  7. data/Rakefile +37 -0
  8. data/TODO +32 -0
  9. data/bin/oauth +5 -0
  10. data/examples/yql.rb +44 -0
  11. data/lib/digest/hmac.rb +104 -0
  12. data/lib/oauth.rb +13 -0
  13. data/lib/oauth/cli.rb +378 -0
  14. data/lib/oauth/client.rb +4 -0
  15. data/lib/oauth/client/action_controller_request.rb +65 -0
  16. data/lib/oauth/client/em_http.rb +124 -0
  17. data/lib/oauth/client/helper.rb +91 -0
  18. data/lib/oauth/client/net_http.rb +120 -0
  19. data/lib/oauth/consumer.rb +382 -0
  20. data/lib/oauth/core_ext.rb +31 -0
  21. data/lib/oauth/errors.rb +3 -0
  22. data/lib/oauth/errors/error.rb +4 -0
  23. data/lib/oauth/errors/problem.rb +14 -0
  24. data/lib/oauth/errors/unauthorized.rb +12 -0
  25. data/lib/oauth/helper.rb +88 -0
  26. data/lib/oauth/oauth.rb +13 -0
  27. data/lib/oauth/oauth_test_helper.rb +25 -0
  28. data/lib/oauth/request_proxy.rb +24 -0
  29. data/lib/oauth/request_proxy/action_controller_request.rb +62 -0
  30. data/lib/oauth/request_proxy/base.rb +174 -0
  31. data/lib/oauth/request_proxy/curb_request.rb +55 -0
  32. data/lib/oauth/request_proxy/em_http_request.rb +74 -0
  33. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  34. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  35. data/lib/oauth/request_proxy/net_http.rb +72 -0
  36. data/lib/oauth/request_proxy/rack_request.rb +44 -0
  37. data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
  38. data/lib/oauth/server.rb +66 -0
  39. data/lib/oauth/signature.rb +45 -0
  40. data/lib/oauth/signature/base.rb +110 -0
  41. data/lib/oauth/signature/hmac/base.rb +15 -0
  42. data/lib/oauth/signature/hmac/md5.rb +8 -0
  43. data/lib/oauth/signature/hmac/rmd160.rb +8 -0
  44. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  45. data/lib/oauth/signature/hmac/sha2.rb +8 -0
  46. data/lib/oauth/signature/md5.rb +13 -0
  47. data/lib/oauth/signature/plaintext.rb +23 -0
  48. data/lib/oauth/signature/rsa/sha1.rb +46 -0
  49. data/lib/oauth/signature/sha1.rb +13 -0
  50. data/lib/oauth/token.rb +7 -0
  51. data/lib/oauth/tokens/access_token.rb +71 -0
  52. data/lib/oauth/tokens/consumer_token.rb +33 -0
  53. data/lib/oauth/tokens/request_token.rb +32 -0
  54. data/lib/oauth/tokens/server_token.rb +9 -0
  55. data/lib/oauth/tokens/token.rb +17 -0
  56. data/oauth.gemspec +150 -0
  57. data/tasks/deployment.rake +34 -0
  58. data/tasks/environment.rake +7 -0
  59. data/tasks/website.rake +17 -0
  60. data/test/cases/oauth_case.rb +19 -0
  61. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  62. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  63. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  64. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  65. data/test/integration/consumer_test.rb +307 -0
  66. data/test/keys/rsa.cert +11 -0
  67. data/test/keys/rsa.pem +16 -0
  68. data/test/test_access_token.rb +26 -0
  69. data/test/test_action_controller_request_proxy.rb +133 -0
  70. data/test/test_consumer.rb +171 -0
  71. data/test/test_curb_request_proxy.rb +77 -0
  72. data/test/test_em_http_client.rb +80 -0
  73. data/test/test_em_http_request_proxy.rb +115 -0
  74. data/test/test_helper.rb +26 -0
  75. data/test/test_hmac_sha1.rb +20 -0
  76. data/test/test_net_http_client.rb +280 -0
  77. data/test/test_net_http_request_proxy.rb +72 -0
  78. data/test/test_oauth_helper.rb +71 -0
  79. data/test/test_rack_request_proxy.rb +40 -0
  80. data/test/test_request_token.rb +51 -0
  81. data/test/test_rsa_sha1.rb +59 -0
  82. data/test/test_server.rb +40 -0
  83. data/test/test_signature.rb +22 -0
  84. data/test/test_signature_base.rb +32 -0
  85. data/test/test_signature_plain_text.rb +31 -0
  86. data/test/test_token.rb +14 -0
  87. data/test/test_typhoeus_request_proxy.rb +80 -0
  88. metadata +284 -0
@@ -0,0 +1,31 @@
1
+ # these are to backport methods from 1.8.7/1.9.1 to 1.8.6
2
+
3
+ class Object
4
+
5
+ unless method_defined?(:tap)
6
+ def tap
7
+ yield self
8
+ self
9
+ end
10
+ end
11
+
12
+ end
13
+
14
+ class String
15
+
16
+
17
+
18
+ unless method_defined?(:bytesize)
19
+ def bytesize
20
+ self.size
21
+ end
22
+ end
23
+
24
+ unless method_defined?(:bytes)
25
+ def bytes
26
+ require 'enumerator'
27
+ Enumerable::Enumerator.new(self, :each_byte)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,3 @@
1
+ require 'oauth/errors/error'
2
+ require 'oauth/errors/unauthorized'
3
+ require 'oauth/errors/problem'
@@ -0,0 +1,4 @@
1
+ module OAuth
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ module OAuth
2
+ class Problem < OAuth::Unauthorized
3
+ attr_reader :problem, :params
4
+ def initialize(problem, request = nil, params = {})
5
+ super(request)
6
+ @problem = problem
7
+ @params = params
8
+ end
9
+
10
+ def to_s
11
+ problem
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module OAuth
2
+ class Unauthorized < OAuth::Error
3
+ attr_reader :request
4
+ def initialize(request = nil)
5
+ @request = request
6
+ end
7
+
8
+ def to_s
9
+ [request.code, request.message] * " "
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,88 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ module OAuth
5
+ module Helper
6
+ extend self
7
+
8
+ # Escape +value+ by URL encoding all non-reserved character.
9
+ #
10
+ # See Also: {OAuth core spec version 1.0, section 5.1}[http://oauth.net/core/1.0#rfc.section.5.1]
11
+ def escape(value)
12
+ URI::escape(value.to_s, OAuth::RESERVED_CHARACTERS)
13
+ rescue ArgumentError
14
+ URI::escape(value.to_s.force_encoding(Encoding::UTF_8), OAuth::RESERVED_CHARACTERS)
15
+ end
16
+
17
+ # Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
18
+ # characters removed.
19
+ def generate_key(size=32)
20
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
21
+ end
22
+
23
+ alias_method :generate_nonce, :generate_key
24
+
25
+ def generate_timestamp #:nodoc:
26
+ Time.now.to_i.to_s
27
+ end
28
+
29
+ # Normalize a +Hash+ of parameter values. Parameters are sorted by name, using lexicographical
30
+ # byte value ordering. If two or more parameters share the same name, they are sorted by their value.
31
+ # Parameters are concatenated in their sorted order into a single string. For each parameter, the name
32
+ # is separated from the corresponding value by an "=" character, even if the value is empty. Each
33
+ # name-value pair is separated by an "&" character.
34
+ #
35
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
36
+ def normalize(params)
37
+ params.sort.map do |k, values|
38
+
39
+ if values.is_a?(Array)
40
+ # multiple values were provided for a single key
41
+ values.sort.collect do |v|
42
+ [escape(k),escape(v)] * "="
43
+ end
44
+ else
45
+ [escape(k),escape(values)] * "="
46
+ end
47
+ end * "&"
48
+ end
49
+
50
+ # Parse an Authorization / WWW-Authenticate header into a hash. Takes care of unescaping and
51
+ # removing surrounding quotes. Raises a OAuth::Problem if the header is not parsable into a
52
+ # valid hash. Does not validate the keys or values.
53
+ #
54
+ # hash = parse_header(headers['Authorization'] || headers['WWW-Authenticate'])
55
+ # hash['oauth_timestamp']
56
+ # #=>"1234567890"
57
+ #
58
+ def parse_header(header)
59
+ # decompose
60
+ params = header[6,header.length].split(/[,=&]/)
61
+
62
+ # odd number of arguments - must be a malformed header.
63
+ raise OAuth::Problem.new("Invalid authorization header") if params.size % 2 != 0
64
+
65
+ params.map! do |v|
66
+ # strip and unescape
67
+ val = unescape(v.strip)
68
+ # strip quotes
69
+ val.sub(/^\"(.*)\"$/, '\1')
70
+ end
71
+
72
+ # convert into a Hash
73
+ Hash[*params.flatten]
74
+ end
75
+
76
+ def unescape(value)
77
+ URI.unescape(value.gsub('+', '%2B'))
78
+ end
79
+
80
+ def stringify_keys(hash)
81
+ new_h = {}
82
+ hash.each do |k, v|
83
+ new_h[k.to_s] = v.is_a?(Hash) ? stringify_keys(v) : v
84
+ end
85
+ new_h
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,13 @@
1
+ module OAuth
2
+ # request tokens are passed between the consumer and the provider out of
3
+ # band (i.e. callbacks cannot be used), per section 6.1.1
4
+ OUT_OF_BAND = "oob"
5
+
6
+ # required parameters, per sections 6.1.1, 6.3.1, and 7
7
+ PARAMETERS = %w(oauth_callback oauth_consumer_key oauth_token
8
+ oauth_signature_method oauth_timestamp oauth_nonce oauth_verifier
9
+ oauth_version oauth_signature oauth_body_hash)
10
+
11
+ # reserved character regexp, per section 5.1
12
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
13
+ end
@@ -0,0 +1,25 @@
1
+ require 'action_controller'
2
+ require 'action_controller/test_process'
3
+
4
+ module OAuth
5
+ module OAuthTestHelper
6
+ def mock_incoming_request_with_query(request)
7
+ incoming = ActionController::TestRequest.new(request.to_hash)
8
+ incoming.request_uri = request.path
9
+ incoming.host = request.uri.host
10
+ incoming.env["SERVER_PORT"] = request.uri.port
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.request_uri = request.path
18
+ incoming.host = request.uri.host
19
+ incoming.env["HTTP_AUTHORIZATION"] = request.to_auth_string
20
+ incoming.env["SERVER_PORT"] = request.uri.port
21
+ incoming.env['REQUEST_METHOD'] = request.http_method
22
+ incoming
23
+ end
24
+ end
25
+ 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,62 @@
1
+ require 'active_support'
2
+ require 'action_controller'
3
+ require 'action_controller/request'
4
+ require 'uri'
5
+
6
+ module OAuth::RequestProxy
7
+ class ActionControllerRequest < OAuth::RequestProxy::Base
8
+ proxies(defined?(ActionController::AbstractRequest) ? ActionController::AbstractRequest : ActionController::Request)
9
+
10
+ def method
11
+ request.method.to_s.upcase
12
+ end
13
+
14
+ def uri
15
+ request.url
16
+ end
17
+
18
+ def parameters
19
+ if options[:clobber_request]
20
+ options[:parameters] || {}
21
+ else
22
+ params = request_params.merge(query_params).merge(header_params)
23
+ params.stringify_keys! if params.respond_to?(:stringify_keys!)
24
+ params.merge(options[:parameters] || {})
25
+ end
26
+ end
27
+
28
+ # Override from OAuth::RequestProxy::Base to avoid roundtrip
29
+ # conversion to Hash or Array and thus preserve the original
30
+ # parameter names
31
+ def parameters_for_signature
32
+ params = []
33
+ params << options[:parameters].to_query if options[:parameters]
34
+
35
+ unless options[:clobber_request]
36
+ params << header_params.to_query
37
+ params << request.query_string unless query_string_blank?
38
+
39
+ if request.post? && request.content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded")
40
+ params << request.raw_post
41
+ end
42
+ end
43
+
44
+ params.
45
+ join('&').split('&').
46
+ reject(&:blank?).
47
+ map { |p| p.split('=').map{|esc| CGI.unescape(esc)} }.
48
+ reject { |kv| kv[0] == 'oauth_signature'}
49
+ end
50
+
51
+ protected
52
+
53
+ def query_params
54
+ request.query_parameters
55
+ end
56
+
57
+ def request_params
58
+ request.request_parameters
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,174 @@
1
+ require 'oauth/request_proxy'
2
+ require 'oauth/helper'
3
+
4
+ module OAuth::RequestProxy
5
+ class Base
6
+ include OAuth::Helper
7
+
8
+ def self.proxies(klass)
9
+ OAuth::RequestProxy.available_proxies[klass] = self
10
+ end
11
+
12
+ attr_accessor :request, :options, :unsigned_parameters
13
+
14
+ def initialize(request, options = {})
15
+ @request = request
16
+ @unsigned_parameters = (options[:unsigned_parameters] || []).map {|param| param.to_s}
17
+ @options = options
18
+ end
19
+
20
+ ## OAuth parameters
21
+
22
+ def oauth_callback
23
+ parameters['oauth_callback']
24
+ end
25
+
26
+ def oauth_consumer_key
27
+ parameters['oauth_consumer_key']
28
+ end
29
+
30
+ def oauth_nonce
31
+ parameters['oauth_nonce']
32
+ end
33
+
34
+ def oauth_signature
35
+ # TODO can this be nil?
36
+ [parameters['oauth_signature']].flatten.first || ""
37
+ end
38
+
39
+ def oauth_signature_method
40
+ case parameters['oauth_signature_method']
41
+ when Array
42
+ parameters['oauth_signature_method'].first
43
+ else
44
+ parameters['oauth_signature_method']
45
+ end
46
+ end
47
+
48
+ def oauth_timestamp
49
+ parameters['oauth_timestamp']
50
+ end
51
+
52
+ def oauth_token
53
+ parameters['oauth_token']
54
+ end
55
+
56
+ def oauth_verifier
57
+ parameters['oauth_verifier']
58
+ end
59
+
60
+ def oauth_version
61
+ parameters["oauth_version"]
62
+ end
63
+
64
+ # TODO deprecate these
65
+ alias_method :consumer_key, :oauth_consumer_key
66
+ alias_method :token, :oauth_token
67
+ alias_method :nonce, :oauth_nonce
68
+ alias_method :timestamp, :oauth_timestamp
69
+ alias_method :signature, :oauth_signature
70
+ alias_method :signature_method, :oauth_signature_method
71
+
72
+ ## Parameter accessors
73
+
74
+ def parameters
75
+ raise NotImplementedError, "Must be implemented by subclasses"
76
+ end
77
+
78
+ def parameters_for_signature
79
+ parameters.reject { |k,v| k == "oauth_signature" || unsigned_parameters.include?(k)}
80
+ end
81
+
82
+ def oauth_parameters
83
+ parameters.select { |k,v| OAuth::PARAMETERS.include?(k) }.reject { |k,v| v == "" }
84
+ end
85
+
86
+ def non_oauth_parameters
87
+ parameters.reject { |k,v| OAuth::PARAMETERS.include?(k) }
88
+ end
89
+
90
+ # See 9.1.2 in specs
91
+ def normalized_uri
92
+ u = URI.parse(uri)
93
+ "#{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 : '/'}"
94
+ end
95
+
96
+ # See 9.1.1. in specs Normalize Request Parameters
97
+ def normalized_parameters
98
+ normalize(parameters_for_signature)
99
+ end
100
+
101
+ def sign(options = {})
102
+ OAuth::Signature.sign(self, options)
103
+ end
104
+
105
+ def sign!(options = {})
106
+ parameters["oauth_signature"] = sign(options)
107
+ @signed = true
108
+ signature
109
+ end
110
+
111
+ # See 9.1 in specs
112
+ def signature_base_string
113
+ base = [method, normalized_uri, normalized_parameters]
114
+ base.map { |v| escape(v) }.join("&")
115
+ end
116
+
117
+ # Has this request been signed yet?
118
+ def signed?
119
+ @signed
120
+ end
121
+
122
+ # URI, including OAuth parameters
123
+ def signed_uri(with_oauth = true)
124
+ if signed?
125
+ if with_oauth
126
+ params = parameters
127
+ else
128
+ params = non_oauth_parameters
129
+ end
130
+
131
+ [uri, normalize(params)] * "?"
132
+ else
133
+ STDERR.puts "This request has not yet been signed!"
134
+ end
135
+ end
136
+
137
+ # Authorization header for OAuth
138
+ def oauth_header(options = {})
139
+ header_params_str = oauth_parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
140
+
141
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
142
+ "OAuth #{realm}#{header_params_str}"
143
+ end
144
+
145
+ def query_string_blank?
146
+ if uri = request.request_uri
147
+ uri.split('?', 2)[1].nil?
148
+ else
149
+ request.query_string.blank?
150
+ end
151
+ end
152
+
153
+ protected
154
+
155
+ def header_params
156
+ %w( X-HTTP_AUTHORIZATION Authorization HTTP_AUTHORIZATION ).each do |header|
157
+ next unless request.env.include?(header)
158
+
159
+ header = request.env[header]
160
+ next unless header[0,6] == 'OAuth '
161
+
162
+ # parse the header into a Hash
163
+ oauth_params = OAuth::Helper.parse_header(header)
164
+
165
+ # remove non-OAuth parameters
166
+ oauth_params.reject! { |k,v| k !~ /^oauth_/ }
167
+
168
+ return oauth_params
169
+ end
170
+
171
+ return {}
172
+ end
173
+ end
174
+ end