doorkeeper 0.3.0 → 0.4.0

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 (176) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +98 -0
  5. data/Gemfile +6 -0
  6. data/README.md +42 -6
  7. data/app/controllers/doorkeeper/application_controller.rb +4 -11
  8. data/app/controllers/doorkeeper/applications_controller.rb +7 -1
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +11 -1
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  11. data/app/controllers/doorkeeper/tokens_controller.rb +19 -5
  12. data/app/models/doorkeeper/access_grant.rb +28 -0
  13. data/app/models/doorkeeper/access_token.rb +65 -0
  14. data/app/models/doorkeeper/application.rb +54 -0
  15. data/app/views/doorkeeper/applications/index.html.erb +1 -1
  16. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  17. data/app/views/doorkeeper/authorizations/new.html.erb +15 -15
  18. data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -2
  19. data/config/locales/en.yml +3 -0
  20. data/doorkeeper.gemspec +28 -0
  21. data/gemfiles/gemfile.rails-3.1.x +7 -0
  22. data/gemfiles/gemfile.rails-3.2.x +7 -0
  23. data/lib/doorkeeper/config.rb +73 -12
  24. data/lib/doorkeeper/doorkeeper_for.rb +19 -15
  25. data/lib/doorkeeper/engine.rb +28 -0
  26. data/lib/doorkeeper/models/scopes.rb +13 -0
  27. data/lib/doorkeeper/oauth/access_token_request.rb +9 -20
  28. data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
  29. data/lib/doorkeeper/oauth/authorization/token.rb +2 -2
  30. data/lib/doorkeeper/oauth/authorization_request.rb +18 -23
  31. data/lib/doorkeeper/oauth/client/credentials.rb +21 -0
  32. data/lib/doorkeeper/oauth/client/methods.rb +18 -0
  33. data/lib/doorkeeper/oauth/client.rb +27 -0
  34. data/lib/doorkeeper/oauth/client_credentials/creator.rb +29 -0
  35. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +35 -0
  36. data/lib/doorkeeper/oauth/client_credentials/response.rb +42 -0
  37. data/lib/doorkeeper/oauth/client_credentials/validation.rb +33 -0
  38. data/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
  39. data/lib/doorkeeper/oauth/error.rb +9 -0
  40. data/lib/doorkeeper/oauth/error_response.rb +30 -0
  41. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -2
  42. data/lib/doorkeeper/oauth/password_access_token_request.rb +130 -0
  43. data/lib/doorkeeper/oauth/scopes.rb +60 -0
  44. data/lib/doorkeeper/version.rb +1 -1
  45. data/lib/doorkeeper.rb +23 -3
  46. data/lib/generators/doorkeeper/install_generator.rb +1 -0
  47. data/lib/generators/doorkeeper/templates/initializer.rb +12 -7
  48. data/lib/generators/doorkeeper/templates/migration.rb +1 -1
  49. data/lib/generators/doorkeeper/views_generator.rb +15 -0
  50. data/script/rails +6 -0
  51. data/script/run_all +11 -0
  52. data/spec/controllers/applications_controller_spec.rb +18 -0
  53. data/spec/controllers/authorizations_controller_spec.rb +131 -0
  54. data/spec/controllers/protected_resources_controller_spec.rb +308 -0
  55. data/spec/controllers/tokens_controller_spec.rb +34 -0
  56. data/spec/dummy/Rakefile +7 -0
  57. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  58. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  59. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  60. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  61. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  62. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  63. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  64. data/spec/dummy/app/models/user.rb +11 -0
  65. data/spec/dummy/app/views/home/index.html.erb +0 -0
  66. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  67. data/spec/dummy/config/application.rb +53 -0
  68. data/spec/dummy/config/boot.rb +10 -0
  69. data/spec/dummy/config/database.yml +15 -0
  70. data/spec/dummy/config/environment.rb +5 -0
  71. data/spec/dummy/config/environments/development.rb +30 -0
  72. data/spec/dummy/config/environments/production.rb +60 -0
  73. data/spec/dummy/config/environments/test.rb +39 -0
  74. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  75. data/spec/dummy/config/initializers/doorkeeper.rb +41 -0
  76. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  77. data/spec/dummy/config/initializers/session_store.rb +8 -0
  78. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  79. data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
  80. data/spec/dummy/config/routes.rb +8 -0
  81. data/spec/dummy/config.ru +4 -0
  82. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  83. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
  84. data/spec/dummy/db/migrate/20120524202412_create_doorkeeper_tables.rb +42 -0
  85. data/spec/dummy/db/schema.rb +62 -0
  86. data/spec/dummy/public/404.html +26 -0
  87. data/spec/dummy/public/422.html +26 -0
  88. data/spec/dummy/public/500.html +26 -0
  89. data/spec/dummy/public/favicon.ico +0 -0
  90. data/spec/dummy/script/rails +6 -0
  91. data/spec/factories/access_grant.rb +9 -0
  92. data/spec/factories/access_token.rb +7 -0
  93. data/spec/factories/application.rb +6 -0
  94. data/spec/generators/install_generator_spec.rb +35 -0
  95. data/spec/generators/templates/routes.rb +3 -0
  96. data/spec/generators/views_generator_spec.rb +27 -0
  97. data/spec/lib/config_spec.rb +87 -0
  98. data/spec/lib/models/expirable_spec.rb +49 -0
  99. data/spec/lib/models/revocable_spec.rb +31 -0
  100. data/spec/lib/models/scopes_spec.rb +32 -0
  101. data/spec/lib/oauth/access_token_request_spec.rb +240 -0
  102. data/spec/lib/oauth/authorization/uri_builder_spec.rb +37 -0
  103. data/spec/lib/oauth/authorization_request_spec.rb +286 -0
  104. data/spec/lib/oauth/client/credentials_spec.rb +47 -0
  105. data/spec/lib/oauth/client/methods_spec.rb +54 -0
  106. data/spec/lib/oauth/client_credentials/creator_spec.rb +47 -0
  107. data/spec/lib/oauth/client_credentials/issuer_spec.rb +57 -0
  108. data/spec/lib/oauth/client_credentials/response_spec.rb +58 -0
  109. data/spec/lib/oauth/client_credentials/validation_spec.rb +29 -0
  110. data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
  111. data/spec/lib/oauth/client_credentials_request_spec.rb +60 -0
  112. data/spec/lib/oauth/client_spec.rb +42 -0
  113. data/spec/lib/oauth/error_response_spec.rb +40 -0
  114. data/spec/lib/oauth/error_spec.rb +19 -0
  115. data/spec/lib/oauth/helpers/scope_checker_spec.rb +74 -0
  116. data/spec/lib/oauth/helpers/unique_token_spec.rb +38 -0
  117. data/spec/lib/oauth/helpers/uri_checker_spec.rb +64 -0
  118. data/spec/lib/oauth/password_access_token_request_spec.rb +152 -0
  119. data/spec/lib/oauth/scopes_spec.rb +115 -0
  120. data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
  121. data/spec/models/doorkeeper/access_token_spec.rb +113 -0
  122. data/spec/models/doorkeeper/application_spec.rb +129 -0
  123. data/spec/requests/applications/applications_request_spec.rb +92 -0
  124. data/spec/requests/applications/authorized_applications_spec.rb +30 -0
  125. data/spec/requests/endpoints/authorization_spec.rb +63 -0
  126. data/spec/requests/endpoints/token_spec.rb +29 -0
  127. data/spec/requests/flows/authorization_code_errors_spec.rb +111 -0
  128. data/spec/requests/flows/authorization_code_spec.rb +125 -0
  129. data/spec/requests/flows/client_credentials_spec.rb +56 -0
  130. data/spec/requests/flows/implicit_grant_errors_spec.rb +31 -0
  131. data/spec/requests/flows/implicit_grant_spec.rb +19 -0
  132. data/spec/requests/flows/password_spec.rb +52 -0
  133. data/spec/requests/flows/refresh_token_spec.rb +66 -0
  134. data/spec/requests/flows/skip_authorization_spec.rb +40 -0
  135. data/spec/requests/protected_resources/private_api_spec.rb +43 -0
  136. data/spec/spec_helper.rb +1 -0
  137. data/spec/spec_helper_integration.rb +28 -0
  138. data/spec/support/dependencies/database_cleaner.rb +16 -0
  139. data/spec/support/dependencies/factory_girl.rb +5 -0
  140. data/spec/support/helpers/access_token_request_helper.rb +11 -0
  141. data/spec/support/helpers/authorization_request_helper.rb +32 -0
  142. data/spec/support/helpers/config_helper.rb +9 -0
  143. data/spec/support/helpers/model_helper.rb +45 -0
  144. data/spec/support/helpers/request_spec_helper.rb +72 -0
  145. data/spec/support/helpers/url_helper.rb +51 -0
  146. data/spec/support/shared/controllers_shared_context.rb +60 -0
  147. data/spec/support/shared/models_shared_examples.rb +44 -0
  148. metadata +163 -57
  149. data/app/controllers/doorkeeper/application_controller.rbc +0 -675
  150. data/app/controllers/doorkeeper/applications_controller.rbc +0 -954
  151. data/app/controllers/doorkeeper/authorizations_controller.rbc +0 -659
  152. data/app/controllers/doorkeeper/authorized_applications_controller.rbc +0 -393
  153. data/app/controllers/doorkeeper/tokens_controller.rbc +0 -423
  154. data/app/helpers/doorkeeper/application_helper.rbc +0 -127
  155. data/app/models/access_grant.rb +0 -31
  156. data/app/models/access_grant.rbc +0 -821
  157. data/app/models/access_token.rb +0 -70
  158. data/app/models/access_token.rbc +0 -979
  159. data/app/models/application.rb +0 -45
  160. data/app/models/application.rbc +0 -753
  161. data/config/initializers/form_errors.rbc +0 -272
  162. data/config/routes.rbc +0 -366
  163. data/lib/doorkeeper/config/scope.rb +0 -11
  164. data/lib/doorkeeper/config/scopes.rb +0 -61
  165. data/lib/doorkeeper/config/scopes_builder.rb +0 -18
  166. data/lib/doorkeeper/config.rbc +0 -1385
  167. data/lib/doorkeeper/doorkeeper_for.rbc +0 -1029
  168. data/lib/doorkeeper/engine.rbc +0 -318
  169. data/lib/doorkeeper/oauth/access_token_request.rbc +0 -2042
  170. data/lib/doorkeeper/oauth/authorization_request.rbc +0 -2272
  171. data/lib/doorkeeper/oauth/random_string.rbc +0 -437
  172. data/lib/doorkeeper/validations.rbc +0 -774
  173. data/lib/doorkeeper/version.rbc +0 -130
  174. data/lib/doorkeeper.rbc +0 -407
  175. data/lib/generators/doorkeeper/install_generator.rbc +0 -453
  176. data/lib/tasks/doorkeeper_tasks.rake.compiled.rbc +0 -40
@@ -0,0 +1,240 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe AccessTokenRequest do
5
+ let(:client) { FactoryGirl.create(:application) }
6
+ let(:grant) { FactoryGirl.create(:access_grant, :application => client) }
7
+ let(:params) {
8
+ {
9
+ :code => grant.token,
10
+ :grant_type => "authorization_code",
11
+ :redirect_uri => client.redirect_uri
12
+ }
13
+ }
14
+
15
+ describe "with a valid authorization code and client" do
16
+ subject { AccessTokenRequest.new(client, params) }
17
+
18
+ before { subject.authorize }
19
+
20
+ it { should be_valid }
21
+ its(:token_type) { should == "bearer" }
22
+ its(:error) { should be_nil }
23
+ its(:refresh_token) { should be_nil }
24
+
25
+ it "has an access token" do
26
+ subject.access_token.token.should =~ /\w+/
27
+ end
28
+ end
29
+
30
+ describe "creating the access token" do
31
+ subject { AccessTokenRequest.new(client, params) }
32
+
33
+ it "creates with correct params" do
34
+ Doorkeeper::AccessToken.should_receive(:create!).with({
35
+ :application_id => client.id,
36
+ :resource_owner_id => grant.resource_owner_id,
37
+ :expires_in => 2.hours,
38
+ :scopes =>"public write",
39
+ :use_refresh_token => false,
40
+ })
41
+ subject.authorize
42
+ end
43
+ end
44
+
45
+ describe "with a valid authorization code, client and existing valid access token" do
46
+ subject { AccessTokenRequest.new(client, params) }
47
+
48
+ before { subject.authorize }
49
+ it { should be_valid }
50
+ its(:error) { should be_nil }
51
+
52
+ it "will not create a new token" do
53
+ subject.should_not_receive(:create_access_token)
54
+ subject.authorize
55
+ end
56
+ end
57
+
58
+ describe "with a valid authorization code, client and existing expired access token" do
59
+ subject { AccessTokenRequest.new(client, params) }
60
+
61
+ it "will create a new token" do
62
+ subject.authorize
63
+ expired_access_token = subject.access_token.dup
64
+ subject.access_token.created_at = Time.now - subject.access_token.expires_in - 1.second
65
+ subject.should_receive(:create_access_token)
66
+ subject.access_token.should_receive(:revoke)
67
+ subject.authorize
68
+ subject.access_token.should_not eq(expired_access_token)
69
+ end
70
+ end
71
+
72
+ describe "finding the current access token" do
73
+ subject { AccessTokenRequest.new(client, params) }
74
+ it { should be_valid }
75
+ its(:error) { should be_nil }
76
+
77
+ before { subject.authorize }
78
+
79
+ it "should find the access token and not create a new one" do
80
+ subject.should_not_receive(:create_access_token)
81
+ access_token = subject.authorize
82
+ subject.access_token.should eq(access_token)
83
+ end
84
+ end
85
+
86
+ describe "creating the first access_token" do
87
+ subject { AccessTokenRequest.new(client, params) }
88
+ it { should be_valid }
89
+ its(:error) { should be_nil }
90
+
91
+ it "should create a new access token" do
92
+ subject.should_receive(:create_access_token)
93
+ subject.authorize
94
+ end
95
+ end
96
+
97
+ describe "with errors" do
98
+ def token(params)
99
+ AccessTokenRequest.new(client, params)
100
+ end
101
+
102
+ it "includes the error in the response" do
103
+ access_token = token(params.except(:grant_type))
104
+ access_token.error_response.name.should == :invalid_request
105
+ end
106
+
107
+ [:grant_type, :code, :redirect_uri].each do |param|
108
+ describe "when :#{param} is missing" do
109
+ subject { token(params.except(param)) }
110
+ its(:error) { should == :invalid_request }
111
+ end
112
+ end
113
+
114
+ describe "when client is not present" do
115
+ subject { AccessTokenRequest.new(nil, params) }
116
+ its(:error) { should == :invalid_client }
117
+ end
118
+
119
+ describe "when :code does not exist" do
120
+ subject { token(params.merge(:code => "inexistent")) }
121
+ its(:error) { should == :invalid_grant }
122
+ end
123
+
124
+ describe "when :redirect_uri does not match with grant's one" do
125
+ subject { token(params.merge(:redirect_uri => "another")) }
126
+ its(:error) { should == :invalid_grant }
127
+ end
128
+
129
+ describe "when :grant_type is not 'authorization_code'" do
130
+ subject { token(params.merge(:grant_type => "invalid")) }
131
+ its(:error) { should == :unsupported_grant_type }
132
+ end
133
+
134
+ describe "when granted application does not match" do
135
+ subject { token(params) }
136
+
137
+ before do
138
+ grant.application = FactoryGirl.create(:application)
139
+ grant.save!
140
+ end
141
+
142
+ its(:error) { should == :invalid_grant }
143
+ end
144
+
145
+ describe "when :code is expired" do
146
+ it "error is :invalid_grant" do
147
+ grant # create grant instance
148
+ Timecop.freeze(Time.now + 700.seconds) do
149
+ expired = token(params)
150
+ expired.error.should == :invalid_grant
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ describe AccessTokenRequest, "refresh token" do
158
+ let(:client) { FactoryGirl.create(:application) }
159
+ let(:access) { FactoryGirl.create(:access_token, :application => client, :use_refresh_token => true) }
160
+ let(:params) {
161
+ {
162
+ :refresh_token => access.refresh_token,
163
+ :grant_type => "refresh_token",
164
+ }
165
+ }
166
+
167
+ before do
168
+ Doorkeeper.configure { use_refresh_token }
169
+ end
170
+
171
+ describe "with a valid authorization code and client" do
172
+ subject { AccessTokenRequest.new(client, params) }
173
+
174
+ before do
175
+ subject.authorize
176
+ end
177
+
178
+ it { should be_valid }
179
+ its(:token_type) { should == "bearer" }
180
+ its(:error) { should be_nil }
181
+ its(:refresh_token) { should_not be_nil }
182
+
183
+ it "has an access token" do
184
+ subject.access_token.token.should =~ /\w+/
185
+ end
186
+ end
187
+
188
+ describe "with errors" do
189
+ def token(params)
190
+ AccessTokenRequest.new(client, params)
191
+ end
192
+
193
+ it "includes the error in the response" do
194
+ access_token = token(params.except(:grant_type))
195
+ access_token.error_response.name.should == :invalid_request
196
+ end
197
+
198
+ [:grant_type, :refresh_token].each do |param|
199
+ describe "when :#{param} is missing" do
200
+ subject { token(params.except(param)) }
201
+ its(:error) { should == :invalid_request }
202
+ end
203
+ end
204
+
205
+ describe "when client is not present" do
206
+ subject { AccessTokenRequest.new(nil, params) }
207
+ its(:error) { should == :invalid_client }
208
+ end
209
+
210
+ describe "when :refresh_token does not exist" do
211
+ subject { token(params.merge(:refresh_token => "inexistent")) }
212
+ its(:error) { should == :invalid_grant }
213
+ end
214
+
215
+ describe "when :grant_type is not 'refresh_token'" do
216
+ subject { token(params.merge(:grant_type => "invalid")) }
217
+ its(:error) { should == :invalid_request }
218
+ end
219
+
220
+ describe "when granted application does not match" do
221
+ subject { token(params) }
222
+
223
+ before do
224
+ access.application = FactoryGirl.create(:application)
225
+ access.save!
226
+ end
227
+
228
+ its(:error) { should == :invalid_grant }
229
+ end
230
+
231
+ describe "when :refresh_token is revoked" do
232
+ it "error is :invalid_grant" do
233
+ access.revoke # create grant instance
234
+ revoked = token(params)
235
+ revoked.error.should == :invalid_grant
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext/string'
3
+ require 'uri'
4
+ require 'rack/utils'
5
+ require 'doorkeeper/oauth/authorization/uri_builder'
6
+
7
+ module Doorkeeper::OAuth::Authorization
8
+ describe URIBuilder do
9
+
10
+ subject { Object.new.class.send :include, URIBuilder }
11
+
12
+ describe :uri_with_query do
13
+ it 'returns the uri with query' do
14
+ uri = subject.uri_with_query 'http://example.com/', :parameter => 'value'
15
+ uri.should == 'http://example.com/?parameter=value'
16
+ end
17
+
18
+ it 'rejects nil values' do
19
+ uri = subject.uri_with_query 'http://example.com/', :parameter => ""
20
+ uri.should == 'http://example.com/?'
21
+ end
22
+
23
+ it 'preserves original query parameters' do
24
+ uri = subject.uri_with_query 'http://example.com/?query1=value', :parameter => 'value'
25
+ uri.should =~ /query1=value/
26
+ uri.should =~ /parameter=value/
27
+ end
28
+ end
29
+
30
+ describe :uri_with_fragment do
31
+ it 'returns uri with parameters as fragments' do
32
+ uri = subject.uri_with_fragment 'http://example.com/', :parameter => 'value'
33
+ uri.should == 'http://example.com/#parameter=value'
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,286 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe AuthorizationRequest do
5
+ let(:resource_owner) { double(:resource_owner, :id => 1) }
6
+ let(:client) { FactoryGirl.create(:application) }
7
+ let(:base_attributes) do
8
+ {
9
+ :redirect_uri => client.redirect_uri,
10
+ :scope => "public write",
11
+ :state => "return-this"
12
+ }
13
+ end
14
+
15
+ before :each do
16
+ Doorkeeper.configuration.stub(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string('public write'))
17
+ end
18
+
19
+ describe "with a code response_type" do
20
+ let(:attributes) { base_attributes.merge!(:response_type => "code") }
21
+
22
+ describe "with valid attributes" do
23
+ subject { AuthorizationRequest.new(client, resource_owner, attributes) }
24
+
25
+ describe "after authorization" do
26
+ before { subject.authorize }
27
+
28
+ its(:response_type) { should == "code" }
29
+ its(:client_id) { should == client.uid }
30
+ its(:scope) { should == "public write" }
31
+ its(:state) { should == "return-this" }
32
+ its(:error) { should be_nil }
33
+
34
+ describe ".success_redirect_uri" do
35
+ let(:query) { URI.parse(subject.success_redirect_uri).query }
36
+
37
+ it "includes the grant code" do
38
+ query.should =~ %r{code=\w+}
39
+ end
40
+
41
+ it "includes the state previous assumed" do
42
+ query.should =~ %r{state=return-this}
43
+ end
44
+ end
45
+ end
46
+
47
+ describe :authorize do
48
+ let(:authorization_request) { AuthorizationRequest.new(client, resource_owner, attributes) }
49
+ subject { authorization_request.authorize }
50
+
51
+ it "returns Doorkeeper::AccessGrant object" do
52
+ subject.is_a? Doorkeeper::AccessGrant
53
+ end
54
+
55
+ it "returns instance saved in the database" do
56
+ subject.should be_persisted
57
+ end
58
+
59
+ it "returns object that has scopes attribute same as scope attribute of authorization request" do
60
+ subject.scopes == authorization_request.scope
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "with a redirect_uri with query params" do
66
+ let(:original_query_params) { "abc=123&def=456" }
67
+ let(:attributes_with_query_params) {
68
+ u = URI.parse(client.redirect_uri)
69
+ u.query = original_query_params
70
+ attributes[:redirect_uri] = u.to_s
71
+ attributes
72
+ }
73
+ subject { AuthorizationRequest.new(client, resource_owner, attributes_with_query_params) }
74
+
75
+ it "preservers the original query when error"
76
+
77
+ describe "after authorization" do
78
+ before { subject.authorize }
79
+
80
+ describe ".success_redirect_uri" do
81
+ let(:query) { URI.parse(subject.success_redirect_uri).query }
82
+
83
+ it "includes the grant code" do
84
+ query.should =~ %r{code=\w+}
85
+ end
86
+
87
+ it "includes the state previous assumed" do
88
+ query.should =~ %r{state=return-this}
89
+ end
90
+
91
+ it "preserves the original query parameters" do
92
+ query.should =~ /abc=123/
93
+ query.should =~ /def=456/
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "if no scope given" do
100
+ it "sets the scope to the default one" do
101
+ request = AuthorizationRequest.new(client, resource_owner, attributes.except(:scope))
102
+ request.scopes.to_s.should == "public write"
103
+ end
104
+ end
105
+
106
+ describe "with errors" do
107
+ before do
108
+ Doorkeeper::AccessGrant.should_not_receive(:create)
109
+ end
110
+
111
+ describe "when :response_type is missing" do
112
+ subject { auth(attributes.except(:response_type)) }
113
+ its(:error) { should == :invalid_request }
114
+ end
115
+
116
+ describe "when :redirect_uri is missing" do
117
+ subject { auth(attributes.except(:redirect_uri)) }
118
+ its(:error) { should == :invalid_redirect_uri }
119
+ end
120
+
121
+ describe "when client is not present" do
122
+ subject { AuthorizationRequest.new(nil, resource_owner, attributes) }
123
+ its(:error) { should == :invalid_client }
124
+ end
125
+
126
+ describe "when :redirect_uri mismatches" do
127
+ subject { auth(attributes.merge(:redirect_uri => "http://example.com/mismatch")) }
128
+ its(:error) { should == :invalid_redirect_uri }
129
+ end
130
+
131
+ describe "when :redirect_uri contains a fragment" do
132
+ subject { auth(attributes.merge(:redirect_uri => (client.redirect_uri + "#abc"))) }
133
+ its(:error) { should == :invalid_redirect_uri }
134
+ end
135
+
136
+ describe "when :redirect_uri is not a valid URI" do
137
+ subject { auth(attributes.merge(:redirect_uri => "invalid")) }
138
+ its(:error) { should == :invalid_redirect_uri }
139
+ end
140
+
141
+ describe "when :response_type is not 'code' or 'token'" do
142
+ subject { auth(attributes.merge(:response_type => "invalid")) }
143
+ its(:error) { should == :unsupported_response_type }
144
+ end
145
+
146
+ describe "when :scope contains scopes that are note registered in the provider" do
147
+ subject { auth(attributes.merge(:scope => "public strange")) }
148
+ its(:error) { should == :invalid_scope }
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "with a token response_type" do
154
+ before do
155
+ Doorkeeper.configuration.stub(:access_token_expires_in).and_return(7200)
156
+ end
157
+
158
+ let(:attributes) { base_attributes.merge!(:response_type => "token") }
159
+
160
+ describe "with valid attributes" do
161
+ subject { AuthorizationRequest.new(client, resource_owner, attributes) }
162
+
163
+ describe "after authorization" do
164
+ before { subject.authorize }
165
+
166
+ its(:response_type) { should == "token" }
167
+ its(:scope) { should == "public write" }
168
+ its(:state) { should == "return-this" }
169
+ its(:error) { should be_nil }
170
+
171
+ describe ".success_redirect_uri" do
172
+ let(:fragment) { URI.parse(subject.success_redirect_uri).fragment }
173
+
174
+ it "has a fragment" do
175
+ fragment.should_not be_nil
176
+ end
177
+
178
+ it "doesn't have query parameters" do
179
+ URI.parse(subject.success_redirect_uri).query.should be_nil
180
+ end
181
+
182
+ it "includes the access token" do
183
+ fragment.should =~ %r{access_token=\w+}
184
+ end
185
+
186
+ it "includes the token type" do
187
+ fragment.should =~ %r{token_type=bearer}
188
+ end
189
+
190
+ it "includes the expires in" do
191
+ fragment.should =~ %r{expires_in=\w+}
192
+ end
193
+
194
+ it "includes the state previous assumed" do
195
+ fragment.should =~ %r{state=return-this}
196
+ end
197
+ end
198
+ end
199
+
200
+ describe :authorize do
201
+ let(:authorization_request) { AuthorizationRequest.new(client, resource_owner, attributes) }
202
+ subject { authorization_request.authorize }
203
+
204
+ it "returns Doorkeeper::AccessGrant object" do
205
+ subject.is_a? Doorkeeper::AccessGrant
206
+ end
207
+
208
+ it "returns instance saved in the database" do
209
+ subject.should be_persisted
210
+ end
211
+
212
+ it "returns object that has scopes attribute same as scope attribute of authorization request" do
213
+ subject.scopes == authorization_request.scope
214
+ end
215
+ end
216
+ end
217
+
218
+ describe "if no scope given" do
219
+ it "sets the scope to the default one" do
220
+ request = AuthorizationRequest.new(client, resource_owner, attributes.except(:scope))
221
+ request.scopes.to_s.should == "public write"
222
+ end
223
+ end
224
+
225
+ describe "with errors" do
226
+ before do
227
+ Doorkeeper::AccessGrant.should_not_receive(:create)
228
+ end
229
+
230
+ describe "when :response_type is missing" do
231
+ subject { auth(attributes.except(:response_type)) }
232
+ its(:error) { should == :invalid_request }
233
+ end
234
+
235
+ describe "when :redirect_uri is missing" do
236
+ subject { auth(attributes.except(:redirect_uri)) }
237
+ its(:error) { should == :invalid_redirect_uri }
238
+ end
239
+
240
+ describe "when client is not present" do
241
+ subject { AuthorizationRequest.new(nil, resource_owner, attributes) }
242
+ its(:error) { should == :invalid_client }
243
+ end
244
+
245
+ describe "when :redirect_uri has a fragment" do
246
+ subject { auth(attributes.merge(:redirect_uri => client.redirect_uri + "#xyz")) }
247
+ its(:error) { should == :invalid_redirect_uri }
248
+ end
249
+
250
+ describe "when :redirect_uri is a relative URI" do
251
+ subject { auth(attributes.merge(:redirect_uri => "/abcdef")) }
252
+ its(:error) { should == :invalid_redirect_uri }
253
+ end
254
+
255
+ describe "when :redirect_uri mismatches" do
256
+ subject { auth(attributes.merge(:redirect_uri => "http://example.com/mismatch")) }
257
+ its(:error) { should == :invalid_redirect_uri }
258
+ end
259
+
260
+ describe "when :redirect_uri contains a fragment" do
261
+ subject { auth(attributes.merge(:redirect_uri => (client.redirect_uri + "#abc"))) }
262
+ its(:error) { should == :invalid_redirect_uri }
263
+ end
264
+
265
+ describe "when :redirect_uri is not a valid URI" do
266
+ subject { auth(attributes.merge(:redirect_uri => "invalid")) }
267
+ its(:error) { should == :invalid_redirect_uri }
268
+ end
269
+
270
+ describe "when :response_type is not 'code' or 'token'" do
271
+ subject { auth(attributes.merge(:response_type => "invalid")) }
272
+ its(:error) { should == :unsupported_response_type }
273
+ end
274
+
275
+ describe "when :scope contains scopes that are note registered in the provider" do
276
+ subject { auth(attributes.merge(:scope => "public strange")) }
277
+ its(:error) { should == :invalid_scope }
278
+ end
279
+ end
280
+ end
281
+
282
+ def auth(attributes)
283
+ AuthorizationRequest.new(client, resource_owner, attributes)
284
+ end
285
+ end
286
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext/string'
3
+ require 'doorkeeper/oauth/client'
4
+
5
+ class Doorkeeper::OAuth::Client
6
+ describe Credentials do
7
+ it 'is blank when any of the credentials is blank' do
8
+ Credentials.new(nil, "something").should be_blank
9
+ Credentials.new("something", nil).should be_blank
10
+ end
11
+
12
+ describe :from_request do
13
+ let(:request) { stub.as_null_object }
14
+
15
+ let(:method) do
16
+ lambda { |request| return 'uid', 'secret' }
17
+ end
18
+
19
+ it 'accepts anything that responds to #call' do
20
+ method.should_receive(:call).with(request)
21
+ Credentials.from_request request, method
22
+ end
23
+
24
+ it 'delegates methods received as symbols to Credentials class' do
25
+ Credentials.should_receive(:from_params).with(request)
26
+ Credentials.from_request request, :from_params
27
+ end
28
+
29
+ it 'stops at the first credentials found' do
30
+ not_called_method = mock
31
+ not_called_method.should_not_receive(:call)
32
+ credentials = Credentials.from_request request, lambda { |r| }, method, not_called_method
33
+ end
34
+
35
+ it 'returns new Credentials' do
36
+ credentials = Credentials.from_request request, method
37
+ credentials.should be_a(Credentials)
38
+ end
39
+
40
+ it 'returns uid and secret from extractor method' do
41
+ credentials = Credentials.from_request request, method
42
+ credentials.uid.should == 'uid'
43
+ credentials.secret.should == 'secret'
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'active_support/core_ext/string'
3
+ require 'doorkeeper/oauth/client'
4
+
5
+ class Doorkeeper::OAuth::Client
6
+ describe 'Methods' do
7
+ let(:client_id) { "some-uid" }
8
+ let(:client_secret) { "some-secret" }
9
+
10
+ subject do
11
+ Class.new do
12
+ include Methods
13
+ end.new
14
+ end
15
+
16
+ describe :from_params do
17
+ it 'returns credentials from parameters when Authorization header is not available' do
18
+ request = stub :parameters => { :client_id => client_id, :client_secret => client_secret }
19
+ uid, secret = subject.from_params(request)
20
+
21
+ uid.should == "some-uid"
22
+ secret.should == "some-secret"
23
+ end
24
+
25
+ it 'is blank when there are no credentials' do
26
+ request = stub :parameters => {}
27
+ uid, secret = subject.from_params(request)
28
+
29
+ uid.should be_blank
30
+ secret.should be_blank
31
+ end
32
+ end
33
+
34
+ describe :from_basic do
35
+ let(:credentials) { Base64.encode64("#{client_id}:#{client_secret}") }
36
+
37
+ it 'decodes the credentials' do
38
+ request = stub :authorization => "Basic #{credentials}"
39
+ uid, secret = subject.from_basic(request)
40
+
41
+ uid.should == "some-uid"
42
+ secret.should == "some-secret"
43
+ end
44
+
45
+ it 'is blank if Authorization is not Basic' do
46
+ request = stub :authorization => "#{credentials}"
47
+ uid, secret = subject.from_basic(request)
48
+
49
+ uid.should be_blank
50
+ secret.should be_blank
51
+ end
52
+ end
53
+ end
54
+ end