houston-oauth-plugin 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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