gregwebs-oauth 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 (85) hide show
  1. data/History.txt +102 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +84 -0
  4. data/README.rdoc +71 -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 +85 -0
  14. data/lib/oauth/client/net_http.rb +103 -0
  15. data/lib/oauth/consumer.rb +354 -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 +166 -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 +68 -0
  29. data/lib/oauth/request_proxy/rack_request.rb +40 -0
  30. data/lib/oauth/server.rb +66 -0
  31. data/lib/oauth/signature.rb +40 -0
  32. data/lib/oauth/signature/base.rb +91 -0
  33. data/lib/oauth/signature/hmac/base.rb +12 -0
  34. data/lib/oauth/signature/hmac/md5.rb +9 -0
  35. data/lib/oauth/signature/hmac/rmd160.rb +9 -0
  36. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  37. data/lib/oauth/signature/hmac/sha2.rb +9 -0
  38. data/lib/oauth/signature/md5.rb +13 -0
  39. data/lib/oauth/signature/plaintext.rb +23 -0
  40. data/lib/oauth/signature/rsa/sha1.rb +45 -0
  41. data/lib/oauth/signature/sha1.rb +13 -0
  42. data/lib/oauth/token.rb +7 -0
  43. data/lib/oauth/tokens/access_token.rb +68 -0
  44. data/lib/oauth/tokens/consumer_token.rb +33 -0
  45. data/lib/oauth/tokens/request_token.rb +32 -0
  46. data/lib/oauth/tokens/server_token.rb +9 -0
  47. data/lib/oauth/tokens/token.rb +17 -0
  48. data/lib/oauth/version.rb +3 -0
  49. data/oauth.gemspec +49 -0
  50. data/script/destroy +14 -0
  51. data/script/generate +14 -0
  52. data/script/txt2html +74 -0
  53. data/setup.rb +1585 -0
  54. data/tasks/deployment.rake +34 -0
  55. data/tasks/environment.rake +7 -0
  56. data/tasks/website.rake +17 -0
  57. data/test/cases/oauth_case.rb +19 -0
  58. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  59. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  60. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  61. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  62. data/test/keys/rsa.cert +11 -0
  63. data/test/keys/rsa.pem +16 -0
  64. data/test/test_access_token.rb +26 -0
  65. data/test/test_action_controller_request_proxy.rb +129 -0
  66. data/test/test_consumer.rb +362 -0
  67. data/test/test_helper.rb +14 -0
  68. data/test/test_hmac_sha1.rb +20 -0
  69. data/test/test_net_http_client.rb +185 -0
  70. data/test/test_net_http_request_proxy.rb +72 -0
  71. data/test/test_oauth_helper.rb +49 -0
  72. data/test/test_rack_request_proxy.rb +40 -0
  73. data/test/test_request_token.rb +51 -0
  74. data/test/test_rsa_sha1.rb +59 -0
  75. data/test/test_server.rb +40 -0
  76. data/test/test_signature.rb +19 -0
  77. data/test/test_signature_base.rb +32 -0
  78. data/test/test_signature_plain_text.rb +31 -0
  79. data/test/test_token.rb +14 -0
  80. data/website/index.html +87 -0
  81. data/website/index.txt +73 -0
  82. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  83. data/website/stylesheets/screen.css +138 -0
  84. data/website/template.rhtml +48 -0
  85. metadata +217 -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,166 @@
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'] || ""
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
+ protected
146
+
147
+ def header_params
148
+ %w( X-HTTP_AUTHORIZATION Authorization HTTP_AUTHORIZATION ).each do |header|
149
+ next unless request.env.include?(header)
150
+
151
+ header = request.env[header]
152
+ next unless header[0,6] == 'OAuth '
153
+
154
+ # parse the header into a Hash
155
+ oauth_params = OAuth::Helper.parse_header(header)
156
+
157
+ # remove non-OAuth parameters
158
+ oauth_params.reject! { |k,v| k !~ /^oauth_/ }
159
+
160
+ return oauth_params
161
+ end
162
+
163
+ return {}
164
+ end
165
+ end
166
+ 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