typhoauth 0.3.6.1

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 (87) hide show
  1. data/History.txt +106 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +84 -0
  4. data/README.rdoc +78 -0
  5. data/Rakefile +36 -0
  6. data/TODO +31 -0
  7. data/bin/oauth +5 -0
  8. data/examples/yql.rb +44 -0
  9. data/lib/oauth.rb +4 -0
  10. data/lib/oauth/cli.rb +378 -0
  11. data/lib/oauth/client.rb +4 -0
  12. data/lib/oauth/client/action_controller_request.rb +54 -0
  13. data/lib/oauth/client/helper.rb +83 -0
  14. data/lib/oauth/client/net_http.rb +106 -0
  15. data/lib/oauth/consumer.rb +351 -0
  16. data/lib/oauth/errors.rb +3 -0
  17. data/lib/oauth/errors/error.rb +4 -0
  18. data/lib/oauth/errors/problem.rb +14 -0
  19. data/lib/oauth/errors/unauthorized.rb +12 -0
  20. data/lib/oauth/helper.rb +78 -0
  21. data/lib/oauth/oauth.rb +11 -0
  22. data/lib/oauth/oauth_test_helper.rb +25 -0
  23. data/lib/oauth/request_proxy.rb +24 -0
  24. data/lib/oauth/request_proxy/action_controller_request.rb +61 -0
  25. data/lib/oauth/request_proxy/base.rb +165 -0
  26. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  27. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  28. data/lib/oauth/request_proxy/net_http.rb +65 -0
  29. data/lib/oauth/request_proxy/rack_request.rb +40 -0
  30. data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
  31. data/lib/oauth/server.rb +66 -0
  32. data/lib/oauth/signature.rb +37 -0
  33. data/lib/oauth/signature/base.rb +91 -0
  34. data/lib/oauth/signature/hmac/base.rb +12 -0
  35. data/lib/oauth/signature/hmac/md5.rb +9 -0
  36. data/lib/oauth/signature/hmac/rmd160.rb +9 -0
  37. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  38. data/lib/oauth/signature/hmac/sha2.rb +9 -0
  39. data/lib/oauth/signature/md5.rb +13 -0
  40. data/lib/oauth/signature/plaintext.rb +23 -0
  41. data/lib/oauth/signature/rsa/sha1.rb +45 -0
  42. data/lib/oauth/signature/sha1.rb +13 -0
  43. data/lib/oauth/token.rb +7 -0
  44. data/lib/oauth/tokens/access_token.rb +68 -0
  45. data/lib/oauth/tokens/consumer_token.rb +33 -0
  46. data/lib/oauth/tokens/request_token.rb +32 -0
  47. data/lib/oauth/tokens/server_token.rb +9 -0
  48. data/lib/oauth/tokens/token.rb +17 -0
  49. data/lib/oauth/version.rb +3 -0
  50. data/oauth.gemspec +47 -0
  51. data/script/destroy +14 -0
  52. data/script/generate +14 -0
  53. data/script/txt2html +74 -0
  54. data/setup.rb +1585 -0
  55. data/tasks/deployment.rake +34 -0
  56. data/tasks/environment.rake +7 -0
  57. data/tasks/website.rake +17 -0
  58. data/test/cases/oauth_case.rb +19 -0
  59. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  60. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  61. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  62. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  63. data/test/keys/rsa.cert +11 -0
  64. data/test/keys/rsa.pem +16 -0
  65. data/test/test_access_token.rb +26 -0
  66. data/test/test_action_controller_request_proxy.rb +129 -0
  67. data/test/test_consumer.rb +362 -0
  68. data/test/test_helper.rb +14 -0
  69. data/test/test_hmac_sha1.rb +20 -0
  70. data/test/test_net_http_client.rb +185 -0
  71. data/test/test_net_http_request_proxy.rb +72 -0
  72. data/test/test_oauth_helper.rb +49 -0
  73. data/test/test_rack_request_proxy.rb +40 -0
  74. data/test/test_request_token.rb +51 -0
  75. data/test/test_rsa_sha1.rb +59 -0
  76. data/test/test_server.rb +40 -0
  77. data/test/test_signature.rb +19 -0
  78. data/test/test_signature_base.rb +32 -0
  79. data/test/test_signature_plain_text.rb +31 -0
  80. data/test/test_token.rb +14 -0
  81. data/test/test_typhoeus_request_proxy.rb +72 -0
  82. data/website/index.html +87 -0
  83. data/website/index.txt +73 -0
  84. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  85. data/website/stylesheets/screen.css +138 -0
  86. data/website/template.rhtml +48 -0
  87. metadata +220 -0
@@ -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,78 @@
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
+ end
14
+
15
+ # Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
16
+ # characters removed.
17
+ def generate_key(size=32)
18
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
19
+ end
20
+
21
+ alias_method :generate_nonce, :generate_key
22
+
23
+ def generate_timestamp #:nodoc:
24
+ Time.now.to_i.to_s
25
+ end
26
+
27
+ # Normalize a +Hash+ of parameter values. Parameters are sorted by name, using lexicographical
28
+ # byte value ordering. If two or more parameters share the same name, they are sorted by their value.
29
+ # Parameters are concatenated in their sorted order into a single string. For each parameter, the name
30
+ # is separated from the corresponding value by an "=" character, even if the value is empty. Each
31
+ # name-value pair is separated by an "&" character.
32
+ #
33
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
34
+ def normalize(params)
35
+ params.sort.map do |k, values|
36
+
37
+ if values.is_a?(Array)
38
+ # multiple values were provided for a single key
39
+ values.sort.collect do |v|
40
+ [escape(k),escape(v)] * "="
41
+ end
42
+ else
43
+ [escape(k),escape(values)] * "="
44
+ end
45
+ end * "&"
46
+ end
47
+
48
+ # Parse an Authorization / WWW-Authenticate header into a hash. Takes care of unescaping and
49
+ # removing surrounding quotes. Raises a OAuth::Problem if the header is not parsable into a
50
+ # valid hash. Does not validate the keys or values.
51
+ #
52
+ # hash = parse_header(headers['Authorization'] || headers['WWW-Authenticate'])
53
+ # hash['oauth_timestamp']
54
+ # #=>"1234567890"
55
+ #
56
+ def parse_header(header)
57
+ # decompose
58
+ params = header[6,header.length].split(/[,=]/)
59
+
60
+ # odd number of arguments - must be a malformed header.
61
+ raise OAuth::Problem.new("Invalid authorization header") if params.size % 2 != 0
62
+
63
+ params.map! do |v|
64
+ # strip and unescape
65
+ val = unescape(v.strip)
66
+ # strip quotes
67
+ val.sub(/^\"(.*)\"$/, '\1')
68
+ end
69
+
70
+ # convert into a Hash
71
+ Hash[*params.flatten]
72
+ end
73
+
74
+ def unescape(value)
75
+ URI.unescape(value.gsub('+', '%2B'))
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,11 @@
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 oauth_signature_method oauth_timestamp oauth_nonce oauth_verifier oauth_version oauth_signature)
8
+
9
+ # reserved character regexp, per section 5.1
10
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
11
+ 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,61 @@
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 request.query_string.blank?
38
+ if request.post? && request.content_type == Mime::Type.lookup("application/x-www-form-urlencoded")
39
+ params << request.raw_post
40
+ end
41
+ end
42
+
43
+ params.
44
+ join('&').split('&').
45
+ reject(&:blank?).
46
+ map { |p| p.split('=').map{|esc| CGI.unescape(esc)} }.
47
+ reject { |kv| kv[0] == 'oauth_signature'}
48
+ end
49
+
50
+ protected
51
+
52
+ def query_params
53
+ request.query_parameters
54
+ end
55
+
56
+ def request_params
57
+ request.request_parameters
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,165 @@
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
13
+
14
+ def initialize(request, options = {})
15
+ @request = request
16
+ @options = options
17
+ end
18
+
19
+ ## OAuth parameters
20
+
21
+ def oauth_callback
22
+ parameters['oauth_callback']
23
+ end
24
+
25
+ def oauth_consumer_key
26
+ parameters['oauth_consumer_key']
27
+ end
28
+
29
+ def oauth_nonce
30
+ parameters['oauth_nonce']
31
+ end
32
+
33
+ def oauth_signature
34
+ # TODO can this be nil?
35
+ parameters['oauth_signature'] || ""
36
+ end
37
+
38
+ def oauth_signature_method
39
+ case parameters['oauth_signature_method']
40
+ when Array
41
+ parameters['oauth_signature_method'].first
42
+ else
43
+ parameters['oauth_signature_method']
44
+ end
45
+ end
46
+
47
+ def oauth_timestamp
48
+ parameters['oauth_timestamp']
49
+ end
50
+
51
+ def oauth_token
52
+ parameters['oauth_token']
53
+ end
54
+
55
+ def oauth_verifier
56
+ parameters['oauth_verifier']
57
+ end
58
+
59
+ def oauth_version
60
+ parameters["oauth_version"]
61
+ end
62
+
63
+ # TODO deprecate these
64
+ alias_method :consumer_key, :oauth_consumer_key
65
+ alias_method :token, :oauth_token
66
+ alias_method :nonce, :oauth_nonce
67
+ alias_method :timestamp, :oauth_timestamp
68
+ alias_method :signature, :oauth_signature
69
+ alias_method :signature_method, :oauth_signature_method
70
+
71
+ ## Parameter accessors
72
+
73
+ def parameters
74
+ raise NotImplementedError, "Must be implemented by subclasses"
75
+ end
76
+
77
+ def parameters_for_signature
78
+ parameters.reject { |k,v| k == "oauth_signature" }
79
+ end
80
+
81
+ def oauth_parameters
82
+ parameters.select { |k,v| OAuth::PARAMETERS.include?(k) }.reject { |k,v| v == "" }
83
+ end
84
+
85
+ def non_oauth_parameters
86
+ parameters.reject { |k,v| OAuth::PARAMETERS.include?(k) }
87
+ end
88
+
89
+ # See 9.1.2 in specs
90
+ def normalized_uri
91
+ u = URI.parse(uri)
92
+ "#{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 : '/'}"
93
+ end
94
+
95
+ # See 9.1.1. in specs Normalize Request Parameters
96
+ def normalized_parameters
97
+ normalize(parameters_for_signature)
98
+ end
99
+
100
+ def sign(options = {})
101
+ OAuth::Signature.sign(self, options)
102
+ end
103
+
104
+ def sign!(options = {})
105
+ parameters["oauth_signature"] = sign(options)
106
+ @signed = true
107
+ signature
108
+ end
109
+
110
+ # See 9.1 in specs
111
+ def signature_base_string
112
+ base = [method, normalized_uri, normalized_parameters]
113
+ base.map { |v| escape(v) }.join("&")
114
+ end
115
+
116
+ # Has this request been signed yet?
117
+ def signed?
118
+ @signed
119
+ end
120
+
121
+ # URI, including OAuth parameters
122
+ def signed_uri(with_oauth = true)
123
+ if signed?
124
+ if with_oauth
125
+ params = parameters
126
+ else
127
+ params = non_oauth_parameters
128
+ end
129
+
130
+ [uri, normalize(params)] * "?"
131
+ else
132
+ STDERR.puts "This request has not yet been signed!"
133
+ end
134
+ end
135
+
136
+ # Authorization header for OAuth
137
+ def oauth_header(options = {})
138
+ header_params_str = oauth_parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
139
+
140
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
141
+ "OAuth #{realm}#{header_params_str}"
142
+ end
143
+
144
+ protected
145
+
146
+ def header_params
147
+ %w( X-HTTP_AUTHORIZATION Authorization HTTP_AUTHORIZATION ).each do |header|
148
+ next unless request.env.include?(header)
149
+
150
+ header = request.env[header]
151
+ next unless header[0,6] == 'OAuth '
152
+
153
+ # parse the header into a Hash
154
+ oauth_params = OAuth::Helper.parse_header(header)
155
+
156
+ # remove non-OAuth parameters
157
+ oauth_params.reject! { |k,v| k !~ /^oauth_/ }
158
+
159
+ return oauth_params
160
+ end
161
+
162
+ return {}
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,41 @@
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
+ end
40
+ end
41
+ end