oauth-instructure 0.4.8

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 (89) hide show
  1. data/.gemtest +0 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +47 -0
  4. data/HISTORY +174 -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_pack.rb +9 -0
  16. data/lib/oauth/client/em_http.rb +120 -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 +389 -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 +109 -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 +116 -0
  30. data/lib/oauth/request_proxy/action_dispatch_request.rb +113 -0
  31. data/lib/oauth/request_proxy/base.rb +174 -0
  32. data/lib/oauth/request_proxy/curb_request.rb +55 -0
  33. data/lib/oauth/request_proxy/em_http_request.rb +66 -0
  34. data/lib/oauth/request_proxy/jabber_request.rb +41 -0
  35. data/lib/oauth/request_proxy/mock_request.rb +44 -0
  36. data/lib/oauth/request_proxy/net_http.rb +73 -0
  37. data/lib/oauth/request_proxy/rack_request.rb +44 -0
  38. data/lib/oauth/request_proxy/typhoeus_request.rb +53 -0
  39. data/lib/oauth/server.rb +66 -0
  40. data/lib/oauth/signature.rb +45 -0
  41. data/lib/oauth/signature/base.rb +110 -0
  42. data/lib/oauth/signature/hmac/base.rb +15 -0
  43. data/lib/oauth/signature/hmac/md5.rb +8 -0
  44. data/lib/oauth/signature/hmac/rmd160.rb +8 -0
  45. data/lib/oauth/signature/hmac/sha1.rb +9 -0
  46. data/lib/oauth/signature/hmac/sha2.rb +8 -0
  47. data/lib/oauth/signature/md5.rb +13 -0
  48. data/lib/oauth/signature/plaintext.rb +23 -0
  49. data/lib/oauth/signature/rsa/sha1.rb +46 -0
  50. data/lib/oauth/signature/sha1.rb +13 -0
  51. data/lib/oauth/token.rb +7 -0
  52. data/lib/oauth/tokens/access_token.rb +71 -0
  53. data/lib/oauth/tokens/consumer_token.rb +33 -0
  54. data/lib/oauth/tokens/request_token.rb +32 -0
  55. data/lib/oauth/tokens/server_token.rb +9 -0
  56. data/lib/oauth/tokens/token.rb +17 -0
  57. data/oauth.gemspec +148 -0
  58. data/tasks/deployment.rake +34 -0
  59. data/tasks/environment.rake +7 -0
  60. data/tasks/website.rake +17 -0
  61. data/test/cases/oauth_case.rb +19 -0
  62. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  63. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  64. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  65. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  66. data/test/integration/consumer_test.rb +307 -0
  67. data/test/keys/rsa.cert +11 -0
  68. data/test/keys/rsa.pem +16 -0
  69. data/test/test_access_token.rb +26 -0
  70. data/test/test_action_controller_request_proxy.rb +133 -0
  71. data/test/test_consumer.rb +220 -0
  72. data/test/test_curb_request_proxy.rb +77 -0
  73. data/test/test_em_http_client.rb +80 -0
  74. data/test/test_em_http_request_proxy.rb +115 -0
  75. data/test/test_helper.rb +28 -0
  76. data/test/test_hmac_sha1.rb +20 -0
  77. data/test/test_net_http_client.rb +292 -0
  78. data/test/test_net_http_request_proxy.rb +72 -0
  79. data/test/test_oauth_helper.rb +94 -0
  80. data/test/test_rack_request_proxy.rb +40 -0
  81. data/test/test_request_token.rb +51 -0
  82. data/test/test_rsa_sha1.rb +59 -0
  83. data/test/test_server.rb +40 -0
  84. data/test/test_signature.rb +22 -0
  85. data/test/test_signature_base.rb +32 -0
  86. data/test/test_signature_plain_text.rb +31 -0
  87. data/test/test_token.rb +14 -0
  88. data/test/test_typhoeus_request_proxy.rb +80 -0
  89. metadata +274 -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,109 @@
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
+ if values.is_a?(Array)
39
+ # make sure the array has an element so we don't lose the key
40
+ values << nil if values.empty?
41
+ # multiple values were provided for a single key
42
+ values.sort.collect do |v|
43
+ [escape(k),escape(v)] * "="
44
+ end
45
+ elsif values.is_a?(Hash)
46
+ normalize_nested_query(values, k)
47
+ else
48
+ [escape(k),escape(values)] * "="
49
+ end
50
+ end * "&"
51
+ end
52
+
53
+ #Returns a string representation of the Hash like in URL query string
54
+ # build_nested_query({:level_1 => {:level_2 => ['value_1','value_2']}}, 'prefix'))
55
+ # #=> ["prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_1", "prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_2"]
56
+ def normalize_nested_query(value, prefix = nil)
57
+ case value
58
+ when Array
59
+ value.map do |v|
60
+ normalize_nested_query(v, "#{prefix}[]")
61
+ end.flatten.sort
62
+ when Hash
63
+ value.map do |k, v|
64
+ normalize_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
65
+ end.flatten.sort
66
+ else
67
+ [escape(prefix), escape(value)] * "="
68
+ end
69
+ end
70
+
71
+ # Parse an Authorization / WWW-Authenticate header into a hash. Takes care of unescaping and
72
+ # removing surrounding quotes. Raises a OAuth::Problem if the header is not parsable into a
73
+ # valid hash. Does not validate the keys or values.
74
+ #
75
+ # hash = parse_header(headers['Authorization'] || headers['WWW-Authenticate'])
76
+ # hash['oauth_timestamp']
77
+ # #=>"1234567890"
78
+ #
79
+ def parse_header(header)
80
+ # decompose
81
+ params = header[6,header.length].split(/[,=&]/)
82
+
83
+ # odd number of arguments - must be a malformed header.
84
+ raise OAuth::Problem.new("Invalid authorization header") if params.size % 2 != 0
85
+
86
+ params.map! do |v|
87
+ # strip and unescape
88
+ val = unescape(v.strip)
89
+ # strip quotes
90
+ val.sub(/^\"(.*)\"$/, '\1')
91
+ end
92
+
93
+ # convert into a Hash
94
+ Hash[*params.flatten]
95
+ end
96
+
97
+ def unescape(value)
98
+ URI.unescape(value.gsub('+', '%2B'))
99
+ end
100
+
101
+ def stringify_keys(hash)
102
+ new_h = {}
103
+ hash.each do |k, v|
104
+ new_h[k.to_s] = v.is_a?(Hash) ? stringify_keys(v) : v
105
+ end
106
+ new_h
107
+ end
108
+ end
109
+ 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,116 @@
1
+ require 'active_support'
2
+ require 'action_controller'
3
+ if Rails.version < "3.0"
4
+ require 'action_controller/request'
5
+ else
6
+ require 'action_controller/test_case'
7
+ end
8
+ require 'uri'
9
+
10
+ module OAuth::RequestProxy
11
+ class ActionControllerRequest < OAuth::RequestProxy::Base
12
+ proxies(defined?(ActionController::AbstractRequest) ? ActionController::AbstractRequest : ActionController::Request)
13
+
14
+ def method
15
+ request.method.to_s.upcase
16
+ end
17
+
18
+ def uri
19
+ request.url
20
+ end
21
+
22
+ def parameters
23
+ if options[:clobber_request]
24
+ options[:parameters] || {}
25
+ else
26
+ params = request_params.merge(query_params).merge(header_params)
27
+ params.stringify_keys! if params.respond_to?(:stringify_keys!)
28
+ params.merge(options[:parameters] || {})
29
+ end
30
+ end
31
+
32
+ # Override from OAuth::RequestProxy::Base to avoid roundtrip
33
+ # conversion to Hash or Array and thus preserve the original
34
+ # parameter names
35
+ def parameters_for_signature
36
+ params = []
37
+ params << options[:parameters].to_query if options[:parameters]
38
+
39
+ unless options[:clobber_request]
40
+ params << header_params.to_query
41
+ params << request.query_string unless query_string_blank?
42
+
43
+ if request.post? && request.content_type.to_s.downcase.start_with?("application/x-www-form-urlencoded")
44
+ params << request.raw_post
45
+ end
46
+ end
47
+
48
+ params.
49
+ join('&').split('&').
50
+ reject(&:blank?).
51
+ map { |p| p.split('=').map{|esc| CGI.unescape(esc)} }.
52
+ reject { |kv| kv[0] == 'oauth_signature'}
53
+ end
54
+
55
+ protected
56
+
57
+ def query_params
58
+ request.query_parameters
59
+ end
60
+
61
+ def request_params
62
+ request.request_parameters
63
+ end
64
+
65
+ end
66
+ end
67
+
68
+ module ActionController
69
+ class Base
70
+ def process_with_oauth(request, response=nil)
71
+ request.apply_oauth! if request.respond_to?(:apply_oauth!)
72
+ process_without_oauth(request, response)
73
+ end
74
+ alias_method_chain :process, :oauth
75
+ end
76
+
77
+ class TestRequest
78
+ def self.use_oauth=(bool)
79
+ @use_oauth = bool
80
+ end
81
+
82
+ def self.use_oauth?
83
+ @use_oauth
84
+ end
85
+
86
+ def configure_oauth(consumer = nil, token = nil, options = {})
87
+ @oauth_options = { :consumer => consumer,
88
+ :token => token,
89
+ :scheme => 'header',
90
+ :signature_method => nil,
91
+ :nonce => nil,
92
+ :timestamp => nil }.merge(options)
93
+ end
94
+
95
+ def apply_oauth!
96
+ return unless ActionController::TestRequest.use_oauth? && @oauth_options
97
+
98
+ @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge(:request_uri => (respond_to?(:fullpath) ? fullpath : request_uri)))
99
+ @oauth_helper.amend_user_agent_header(env)
100
+
101
+ self.send("set_oauth_#{@oauth_options[:scheme]}")
102
+ end
103
+
104
+ def set_oauth_header
105
+ env['Authorization'] = @oauth_helper.header
106
+ end
107
+
108
+ def set_oauth_parameters
109
+ @query_parameters = @oauth_helper.parameters_with_oauth
110
+ @query_parameters.merge!(:oauth_signature => @oauth_helper.signature)
111
+ end
112
+
113
+ def set_oauth_query_string
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,113 @@
1
+ require 'active_support'
2
+ require 'action_controller'
3
+ require 'uri'
4
+
5
+ module OAuth::RequestProxy
6
+ class ActionDispatchRequest < OAuth::RequestProxy::Base
7
+ proxies ActionDispatch::Request
8
+
9
+ def method
10
+ request.method.to_s.upcase
11
+ end
12
+
13
+ def uri
14
+ request.url
15
+ end
16
+
17
+ def parameters
18
+ if options[:clobber_request]
19
+ options[:parameters] || {}
20
+ else
21
+ params = request_params.merge(query_params).merge(header_params)
22
+ params.stringify_keys! if params.respond_to?(:stringify_keys!)
23
+ params.merge(options[:parameters] || {})
24
+ end
25
+ end
26
+
27
+ # Override from OAuth::RequestProxy::Base to avoid roundtrip
28
+ # conversion to Hash or Array and thus preserve the original
29
+ # parameter names
30
+ def parameters_for_signature
31
+ params = []
32
+ params << options[:parameters].to_query if options[:parameters]
33
+
34
+ unless options[:clobber_request]
35
+ params << header_params.to_query
36
+ params << request.query_string unless request.query_string.blank?
37
+
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
+
62
+ end
63
+
64
+ module ActionController
65
+ class Base
66
+ def process_with_new_base_test(request, response=nil)
67
+ request.apply_oauth! if request.respond_to?(:apply_oauth!)
68
+ super(request, response)
69
+ end
70
+ end
71
+ end
72
+
73
+ module ActionDispatch
74
+ class TestRequest
75
+ def self.use_oauth=(bool)
76
+ @use_oauth = bool
77
+ end
78
+
79
+ def self.use_oauth?
80
+ @use_oauth
81
+ end
82
+
83
+ def configure_oauth(consumer = nil, token = nil, options = {})
84
+ @oauth_options = { :consumer => consumer,
85
+ :token => token,
86
+ :scheme => 'header',
87
+ :signature_method => nil,
88
+ :nonce => nil,
89
+ :timestamp => nil }.merge(options)
90
+ end
91
+
92
+ def apply_oauth!
93
+ return unless ActionDispatch::TestRequest.use_oauth? && @oauth_options
94
+
95
+ @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge(:request_uri => (respond_to?(:fullpath) ? fullpath : request_uri)))
96
+ @oauth_helper.amend_user_agent_header(env)
97
+
98
+ self.send("set_oauth_#{@oauth_options[:scheme]}")
99
+ end
100
+
101
+ def set_oauth_header
102
+ env['Authorization'] = @oauth_helper.header
103
+ end
104
+
105
+ def set_oauth_parameters
106
+ @query_parameters = @oauth_helper.parameters_with_oauth
107
+ @query_parameters.merge!(:oauth_signature => @oauth_helper.signature)
108
+ end
109
+
110
+ def set_oauth_query_string
111
+ end
112
+ end
113
+ end