houston-oauth-plugin 0.5.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 (172) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/CHANGELOG +187 -0
  4. data/Gemfile +27 -0
  5. data/Guardfile +8 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.rdoc +542 -0
  8. data/Rakefile +1 -0
  9. data/UPGRADE.rdoc +21 -0
  10. data/generators/oauth_consumer/USAGE +10 -0
  11. data/generators/oauth_consumer/oauth_consumer_generator.rb +52 -0
  12. data/generators/oauth_consumer/templates/consumer_token.rb +11 -0
  13. data/generators/oauth_consumer/templates/controller.rb +27 -0
  14. data/generators/oauth_consumer/templates/index.html.erb +29 -0
  15. data/generators/oauth_consumer/templates/index.html.haml +18 -0
  16. data/generators/oauth_consumer/templates/index.html.slim +15 -0
  17. data/generators/oauth_consumer/templates/migration.rb +23 -0
  18. data/generators/oauth_consumer/templates/oauth_config.rb +73 -0
  19. data/generators/oauth_consumer/templates/show.html.erb +7 -0
  20. data/generators/oauth_consumer/templates/show.html.haml +8 -0
  21. data/generators/oauth_consumer/templates/show.html.slim +8 -0
  22. data/generators/oauth_provider/USAGE +20 -0
  23. data/generators/oauth_provider/lib/insert_routes.rb +67 -0
  24. data/generators/oauth_provider/oauth_provider_generator.rb +127 -0
  25. data/generators/oauth_provider/templates/_form.html.erb +17 -0
  26. data/generators/oauth_provider/templates/_form.html.haml +21 -0
  27. data/generators/oauth_provider/templates/access_token.rb +16 -0
  28. data/generators/oauth_provider/templates/authorize.html.erb +14 -0
  29. data/generators/oauth_provider/templates/authorize.html.haml +16 -0
  30. data/generators/oauth_provider/templates/authorize_failure.html.erb +1 -0
  31. data/generators/oauth_provider/templates/authorize_failure.html.haml +1 -0
  32. data/generators/oauth_provider/templates/authorize_success.html.erb +1 -0
  33. data/generators/oauth_provider/templates/authorize_success.html.haml +1 -0
  34. data/generators/oauth_provider/templates/client_application.rb +57 -0
  35. data/generators/oauth_provider/templates/client_application_spec.rb +29 -0
  36. data/generators/oauth_provider/templates/client_application_test.rb +42 -0
  37. data/generators/oauth_provider/templates/client_applications.yml +23 -0
  38. data/generators/oauth_provider/templates/clients_controller.rb +52 -0
  39. data/generators/oauth_provider/templates/clients_controller_spec.rb +176 -0
  40. data/generators/oauth_provider/templates/clients_controller_test.rb +280 -0
  41. data/generators/oauth_provider/templates/controller.rb +23 -0
  42. data/generators/oauth_provider/templates/edit.html.erb +7 -0
  43. data/generators/oauth_provider/templates/edit.html.haml +4 -0
  44. data/generators/oauth_provider/templates/index.html.erb +43 -0
  45. data/generators/oauth_provider/templates/index.html.haml +39 -0
  46. data/generators/oauth_provider/templates/migration.rb +47 -0
  47. data/generators/oauth_provider/templates/new.html.erb +5 -0
  48. data/generators/oauth_provider/templates/new.html.haml +5 -0
  49. data/generators/oauth_provider/templates/oauth2_authorize.html.erb +16 -0
  50. data/generators/oauth_provider/templates/oauth2_authorize.html.haml +17 -0
  51. data/generators/oauth_provider/templates/oauth2_token.rb +20 -0
  52. data/generators/oauth_provider/templates/oauth2_token_spec.rb +52 -0
  53. data/generators/oauth_provider/templates/oauth2_verifier.rb +35 -0
  54. data/generators/oauth_provider/templates/oauth2_verifier_spec.rb +44 -0
  55. data/generators/oauth_provider/templates/oauth_nonce.rb +13 -0
  56. data/generators/oauth_provider/templates/oauth_nonce_spec.rb +24 -0
  57. data/generators/oauth_provider/templates/oauth_nonce_test.rb +26 -0
  58. data/generators/oauth_provider/templates/oauth_nonces.yml +13 -0
  59. data/generators/oauth_provider/templates/oauth_token.rb +30 -0
  60. data/generators/oauth_provider/templates/oauth_token_spec.rb +309 -0
  61. data/generators/oauth_provider/templates/oauth_token_test.rb +57 -0
  62. data/generators/oauth_provider/templates/oauth_tokens.yml +17 -0
  63. data/generators/oauth_provider/templates/request_token.rb +40 -0
  64. data/generators/oauth_provider/templates/show.html.erb +27 -0
  65. data/generators/oauth_provider/templates/show.html.haml +30 -0
  66. data/init.rb +1 -0
  67. data/install.rb +2 -0
  68. data/lib/generators/active_record/oauth_consumer_generator.rb +33 -0
  69. data/lib/generators/active_record/oauth_consumer_templates/consumer_token.rb +11 -0
  70. data/lib/generators/active_record/oauth_consumer_templates/migration.rb +20 -0
  71. data/lib/generators/active_record/oauth_provider_generator.rb +39 -0
  72. data/lib/generators/active_record/oauth_provider_templates/access_token.rb +16 -0
  73. data/lib/generators/active_record/oauth_provider_templates/client_application.rb +57 -0
  74. data/lib/generators/active_record/oauth_provider_templates/migration.rb +47 -0
  75. data/lib/generators/active_record/oauth_provider_templates/oauth2_token.rb +20 -0
  76. data/lib/generators/active_record/oauth_provider_templates/oauth2_verifier.rb +35 -0
  77. data/lib/generators/active_record/oauth_provider_templates/oauth_nonce.rb +13 -0
  78. data/lib/generators/active_record/oauth_provider_templates/oauth_token.rb +30 -0
  79. data/lib/generators/active_record/oauth_provider_templates/request_token.rb +40 -0
  80. data/lib/generators/erb/oauth_consumer_generator.rb +14 -0
  81. data/lib/generators/erb/oauth_consumer_templates/index.html.erb +29 -0
  82. data/lib/generators/erb/oauth_consumer_templates/show.html.erb +7 -0
  83. data/lib/generators/erb/oauth_provider_generator.rb +23 -0
  84. data/lib/generators/erb/oauth_provider_templates/_form.html.erb +17 -0
  85. data/lib/generators/erb/oauth_provider_templates/authorize.html.erb +14 -0
  86. data/lib/generators/erb/oauth_provider_templates/authorize_failure.html.erb +1 -0
  87. data/lib/generators/erb/oauth_provider_templates/authorize_success.html.erb +1 -0
  88. data/lib/generators/erb/oauth_provider_templates/edit.html.erb +7 -0
  89. data/lib/generators/erb/oauth_provider_templates/index.html.erb +43 -0
  90. data/lib/generators/erb/oauth_provider_templates/new.html.erb +5 -0
  91. data/lib/generators/erb/oauth_provider_templates/oauth2_authorize.html.erb +16 -0
  92. data/lib/generators/erb/oauth_provider_templates/show.html.erb +27 -0
  93. data/lib/generators/haml/oauth_consumer_generator.rb +21 -0
  94. data/lib/generators/haml/oauth_consumer_templates/index.html.haml +18 -0
  95. data/lib/generators/haml/oauth_consumer_templates/show.html.haml +8 -0
  96. data/lib/generators/haml/oauth_provider_generator.rb +28 -0
  97. data/lib/generators/haml/oauth_provider_templates/_form.html.haml +21 -0
  98. data/lib/generators/haml/oauth_provider_templates/authorize.html.haml +16 -0
  99. data/lib/generators/haml/oauth_provider_templates/authorize_failure.html.haml +1 -0
  100. data/lib/generators/haml/oauth_provider_templates/authorize_success.html.haml +1 -0
  101. data/lib/generators/haml/oauth_provider_templates/edit.html.haml +4 -0
  102. data/lib/generators/haml/oauth_provider_templates/index.html.haml +39 -0
  103. data/lib/generators/haml/oauth_provider_templates/new.html.haml +5 -0
  104. data/lib/generators/haml/oauth_provider_templates/oauth2_authorize.html.haml +17 -0
  105. data/lib/generators/haml/oauth_provider_templates/show.html.haml +30 -0
  106. data/lib/generators/mongoid/oauth_consumer_generator.rb +15 -0
  107. data/lib/generators/mongoid/oauth_consumer_templates/consumer_token.rb +41 -0
  108. data/lib/generators/mongoid/oauth_provider_generator.rb +21 -0
  109. data/lib/generators/mongoid/oauth_provider_templates/access_token.rb +16 -0
  110. data/lib/generators/mongoid/oauth_provider_templates/client_application.rb +71 -0
  111. data/lib/generators/mongoid/oauth_provider_templates/oauth2_token.rb +20 -0
  112. data/lib/generators/mongoid/oauth_provider_templates/oauth2_verifier.rb +35 -0
  113. data/lib/generators/mongoid/oauth_provider_templates/oauth_nonce.rb +24 -0
  114. data/lib/generators/mongoid/oauth_provider_templates/oauth_token.rb +44 -0
  115. data/lib/generators/mongoid/oauth_provider_templates/request_token.rb +36 -0
  116. data/lib/generators/oauth_consumer/USAGE +11 -0
  117. data/lib/generators/oauth_consumer/oauth_consumer_generator.rb +31 -0
  118. data/lib/generators/oauth_consumer/templates/controller.rb +59 -0
  119. data/lib/generators/oauth_consumer/templates/oauth_config.rb +68 -0
  120. data/lib/generators/oauth_inflections.rb +6 -0
  121. data/lib/generators/oauth_plugin.rb +0 -0
  122. data/lib/generators/oauth_provider/USAGE +18 -0
  123. data/lib/generators/oauth_provider/oauth_provider_generator.rb +37 -0
  124. data/lib/generators/oauth_provider/templates/clients_controller.rb +52 -0
  125. data/lib/generators/oauth_provider/templates/controller.rb +23 -0
  126. data/lib/generators/rspec/oauth_provider_generator.rb +35 -0
  127. data/lib/generators/rspec/templates/client_application_spec.rb +29 -0
  128. data/lib/generators/rspec/templates/client_applications.yml +23 -0
  129. data/lib/generators/rspec/templates/clients_controller_spec.rb +176 -0
  130. data/lib/generators/rspec/templates/oauth2_token_spec.rb +52 -0
  131. data/lib/generators/rspec/templates/oauth2_verifier_spec.rb +44 -0
  132. data/lib/generators/rspec/templates/oauth_nonce_spec.rb +24 -0
  133. data/lib/generators/rspec/templates/oauth_nonces.yml +13 -0
  134. data/lib/generators/rspec/templates/oauth_token_spec.rb +309 -0
  135. data/lib/generators/rspec/templates/oauth_tokens.yml +17 -0
  136. data/lib/generators/slim/oauth_consumer_generator.rb +21 -0
  137. data/lib/generators/slim/oauth_consumer_templates/index.html.slim +15 -0
  138. data/lib/generators/slim/oauth_consumer_templates/show.html.slim +8 -0
  139. data/lib/generators/test_unit/oauth_provider_generator.rb +33 -0
  140. data/lib/generators/test_unit/templates/client_application_test.rb +42 -0
  141. data/lib/generators/test_unit/templates/client_applications.yml +23 -0
  142. data/lib/generators/test_unit/templates/clients_controller_test.rb +280 -0
  143. data/lib/generators/test_unit/templates/oauth_nonce_test.rb +26 -0
  144. data/lib/generators/test_unit/templates/oauth_nonces.yml +13 -0
  145. data/lib/generators/test_unit/templates/oauth_token_test.rb +57 -0
  146. data/lib/generators/test_unit/templates/oauth_tokens.yml +17 -0
  147. data/lib/oauth-plugin.rb +24 -0
  148. data/lib/oauth-plugin/version.rb +5 -0
  149. data/lib/oauth/controllers/application_controller_methods.rb +140 -0
  150. data/lib/oauth/controllers/consumer_controller.rb +153 -0
  151. data/lib/oauth/controllers/provider_controller.rb +181 -0
  152. data/lib/oauth/models/consumers/service_loader.rb +28 -0
  153. data/lib/oauth/models/consumers/services/agree2_token.rb +15 -0
  154. data/lib/oauth/models/consumers/services/fireeagle_token.rb +39 -0
  155. data/lib/oauth/models/consumers/services/google_token.rb +21 -0
  156. data/lib/oauth/models/consumers/services/oauth2_token.rb +49 -0
  157. data/lib/oauth/models/consumers/services/opentransact_token.rb +15 -0
  158. data/lib/oauth/models/consumers/services/picomoney_token.rb +17 -0
  159. data/lib/oauth/models/consumers/services/twitter_token.rb +24 -0
  160. data/lib/oauth/models/consumers/simple_client.rb +50 -0
  161. data/lib/oauth/models/consumers/token.rb +121 -0
  162. data/lib/oauth/provider/authorizer.rb +83 -0
  163. data/lib/oauth/rack/oauth_filter.rb +97 -0
  164. data/oauth-plugin.gemspec +40 -0
  165. data/rails/init.rb +1 -0
  166. data/spec/dummy_provider_models.rb +53 -0
  167. data/spec/oauth/provider/authorizer_spec.rb +202 -0
  168. data/spec/rack/oauth_filter_spec.rb +244 -0
  169. data/spec/spec_helper.rb +3 -0
  170. data/tasks/oauth_tasks.rake +4 -0
  171. data/uninstall.rb +1 -0
  172. metadata +373 -0
@@ -0,0 +1,97 @@
1
+ require "rack"
2
+ require "rack/request"
3
+ require "oauth"
4
+ require "oauth/request_proxy/rack_request"
5
+
6
+ module OAuth
7
+ module Rack
8
+
9
+ # An OAuth 1.0a filter to be used together with the oauth-plugin for rails.T
10
+ # This is still experimental
11
+ #
12
+ # Add it as middleware to your config/application.rb:
13
+ #
14
+ # require 'oauth/rack/oauth_filter'
15
+ # config.middleware.use OAuth::Rack::OAuthFilter
16
+
17
+ class OAuthFilter
18
+ def initialize(app)
19
+ @app = app
20
+ end
21
+
22
+ def call(env)
23
+ request = ::Rack::Request.new(env)
24
+ env["oauth_plugin"] = true
25
+ strategies = []
26
+ if token_string = oauth2_token(request)
27
+ if token = Oauth2Token.where('invalidated_at IS NULL and authorized_at IS NOT NULL and token = ?', token_string).first
28
+ env["oauth.token"] = token
29
+ env["oauth.version"] = 2
30
+ strategies << :oauth20_token
31
+ strategies << :token
32
+ end
33
+
34
+ elsif oauth1_verify(request) do |request_proxy|
35
+ client_application = ClientApplication.find_by_key(request_proxy.consumer_key)
36
+ env["oauth.client_application_candidate"] = client_application
37
+
38
+ oauth_token = nil
39
+
40
+ if client_application
41
+ # Store this temporarily in client_application object for use in request token generation
42
+ client_application.token_callback_url = request_proxy.oauth_callback if request_proxy.oauth_callback
43
+
44
+ if request_proxy.token
45
+ oauth_token = client_application.tokens.where('invalidated_at IS NULL AND authorized_at IS NOT NULL and token = ?', request_proxy.token).first
46
+ if oauth_token.respond_to?(:provided_oauth_verifier=)
47
+ oauth_token.provided_oauth_verifier = request_proxy.oauth_verifier
48
+ end
49
+ env["oauth.token_candidate"] = oauth_token
50
+ end
51
+ end
52
+
53
+ # return the token secret and the consumer secret
54
+ [(oauth_token.nil? ? nil : oauth_token.secret), (client_application.nil? ? nil : client_application.secret)]
55
+ end
56
+ if env["oauth.token_candidate"]
57
+ env["oauth.token"] = env["oauth.token_candidate"]
58
+ strategies << :oauth10_token
59
+ if env["oauth.token"].is_a?(::RequestToken)
60
+ strategies << :oauth10_request_token
61
+ elsif env["oauth.token"].is_a?(::AccessToken)
62
+ strategies << :token
63
+ strategies << :oauth10_access_token
64
+ end
65
+ else
66
+ strategies << :two_legged
67
+ end
68
+ env["oauth.client_application"] = env["oauth.client_application_candidate"]
69
+ env["oauth.version"] = 1
70
+
71
+ end
72
+ env["oauth.strategies"] = strategies unless strategies.empty?
73
+ env["oauth.client_application_candidate"] = nil
74
+ env["oauth.token_candidate"] = nil
75
+ @app.call(env)
76
+ end
77
+
78
+ def oauth1_verify(request, options = {}, &block)
79
+ begin
80
+ signature = OAuth::Signature.build(request, options, &block)
81
+ return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
82
+ value = signature.verify
83
+ value
84
+ rescue OAuth::Signature::UnknownSignatureMethod => e
85
+ false
86
+ end
87
+ end
88
+
89
+ def oauth2_token(request)
90
+ request.params['bearer_token'] || request.params['access_token'] || (request.params["oauth_token"] && !request.params["oauth_signature"] ? request.params["oauth_token"] : nil ) ||
91
+ request.env["HTTP_AUTHORIZATION"] &&
92
+ !request.env["HTTP_AUTHORIZATION"][/(oauth_version="1.0")/] &&
93
+ request.env["HTTP_AUTHORIZATION"][/^(Bearer|OAuth|Token) (token=)?([^\s]*)$/, 3]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "oauth-plugin/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{houston-oauth-plugin}
7
+ s.version = Oauth::Plugin::VERSION
8
+
9
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
10
+ s.authors = ["Pelle Braendgaard"]
11
+ s.date = %q{2011-10-20}
12
+ s.description = %q{Rails plugin for implementing an OAuth Provider or Consumer}
13
+ s.license = "MIT"
14
+ s.email = %q{oauth-ruby@googlegroups.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+
22
+ s.homepage = %q{http://github.com/pelle/oauth-plugin}
23
+ s.require_paths = ["lib"]
24
+ s.rubyforge_project = %q{oauth}
25
+ s.rubygems_version = %q{1.3.7}
26
+ s.summary = %q{Ruby on Rails Plugin for OAuth Provider and Consumer}
27
+ s.add_development_dependency "opentransact"
28
+ s.add_development_dependency "rspec", "~> 2.4.0"
29
+ s.add_development_dependency "fakeweb"
30
+ s.add_development_dependency "fuubar"
31
+ s.add_development_dependency "guard-rspec"
32
+ s.add_development_dependency "growl"
33
+ s.add_development_dependency "rack-test"
34
+
35
+ s.add_dependency "multi_json"
36
+ s.add_dependency("oauth", ["~> 0.4.4"])
37
+ s.add_dependency("rack")
38
+ s.add_dependency("oauth2", '>= 0.5.0')
39
+ end
40
+
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'oauth-plugin'
@@ -0,0 +1,53 @@
1
+ # Dummy implementation
2
+ class ClientApplication
3
+ attr_accessor :key
4
+
5
+ def self.find_by_key(key)
6
+ ClientApplication.new(key)
7
+ end
8
+
9
+ def initialize(key)
10
+ @key = key
11
+ end
12
+
13
+ def tokens
14
+ @tokens||=[]
15
+ end
16
+
17
+ def secret
18
+ "secret"
19
+ end
20
+ end
21
+
22
+ class OauthToken
23
+ attr_accessor :token, :refresh_token
24
+
25
+ def self.where(q, p)
26
+ case p
27
+ when "not_authorized", "invalidated"
28
+ []
29
+ else
30
+ [OauthToken.new(p)]
31
+ end
32
+ end
33
+
34
+ def initialize(token)
35
+ @token = token
36
+ end
37
+
38
+ def secret
39
+ "secret"
40
+ end
41
+ end
42
+
43
+ class Oauth2Token < OauthToken ; end
44
+ class Oauth2Verifier < OauthToken ; end
45
+ class AccessToken < OauthToken ; end
46
+ class RequestToken < OauthToken ; end
47
+
48
+ class OauthNonce
49
+ # Always remember
50
+ def self.remember(nonce,timestamp)
51
+ true
52
+ end
53
+ end
@@ -0,0 +1,202 @@
1
+ require 'spec_helper'
2
+ require 'multi_json'
3
+ require 'oauth/provider/authorizer'
4
+ require 'dummy_provider_models'
5
+
6
+ describe OAuth::Provider::Authorizer do
7
+
8
+
9
+ describe "Authorization code" do
10
+
11
+ describe "should issue code" do
12
+
13
+ before(:each) do
14
+ @user = double("user")
15
+ @app = double("app")
16
+ @code = double("code", :token => "secret auth code")
17
+
18
+ ::ClientApplication.should_receive(:find_by_key!).with('client id').and_return(@app)
19
+ end
20
+
21
+ it "should allow" do
22
+ ::Oauth2Verifier.should_receive(:create!).with( :client_application=>@app,
23
+ :user=>@user,
24
+ :callback_url=>'http://mysite.com/callback',
25
+ :scope => 'a b').and_return(@code)
26
+
27
+ @authorizer = OAuth::Provider::Authorizer.new @user, true, :response_type => 'code',
28
+ :scope => "a b",
29
+ :client_id => 'client id',
30
+ :redirect_uri => 'http://mysite.com/callback'
31
+
32
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?code=secret%20auth%20code"
33
+ @authorizer.should be_authorized
34
+
35
+ end
36
+
37
+ it "should include state" do
38
+ ::Oauth2Verifier.should_receive(:create!).with( :client_application=>@app,
39
+ :user=>@user,
40
+ :callback_url=>'http://mysite.com/callback',
41
+ :scope => 'a b').and_return(@code)
42
+
43
+ @authorizer = OAuth::Provider::Authorizer.new @user, true, :response_type => 'code',
44
+ :state => 'customer id',
45
+ :scope => "a b",
46
+ :client_id => 'client id',
47
+ :redirect_uri => 'http://mysite.com/callback'
48
+
49
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?code=secret%20auth%20code&state=customer%20id"
50
+ @authorizer.should be_authorized
51
+
52
+ end
53
+
54
+ it "should allow query string in callback" do
55
+ ::Oauth2Verifier.should_receive(:create!).with( :client_application=>@app,
56
+ :user=>@user,
57
+ :callback_url=>'http://mysite.com/callback?this=one',
58
+ :scope => 'a b').and_return(@code)
59
+
60
+ @authorizer = OAuth::Provider::Authorizer.new @user, true, :response_type => 'code',
61
+ :scope => "a b",
62
+ :client_id => 'client id',
63
+ :redirect_uri => 'http://mysite.com/callback?this=one'
64
+ @authorizer.should be_authorized
65
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?this=one&code=secret%20auth%20code"
66
+ end
67
+ end
68
+
69
+
70
+ end
71
+
72
+ describe "user does not authorize" do
73
+
74
+ it "should send error" do
75
+ @authorizer = OAuth::Provider::Authorizer.new @user, false, :response_type => 'code',
76
+ :scope => "a b",
77
+ :client_id => 'client id',
78
+ :redirect_uri => 'http://mysite.com/callback'
79
+
80
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?error=access_denied"
81
+ @authorizer.should_not be_authorized
82
+
83
+ end
84
+
85
+ it "should send error with state and query params in callback" do
86
+ @authorizer = OAuth::Provider::Authorizer.new @user, false, :response_type => 'code',
87
+ :scope => "a b",
88
+ :client_id => 'client id',
89
+ :redirect_uri=>'http://mysite.com/callback?this=one',
90
+ :state => "my customer"
91
+
92
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?this=one&error=access_denied&state=my%20customer"
93
+ @authorizer.should_not be_authorized
94
+
95
+ end
96
+
97
+ end
98
+
99
+ describe "Implict Grant" do
100
+
101
+ describe "should issue token" do
102
+
103
+ before(:each) do
104
+ @user = double("user")
105
+ @app = double("app")
106
+ @token = double("token", :token => "secret auth code")
107
+
108
+ ::ClientApplication.should_receive(:find_by_key!).with('client id').and_return(@app)
109
+ end
110
+
111
+ it "should allow" do
112
+ ::Oauth2Token.should_receive(:create!).with( :client_application=>@app,
113
+ :user=>@user,
114
+ :callback_url=>'http://mysite.com/callback',
115
+ :scope => 'a b').and_return(@token)
116
+
117
+ @authorizer = OAuth::Provider::Authorizer.new @user, true, :response_type => 'token',
118
+ :scope => "a b",
119
+ :client_id => 'client id',
120
+ :redirect_uri => 'http://mysite.com/callback'
121
+
122
+ @authorizer.redirect_uri.should == "http://mysite.com/callback#access_token=secret%20auth%20code"
123
+ @authorizer.should be_authorized
124
+
125
+ end
126
+
127
+ it "should include state" do
128
+ ::Oauth2Token.should_receive(:create!).with( :client_application=>@app,
129
+ :user=>@user,
130
+ :callback_url=>'http://mysite.com/callback',
131
+ :scope => 'a b').and_return(@token)
132
+
133
+ @authorizer = OAuth::Provider::Authorizer.new @user, true, :response_type => 'token',
134
+ :state => 'customer id',
135
+ :scope => "a b",
136
+ :client_id => 'client id',
137
+ :redirect_uri => 'http://mysite.com/callback'
138
+
139
+ @authorizer.redirect_uri.should == "http://mysite.com/callback#access_token=secret%20auth%20code&state=customer%20id"
140
+ @authorizer.should be_authorized
141
+
142
+ end
143
+
144
+ it "should allow query string in callback" do
145
+ ::Oauth2Token.should_receive(:create!).with( :client_application=>@app,
146
+ :user=>@user,
147
+ :callback_url=>'http://mysite.com/callback?this=one',
148
+ :scope => 'a b').and_return(@token)
149
+
150
+ @authorizer = OAuth::Provider::Authorizer.new @user, true, :response_type => 'token',
151
+ :scope => "a b",
152
+ :client_id => 'client id',
153
+ :redirect_uri => 'http://mysite.com/callback?this=one'
154
+ @authorizer.should be_authorized
155
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?this=one#access_token=secret%20auth%20code"
156
+ end
157
+ end
158
+
159
+
160
+ end
161
+
162
+ describe "user does not authorize" do
163
+
164
+ it "should send error" do
165
+ @authorizer = OAuth::Provider::Authorizer.new @user, false, :response_type => 'token',
166
+ :scope => "a b",
167
+ :client_id => 'client id',
168
+ :redirect_uri => 'http://mysite.com/callback'
169
+
170
+ @authorizer.redirect_uri.should == "http://mysite.com/callback#error=access_denied"
171
+ @authorizer.should_not be_authorized
172
+
173
+ end
174
+
175
+ it "should send error with state and query params in callback" do
176
+ @authorizer = OAuth::Provider::Authorizer.new @user, false, :response_type => 'token',
177
+ :scope => "a b",
178
+ :client_id => 'client id',
179
+ :redirect_uri=>'http://mysite.com/callback?this=one',
180
+ :state => "my customer"
181
+
182
+ @authorizer.redirect_uri.should == "http://mysite.com/callback?this=one#error=access_denied&state=my%20customer"
183
+ @authorizer.should_not be_authorized
184
+
185
+ end
186
+
187
+ end
188
+
189
+ it "should handle unsupported response type" do
190
+ @user = double("user")
191
+
192
+ @authorizer = OAuth::Provider::Authorizer.new @user, false, :response_type => 'my new',
193
+ :scope => "a b",
194
+ :client_id => 'client id',
195
+ :redirect_uri => 'http://mysite.com/callback'
196
+
197
+ @authorizer.redirect_uri.should == "http://mysite.com/callback#error=unsupported_response_type"
198
+ @authorizer.should_not be_authorized
199
+
200
+ end
201
+
202
+ end
@@ -0,0 +1,244 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+ require 'oauth/rack/oauth_filter'
4
+ require 'multi_json'
5
+ require 'forwardable'
6
+ require 'dummy_provider_models'
7
+
8
+ class OAuthEcho
9
+ def call(env)
10
+ response = {}
11
+ response[:oauth_token] = env["oauth.token"].token if env["oauth.token"]
12
+ response[:client_application] = env["oauth.client_application"].key if env["oauth.client_application"]
13
+ response[:oauth_version] = env["oauth.version"] if env["oauth.version"]
14
+ response[:strategies] = env["oauth.strategies"] if env["oauth.strategies"]
15
+ [200, { "Accept" => "application/json" }, [MultiJson.encode(response)]]
16
+ end
17
+ end
18
+
19
+ describe OAuth::Rack::OAuthFilter do
20
+ include Rack::Test::Methods
21
+
22
+ def app
23
+ @app ||= OAuth::Rack::OAuthFilter.new(OAuthEcho.new)
24
+ end
25
+
26
+ it "should pass through without oauth" do
27
+ get '/'
28
+ last_response.should be_ok
29
+ response = MultiJson.decode(last_response.body)
30
+ response.should == {}
31
+ end
32
+
33
+ describe 'OAuth1' do
34
+ describe 'with optional white space' do
35
+ it "should sign with consumer" do
36
+ get '/',{},{"HTTP_AUTHORIZATION"=>'OAuth oauth_consumer_key="my_consumer", oauth_nonce="amrLDyFE2AMztx5fOYDD1OEqWps6Mc2mAR5qyO44Rj8", oauth_signature="KCSg0RUfVFUcyhrgJo580H8ey0c%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1295039581", oauth_version="1.0"'}
37
+ last_response.should be_ok
38
+ response = MultiJson.decode(last_response.body)
39
+ response.should == {"client_application" => "my_consumer", "oauth_version"=>1, "strategies"=>["two_legged"]}
40
+ end
41
+
42
+ it "should sign with oauth 1 access token" do
43
+ client_application = ClientApplication.new "my_consumer"
44
+ ClientApplication.stub!(:find_by_key).and_return(client_application)
45
+ client_application.tokens.stub!(:where).and_return([AccessToken.new("my_token")])
46
+ get '/',{},{"HTTP_AUTHORIZATION"=>'OAuth oauth_consumer_key="my_consumer", oauth_nonce="oiFHXoN0172eigBBUfgaZLdQg7ycGekv8iTdfkCStY", oauth_signature="y35B2DqTWaNlzNX0p4wv%2FJAGzg8%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1295040394", oauth_token="my_token", oauth_version="1.0"'}
47
+ last_response.should be_ok
48
+ response = MultiJson.decode(last_response.body)
49
+ response.should == {"client_application" => "my_consumer", "oauth_token"=>"my_token","oauth_version"=>1, "strategies"=>["oauth10_token","token","oauth10_access_token"]}
50
+ end
51
+
52
+ it "should sign with oauth 1 request token" do
53
+ client_application = ClientApplication.new "my_consumer"
54
+ ClientApplication.stub!(:find_by_key).and_return(client_application)
55
+ client_application.tokens.stub!(:where).and_return([RequestToken.new("my_token")])
56
+ get '/',{},{"HTTP_AUTHORIZATION"=>'OAuth oauth_consumer_key="my_consumer", oauth_nonce="oiFHXoN0172eigBBUfgaZLdQg7ycGekv8iTdfkCStY", oauth_signature="y35B2DqTWaNlzNX0p4wv%2FJAGzg8%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1295040394", oauth_token="my_token", oauth_version="1.0"'}
57
+ last_response.should be_ok
58
+ response = MultiJson.decode(last_response.body)
59
+ response.should == {"client_application" => "my_consumer", "oauth_token"=>"my_token","oauth_version"=>1, "strategies"=>["oauth10_token","oauth10_request_token"]}
60
+ end
61
+ end
62
+
63
+ describe 'without optional white space' do
64
+ it "should sign with consumer" do
65
+ get '/',{},{"HTTP_AUTHORIZATION"=>'OAuth oauth_consumer_key="my_consumer",oauth_nonce="amrLDyFE2AMztx5fOYDD1OEqWps6Mc2mAR5qyO44Rj8",oauth_signature="KCSg0RUfVFUcyhrgJo580H8ey0c%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1295039581",oauth_version="1.0"'}
66
+ last_response.should be_ok
67
+ response = MultiJson.decode(last_response.body)
68
+ response.should == {"client_application" => "my_consumer", "oauth_version"=>1, "strategies"=>["two_legged"]}
69
+ end
70
+
71
+ it "should sign with oauth 1 access token" do
72
+ client_application = ClientApplication.new "my_consumer"
73
+ ClientApplication.stub!(:find_by_key).and_return(client_application)
74
+ client_application.tokens.stub!(:where).and_return([AccessToken.new("my_token")])
75
+ get '/',{},{"HTTP_AUTHORIZATION"=>'OAuth oauth_consumer_key="my_consumer",oauth_nonce="oiFHXoN0172eigBBUfgaZLdQg7ycGekv8iTdfkCStY",oauth_signature="y35B2DqTWaNlzNX0p4wv%2FJAGzg8%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1295040394",oauth_token="my_token",oauth_version="1.0"'}
76
+ last_response.should be_ok
77
+ response = MultiJson.decode(last_response.body)
78
+ response.should == {"client_application" => "my_consumer", "oauth_token"=>"my_token","oauth_version"=>1, "strategies"=>["oauth10_token","token","oauth10_access_token"]}
79
+ end
80
+
81
+ it "should sign with oauth 1 request token" do
82
+ client_application = ClientApplication.new "my_consumer"
83
+ ClientApplication.stub!(:find_by_key).and_return(client_application)
84
+ client_application.tokens.stub!(:where).and_return([RequestToken.new("my_token")])
85
+ get '/',{},{"HTTP_AUTHORIZATION"=>'OAuth oauth_consumer_key="my_consumer",oauth_nonce="oiFHXoN0172eigBBUfgaZLdQg7ycGekv8iTdfkCStY",oauth_signature="y35B2DqTWaNlzNX0p4wv%2FJAGzg8%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1295040394",oauth_token="my_token",oauth_version="1.0"'}
86
+ last_response.should be_ok
87
+ response = MultiJson.decode(last_response.body)
88
+ response.should == {"client_application" => "my_consumer", "oauth_token"=>"my_token","oauth_version"=>1, "strategies"=>["oauth10_token","oauth10_request_token"]}
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "OAuth2" do
94
+ describe "token given through a HTTP Auth Header" do
95
+ context "authorized and non-invalidated token" do
96
+ it "authenticates" do
97
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Bearer valid_token" }
98
+ last_response.should be_ok
99
+ response = MultiJson.decode(last_response.body)
100
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
101
+ end
102
+ end
103
+
104
+ context "non-authorized token" do
105
+ it "doesn't authenticate" do
106
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Bearer not_authorized" }
107
+ last_response.should be_ok
108
+ response = MultiJson.decode(last_response.body)
109
+ response.should == {}
110
+ end
111
+ end
112
+
113
+ context "authorized and invalidated token" do
114
+ it "doesn't authenticate with an invalidated token" do
115
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Bearer invalidated" }
116
+ last_response.should be_ok
117
+ response = MultiJson.decode(last_response.body)
118
+ response.should == {}
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "OAuth2 pre Bearer" do
124
+ describe "token given through a HTTP Auth Header" do
125
+ context "authorized and non-invalidated token" do
126
+ it "authenticates" do
127
+ get '/', {}, { "HTTP_AUTHORIZATION" => "OAuth valid_token" }
128
+ last_response.should be_ok
129
+ response = MultiJson.decode(last_response.body)
130
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
131
+ end
132
+ end
133
+
134
+ context "non-authorized token" do
135
+ it "doesn't authenticate" do
136
+ get '/', {}, { "HTTP_AUTHORIZATION" => "OAuth not_authorized" }
137
+ last_response.should be_ok
138
+ response = MultiJson.decode(last_response.body)
139
+ response.should == {}
140
+ end
141
+ end
142
+
143
+ context "authorized and invalidated token" do
144
+ it "doesn't authenticate with an invalidated token" do
145
+ get '/', {}, { "HTTP_AUTHORIZATION" => "OAuth invalidated" }
146
+ last_response.should be_ok
147
+ response = MultiJson.decode(last_response.body)
148
+ response.should == {}
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "token given through a HTTP Auth Header following the OAuth2 pre draft" do
155
+ context "authorized and non-invalidated token" do
156
+ it "authenticates" do
157
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Token valid_token" }
158
+ last_response.should be_ok
159
+ response = MultiJson.decode(last_response.body)
160
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
161
+ end
162
+ end
163
+
164
+ context "non-authorized token" do
165
+ it "doesn't authenticate" do
166
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Token not_authorized" }
167
+ last_response.should be_ok
168
+ response = MultiJson.decode(last_response.body)
169
+ response.should == {}
170
+ end
171
+ end
172
+
173
+ context "authorized and invalidated token" do
174
+ it "doesn't authenticate with an invalidated token" do
175
+ get '/', {}, { "HTTP_AUTHORIZATION" => "Token invalidated" }
176
+ last_response.should be_ok
177
+ response = MultiJson.decode(last_response.body)
178
+ response.should == {}
179
+ end
180
+ end
181
+ end
182
+
183
+ ['bearer_token', 'access_token', 'oauth_token'].each do |name|
184
+ describe "token given through the query parameter '#{name}'" do
185
+ context "authorized and non-invalidated token" do
186
+ it "authenticates" do
187
+ get "/?#{name}=valid_token"
188
+
189
+ last_response.should be_ok
190
+ response = MultiJson.decode(last_response.body)
191
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
192
+ end
193
+ end
194
+
195
+ context "non-authorized token" do
196
+ it "doesn't authenticate" do
197
+ get "/?#{name}=not_authorized"
198
+ last_response.should be_ok
199
+ response = MultiJson.decode(last_response.body)
200
+ response.should == {}
201
+ end
202
+ end
203
+
204
+ context "authorized and invalidated token" do
205
+ it "doesn't authenticate with an invalidated token" do
206
+ get "/?#{name}=invalidated"
207
+ last_response.should be_ok
208
+ response = MultiJson.decode(last_response.body)
209
+ response.should == {}
210
+ end
211
+ end
212
+ end
213
+
214
+ describe "token given through the post parameter '#{name}'" do
215
+ context "authorized and non-invalidated token" do
216
+ it "authenticates" do
217
+ post '/', name => 'valid_token'
218
+ last_response.should be_ok
219
+ response = MultiJson.decode(last_response.body)
220
+ response.should == { "oauth_token" => "valid_token", "oauth_version" => 2, "strategies"=> ["oauth20_token", "token"] }
221
+ end
222
+ end
223
+
224
+ context "non-authorized token" do
225
+ it "doesn't authenticate" do
226
+ post '/', name => 'not_authorized'
227
+ last_response.should be_ok
228
+ response = MultiJson.decode(last_response.body)
229
+ response.should == {}
230
+ end
231
+ end
232
+
233
+ context "authorized and invalidated token" do
234
+ it "doesn't authenticate with an invalidated token" do
235
+ post '/', name => 'invalidated'
236
+ last_response.should be_ok
237
+ response = MultiJson.decode(last_response.body)
238
+ response.should == {}
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end