couchkeeper 0.6.7

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 (240) hide show
  1. data/.gitignore +14 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +28 -0
  4. data/CHANGELOG.md +198 -0
  5. data/Gemfile +32 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +290 -0
  8. data/Rakefile +18 -0
  9. data/app/assets/javascripts/doorkeeper/application.js +2 -0
  10. data/app/assets/stylesheets/doorkeeper/application.css +18 -0
  11. data/app/assets/stylesheets/doorkeeper/form.css +13 -0
  12. data/app/controllers/doorkeeper/application_controller.rb +7 -0
  13. data/app/controllers/doorkeeper/applications_controller.rb +60 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +57 -0
  15. data/app/controllers/doorkeeper/authorized_applications_controller.rb +12 -0
  16. data/app/controllers/doorkeeper/token_info_controller.rb +12 -0
  17. data/app/controllers/doorkeeper/tokens_controller.rb +20 -0
  18. data/app/helpers/doorkeeper/form_errors_helper.rb +9 -0
  19. data/app/validators/redirect_uri_validator.rb +23 -0
  20. data/app/views/doorkeeper/applications/_form.html.erb +34 -0
  21. data/app/views/doorkeeper/applications/edit.html.erb +13 -0
  22. data/app/views/doorkeeper/applications/index.html.erb +29 -0
  23. data/app/views/doorkeeper/applications/new.html.erb +13 -0
  24. data/app/views/doorkeeper/applications/show.html.erb +26 -0
  25. data/app/views/doorkeeper/authorizations/error.html.erb +6 -0
  26. data/app/views/doorkeeper/authorizations/new.html.erb +37 -0
  27. data/app/views/doorkeeper/authorizations/show.html.erb +4 -0
  28. data/app/views/doorkeeper/authorized_applications/index.html.erb +25 -0
  29. data/app/views/layouts/doorkeeper/application.html.erb +33 -0
  30. data/config/locales/en.yml +68 -0
  31. data/doorkeeper.gemspec +28 -0
  32. data/lib/doorkeeper.rb +64 -0
  33. data/lib/doorkeeper/config.rb +194 -0
  34. data/lib/doorkeeper/doorkeeper_for.rb +76 -0
  35. data/lib/doorkeeper/engine.rb +19 -0
  36. data/lib/doorkeeper/errors.rb +15 -0
  37. data/lib/doorkeeper/helpers/controller.rb +58 -0
  38. data/lib/doorkeeper/helpers/filter.rb +38 -0
  39. data/lib/doorkeeper/models/access_grant.rb +24 -0
  40. data/lib/doorkeeper/models/access_token.rb +95 -0
  41. data/lib/doorkeeper/models/accessible.rb +9 -0
  42. data/lib/doorkeeper/models/active_record/access_grant.rb +5 -0
  43. data/lib/doorkeeper/models/active_record/access_token.rb +21 -0
  44. data/lib/doorkeeper/models/active_record/application.rb +20 -0
  45. data/lib/doorkeeper/models/application.rb +33 -0
  46. data/lib/doorkeeper/models/couchbase/access_grant.rb +10 -0
  47. data/lib/doorkeeper/models/couchbase/access_token.rb +7 -0
  48. data/lib/doorkeeper/models/couchbase/application.rb +35 -0
  49. data/lib/doorkeeper/models/doorkeeper_access_grant/by_token/map.js +5 -0
  50. data/lib/doorkeeper/models/doorkeeper_access_token/by_application_id/map.js +5 -0
  51. data/lib/doorkeeper/models/doorkeeper_access_token/by_application_id_and_resource_owner_id/map.js +5 -0
  52. data/lib/doorkeeper/models/doorkeeper_access_token/by_refresh_token/map.js +5 -0
  53. data/lib/doorkeeper/models/doorkeeper_access_token/by_resource_owner_id/map.js +5 -0
  54. data/lib/doorkeeper/models/doorkeeper_access_token/by_token/map.js +5 -0
  55. data/lib/doorkeeper/models/doorkeeper_application/by_uid/map.js +5 -0
  56. data/lib/doorkeeper/models/doorkeeper_application/by_uid_and_secret/map.js +5 -0
  57. data/lib/doorkeeper/models/doorkeeper_application/show_all/map.js +6 -0
  58. data/lib/doorkeeper/models/expirable.rb +21 -0
  59. data/lib/doorkeeper/models/mongo_mapper/access_grant.rb +28 -0
  60. data/lib/doorkeeper/models/mongo_mapper/access_token.rb +51 -0
  61. data/lib/doorkeeper/models/mongo_mapper/application.rb +30 -0
  62. data/lib/doorkeeper/models/mongo_mapper/revocable.rb +15 -0
  63. data/lib/doorkeeper/models/mongoid/revocable.rb +15 -0
  64. data/lib/doorkeeper/models/mongoid/scopes.rb +15 -0
  65. data/lib/doorkeeper/models/mongoid2/access_grant.rb +22 -0
  66. data/lib/doorkeeper/models/mongoid2/access_token.rb +41 -0
  67. data/lib/doorkeeper/models/mongoid2/application.rb +22 -0
  68. data/lib/doorkeeper/models/mongoid3/access_grant.rb +22 -0
  69. data/lib/doorkeeper/models/mongoid3/access_token.rb +41 -0
  70. data/lib/doorkeeper/models/mongoid3/application.rb +22 -0
  71. data/lib/doorkeeper/models/ownership.rb +16 -0
  72. data/lib/doorkeeper/models/scopes.rb +17 -0
  73. data/lib/doorkeeper/oauth/authorization.rb +10 -0
  74. data/lib/doorkeeper/oauth/authorization/code.rb +32 -0
  75. data/lib/doorkeeper/oauth/authorization/token.rb +28 -0
  76. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +29 -0
  77. data/lib/doorkeeper/oauth/authorization_code_request.rb +82 -0
  78. data/lib/doorkeeper/oauth/client.rb +29 -0
  79. data/lib/doorkeeper/oauth/client/credentials.rb +21 -0
  80. data/lib/doorkeeper/oauth/client/methods.rb +18 -0
  81. data/lib/doorkeeper/oauth/client_credentials/creator.rb +29 -0
  82. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +35 -0
  83. data/lib/doorkeeper/oauth/client_credentials/validation.rb +33 -0
  84. data/lib/doorkeeper/oauth/client_credentials_request.rb +47 -0
  85. data/lib/doorkeeper/oauth/code_request.rb +28 -0
  86. data/lib/doorkeeper/oauth/code_response.rb +37 -0
  87. data/lib/doorkeeper/oauth/error.rb +9 -0
  88. data/lib/doorkeeper/oauth/error_response.rb +44 -0
  89. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +18 -0
  90. data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -0
  91. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +32 -0
  92. data/lib/doorkeeper/oauth/password_access_token_request.rb +84 -0
  93. data/lib/doorkeeper/oauth/pre_authorization.rb +62 -0
  94. data/lib/doorkeeper/oauth/refresh_token_request.rb +58 -0
  95. data/lib/doorkeeper/oauth/scopes.rb +60 -0
  96. data/lib/doorkeeper/oauth/token.rb +36 -0
  97. data/lib/doorkeeper/oauth/token_request.rb +28 -0
  98. data/lib/doorkeeper/oauth/token_response.rb +29 -0
  99. data/lib/doorkeeper/rails/routes.rb +90 -0
  100. data/lib/doorkeeper/rails/routes/mapper.rb +28 -0
  101. data/lib/doorkeeper/rails/routes/mapping.rb +39 -0
  102. data/lib/doorkeeper/request.rb +33 -0
  103. data/lib/doorkeeper/request/authorization_code.rb +23 -0
  104. data/lib/doorkeeper/request/client_credentials.rb +23 -0
  105. data/lib/doorkeeper/request/code.rb +24 -0
  106. data/lib/doorkeeper/request/password.rb +23 -0
  107. data/lib/doorkeeper/request/refresh_token.rb +23 -0
  108. data/lib/doorkeeper/request/token.rb +24 -0
  109. data/lib/doorkeeper/server.rb +54 -0
  110. data/lib/doorkeeper/validations.rb +30 -0
  111. data/lib/doorkeeper/version.rb +3 -0
  112. data/lib/generators/doorkeeper/application_owner_generator.rb +15 -0
  113. data/lib/generators/doorkeeper/install_generator.rb +12 -0
  114. data/lib/generators/doorkeeper/migration_generator.rb +15 -0
  115. data/lib/generators/doorkeeper/mongo_mapper/indexes_generator.rb +12 -0
  116. data/lib/generators/doorkeeper/templates/README +44 -0
  117. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +7 -0
  118. data/lib/generators/doorkeeper/templates/indexes.rb +3 -0
  119. data/lib/generators/doorkeeper/templates/initializer.rb +67 -0
  120. data/lib/generators/doorkeeper/templates/migration.rb +42 -0
  121. data/lib/generators/doorkeeper/views_generator.rb +15 -0
  122. data/script/rails +6 -0
  123. data/script/run_all +14 -0
  124. data/spec/controllers/applications_controller_spec.rb +18 -0
  125. data/spec/controllers/authorizations_controller_spec.rb +154 -0
  126. data/spec/controllers/protected_resources_controller_spec.rb +304 -0
  127. data/spec/controllers/token_info_controller_spec.rb +54 -0
  128. data/spec/controllers/tokens_controller_spec.rb +36 -0
  129. data/spec/dummy/Rakefile +7 -0
  130. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  131. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  132. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  133. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +7 -0
  134. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  135. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  136. data/spec/dummy/app/controllers/metal_controller.rb +11 -0
  137. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  138. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  139. data/spec/dummy/app/models/user.rb +27 -0
  140. data/spec/dummy/app/views/home/index.html.erb +0 -0
  141. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  142. data/spec/dummy/config.ru +4 -0
  143. data/spec/dummy/config/application.rb +54 -0
  144. data/spec/dummy/config/boot.rb +6 -0
  145. data/spec/dummy/config/database.yml +15 -0
  146. data/spec/dummy/config/environment.rb +5 -0
  147. data/spec/dummy/config/environments/development.rb +30 -0
  148. data/spec/dummy/config/environments/production.rb +60 -0
  149. data/spec/dummy/config/environments/test.rb +39 -0
  150. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  151. data/spec/dummy/config/initializers/doorkeeper.rb +56 -0
  152. data/spec/dummy/config/initializers/secret_token.rb +9 -0
  153. data/spec/dummy/config/initializers/session_store.rb +8 -0
  154. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  155. data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
  156. data/spec/dummy/config/mongo.yml +11 -0
  157. data/spec/dummy/config/mongoid2.yml +9 -0
  158. data/spec/dummy/config/mongoid3.yml +18 -0
  159. data/spec/dummy/config/routes.rb +38 -0
  160. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  161. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
  162. data/spec/dummy/db/migrate/20120524202412_create_doorkeeper_tables.rb +44 -0
  163. data/spec/dummy/db/schema.rb +64 -0
  164. data/spec/dummy/public/404.html +26 -0
  165. data/spec/dummy/public/422.html +26 -0
  166. data/spec/dummy/public/500.html +26 -0
  167. data/spec/dummy/public/favicon.ico +0 -0
  168. data/spec/dummy/script/rails +6 -0
  169. data/spec/factories/access_grant.rb +9 -0
  170. data/spec/factories/access_token.rb +7 -0
  171. data/spec/factories/application.rb +6 -0
  172. data/spec/generators/application_owner_generator_spec.rb +23 -0
  173. data/spec/generators/install_generator_spec.rb +31 -0
  174. data/spec/generators/migration_generator_spec.rb +20 -0
  175. data/spec/generators/templates/routes.rb +3 -0
  176. data/spec/generators/views_generator_spec.rb +27 -0
  177. data/spec/lib/config_spec.rb +170 -0
  178. data/spec/lib/models/expirable_spec.rb +51 -0
  179. data/spec/lib/models/revocable_spec.rb +31 -0
  180. data/spec/lib/models/scopes_spec.rb +32 -0
  181. data/spec/lib/oauth/authorization/uri_builder_spec.rb +37 -0
  182. data/spec/lib/oauth/authorization_code_request_spec.rb +80 -0
  183. data/spec/lib/oauth/client/credentials_spec.rb +47 -0
  184. data/spec/lib/oauth/client/methods_spec.rb +54 -0
  185. data/spec/lib/oauth/client_credentials/creator_spec.rb +47 -0
  186. data/spec/lib/oauth/client_credentials/issuer_spec.rb +57 -0
  187. data/spec/lib/oauth/client_credentials/validation_spec.rb +29 -0
  188. data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
  189. data/spec/lib/oauth/client_credentials_request_spec.rb +64 -0
  190. data/spec/lib/oauth/client_spec.rb +39 -0
  191. data/spec/lib/oauth/code_request_spec.rb +44 -0
  192. data/spec/lib/oauth/error_response_spec.rb +40 -0
  193. data/spec/lib/oauth/error_spec.rb +19 -0
  194. data/spec/lib/oauth/helpers/scope_checker_spec.rb +74 -0
  195. data/spec/lib/oauth/helpers/unique_token_spec.rb +20 -0
  196. data/spec/lib/oauth/helpers/uri_checker_spec.rb +64 -0
  197. data/spec/lib/oauth/password_access_token_request_spec.rb +65 -0
  198. data/spec/lib/oauth/pre_authorization_spec.rb +80 -0
  199. data/spec/lib/oauth/refresh_token_request_spec.rb +56 -0
  200. data/spec/lib/oauth/scopes_spec.rb +115 -0
  201. data/spec/lib/oauth/token_request_spec.rb +46 -0
  202. data/spec/lib/oauth/token_response_spec.rb +52 -0
  203. data/spec/lib/oauth/token_spec.rb +83 -0
  204. data/spec/lib/server_spec.rb +24 -0
  205. data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
  206. data/spec/models/doorkeeper/access_token_spec.rb +153 -0
  207. data/spec/models/doorkeeper/application_spec.rb +162 -0
  208. data/spec/requests/applications/applications_request_spec.rb +92 -0
  209. data/spec/requests/applications/authorized_applications_spec.rb +30 -0
  210. data/spec/requests/endpoints/authorization_spec.rb +47 -0
  211. data/spec/requests/endpoints/token_spec.rb +46 -0
  212. data/spec/requests/flows/authorization_code_errors_spec.rb +66 -0
  213. data/spec/requests/flows/authorization_code_spec.rb +135 -0
  214. data/spec/requests/flows/client_credentials_spec.rb +58 -0
  215. data/spec/requests/flows/implicit_grant_errors_spec.rb +31 -0
  216. data/spec/requests/flows/implicit_grant_spec.rb +19 -0
  217. data/spec/requests/flows/password_spec.rb +78 -0
  218. data/spec/requests/flows/refresh_token_spec.rb +71 -0
  219. data/spec/requests/flows/skip_authorization_spec.rb +40 -0
  220. data/spec/requests/protected_resources/metal_spec.rb +14 -0
  221. data/spec/requests/protected_resources/private_api_spec.rb +50 -0
  222. data/spec/routing/custom_controller_routes_spec.rb +44 -0
  223. data/spec/routing/default_routes_spec.rb +32 -0
  224. data/spec/spec_helper.rb +2 -0
  225. data/spec/spec_helper_integration.rb +40 -0
  226. data/spec/support/dependencies/factory_girl.rb +2 -0
  227. data/spec/support/helpers/access_token_request_helper.rb +11 -0
  228. data/spec/support/helpers/authorization_request_helper.rb +32 -0
  229. data/spec/support/helpers/config_helper.rb +9 -0
  230. data/spec/support/helpers/model_helper.rb +45 -0
  231. data/spec/support/helpers/request_spec_helper.rb +72 -0
  232. data/spec/support/helpers/url_helper.rb +51 -0
  233. data/spec/support/orm/active_record.rb +11 -0
  234. data/spec/support/orm/mongo_mapper.rb +26 -0
  235. data/spec/support/orm/mongoid.rb +31 -0
  236. data/spec/support/shared/controllers_shared_context.rb +60 -0
  237. data/spec/support/shared/models_shared_examples.rb +60 -0
  238. data/spec/validators/redirect_uri_validator_spec.rb +47 -0
  239. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +356 -0
  240. metadata +430 -0
@@ -0,0 +1,92 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Adding applications' do
4
+ context 'in application form' do
5
+ background do
6
+ visit '/oauth/applications/new'
7
+ end
8
+
9
+ scenario 'adding a valid app' do
10
+ fill_in 'Name', :with => 'My Application'
11
+ fill_in 'Redirect uri', :with => 'http://example.com'
12
+ click_button 'Submit'
13
+ i_should_see 'Application created'
14
+ i_should_see 'My Application'
15
+ end
16
+
17
+ scenario 'adding invalid app' do
18
+ click_button 'Submit'
19
+ i_should_see 'Whoops! Check your form for possible errors'
20
+ end
21
+ end
22
+ end
23
+
24
+ feature 'Listing applications' do
25
+ background do
26
+ FactoryGirl.create :application, :name => 'Oauth Dude'
27
+ FactoryGirl.create :application, :name => 'Awesome App'
28
+ end
29
+
30
+ scenario 'application list' do
31
+ visit '/oauth/applications'
32
+ i_should_see 'Awesome App'
33
+ i_should_see 'Oauth Dude'
34
+ end
35
+ end
36
+
37
+ feature 'Show application' do
38
+ let :app do
39
+ FactoryGirl.create :application, :name => 'Just another oauth app'
40
+ end
41
+
42
+ scenario 'visiting application page' do
43
+ visit "/oauth/applications/#{app.id}"
44
+ i_should_see 'Just another oauth app'
45
+ end
46
+ end
47
+
48
+ feature 'Edit application' do
49
+ let :app do
50
+ FactoryGirl.create :application, :name => 'OMG my app'
51
+ end
52
+
53
+ background do
54
+ visit "/oauth/applications/#{app.id}/edit"
55
+ end
56
+
57
+ scenario 'updating a valid app' do
58
+ fill_in :name, :with => "Serious app"
59
+ click_button 'Submit'
60
+ i_should_see "Application updated"
61
+ i_should_see "Serious app"
62
+ i_should_not_see "OMG my app"
63
+ end
64
+
65
+ scenario 'updating an invalid app' do
66
+ fill_in :name, :with => ""
67
+ click_button 'Submit'
68
+ i_should_see 'Whoops! Check your form for possible errors'
69
+ end
70
+ end
71
+
72
+ feature 'Destroy application' do
73
+ background do
74
+ @app = FactoryGirl.create :application
75
+ end
76
+
77
+ scenario 'deleting an application from list' do
78
+ visit "/oauth/applications"
79
+ i_should_see @app.name
80
+ within(:css, "tr#application_#{@app.id}") do
81
+ click_link "Destroy"
82
+ end
83
+ i_should_see "Application deleted"
84
+ i_should_not_see @app.name
85
+ end
86
+
87
+ scenario 'deleting an application from show' do
88
+ visit "/oauth/applications/#{@app.id}"
89
+ click_link 'Remove'
90
+ i_should_see "Application deleted"
91
+ end
92
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Authorized applications' do
4
+ background do
5
+ @user = User.create!(:name => "Joe", :password => "sekret")
6
+ @client = client_exists(:name => "Amazing Client App")
7
+ resource_owner_is_authenticated @user
8
+ client_is_authorized @client, @user
9
+ end
10
+
11
+ scenario "display user's authorized applications" do
12
+ visit '/oauth/authorized_applications'
13
+ i_should_see 'Amazing Client App'
14
+ end
15
+
16
+ scenario "do not display other user's authorized applications" do
17
+ client = client_exists(:name => "Another Client App")
18
+ client_is_authorized client, User.create!(:name => "Joe", :password => "sekret")
19
+ visit '/oauth/authorized_applications'
20
+ i_should_not_see 'Another Client App'
21
+ end
22
+
23
+ scenario "user revoke access to application" do
24
+ visit '/oauth/authorized_applications'
25
+ i_should_see 'Amazing Client App'
26
+ click_on 'Revoke'
27
+ i_should_see 'Application revoked'
28
+ i_should_not_see 'Amazing Client App'
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Authorization endpoint' do
4
+ background do
5
+ config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
6
+ client_exists(:name => "MyApp")
7
+ end
8
+
9
+ scenario 'requires resource owner to be authenticated' do
10
+ visit authorization_endpoint_url(:client => @client)
11
+ i_should_see "Sign in"
12
+ i_should_be_on "/"
13
+ end
14
+
15
+ context 'with authenticated resource owner' do
16
+ background do
17
+ create_resource_owner
18
+ sign_in
19
+ end
20
+
21
+ scenario 'displays the authorization form' do
22
+ visit authorization_endpoint_url(:client => @client)
23
+ i_should_see "Authorize MyApp to use your account?"
24
+ end
25
+
26
+ scenario "displays all requested scopes" do
27
+ default_scopes_exist :public
28
+ optional_scopes_exist :write
29
+ visit authorization_endpoint_url(:client => @client, :scope => "public write")
30
+ i_should_see "Access your public data"
31
+ i_should_see "Update your data"
32
+ end
33
+ end
34
+
35
+ context 'with a invalid request' do
36
+ background do
37
+ create_resource_owner
38
+ sign_in
39
+ end
40
+
41
+ scenario "displays the related error" do
42
+ visit authorization_endpoint_url(:client => @client, :response_type => "")
43
+ i_should_not_see "Authorize"
44
+ i_should_see_translated_error_message :unsupported_response_type
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Token endpoint' do
4
+ background do
5
+ client_exists
6
+ authorization_code_exists :application => @client, :scopes => "public"
7
+ end
8
+
9
+ scenario 'respond with correct headers' do
10
+ post token_endpoint_url(:code => @authorization.token, :client => @client)
11
+ should_have_header 'Pragma', 'no-cache'
12
+ should_have_header 'Cache-Control', 'no-store'
13
+ should_have_header 'Content-Type', 'application/json; charset=utf-8'
14
+ end
15
+
16
+ scenario 'accepts client credentials with basic auth header' do
17
+ post token_endpoint_url(:code => @authorization.token, :redirect_uri => @client.redirect_uri),
18
+ {} ,
19
+ { 'HTTP_AUTHORIZATION' => basic_auth_header_for_client(@client) }
20
+
21
+ should_have_json 'access_token', Doorkeeper::AccessToken.first.token
22
+ end
23
+
24
+ scenario 'returns null for expires_in when a permanent token is set' do
25
+ config_is_set(:access_token_expires_in, nil)
26
+ post token_endpoint_url(:code => @authorization.token, :client => @client)
27
+ should_have_json 'access_token', Doorkeeper::AccessToken.first.token
28
+ should_have_json 'expires_in', nil
29
+ end
30
+
31
+ scenario 'returns unsupported_grant_type for invalid grant_type param' do
32
+ post token_endpoint_url(:code => @authorization.token, :client => @client, :grant_type => 'nothing')
33
+
34
+ should_not_have_json 'access_token'
35
+ should_have_json 'error', 'unsupported_grant_type'
36
+ should_have_json 'error_description', translated_error_message('unsupported_grant_type')
37
+ end
38
+
39
+ scenario 'returns invalid_request if grant_type is missing' do
40
+ post token_endpoint_url(:code => @authorization.token, :client => @client, :grant_type => '')
41
+
42
+ should_not_have_json 'access_token'
43
+ should_have_json 'error', 'invalid_request'
44
+ should_have_json 'error_description', translated_error_message('invalid_request')
45
+ end
46
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Authorization Code Flow Errors' do
4
+ background do
5
+ config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
6
+ client_exists
7
+ create_resource_owner
8
+ sign_in
9
+ end
10
+
11
+ after do
12
+ access_grant_should_not_exist
13
+ end
14
+
15
+ context 'when access was denied' do
16
+ scenario 'redirects with error' do
17
+ visit authorization_endpoint_url(:client => @client)
18
+ click_on "Deny"
19
+
20
+ i_should_be_on_client_callback @client
21
+ url_should_not_have_param "code"
22
+ url_should_have_param "error", "access_denied"
23
+ url_should_have_param "error_description", translated_error_message(:access_denied)
24
+ end
25
+
26
+ scenario 'redirects with state parameter' do
27
+ visit authorization_endpoint_url(:client => @client, :state => "return-this")
28
+ click_on "Deny"
29
+
30
+ i_should_be_on_client_callback @client
31
+ url_should_not_have_param "code"
32
+ url_should_have_param "state", "return-this"
33
+ end
34
+ end
35
+ end
36
+
37
+ feature 'Authorization Code Flow Errors', 'after authorization' do
38
+ background do
39
+ client_exists
40
+ authorization_code_exists :application => @client
41
+ end
42
+
43
+ scenario "returns :invalid_grant error when posting an already revoked grant code" do
44
+ # First successful request
45
+ post token_endpoint_url(:code => @authorization.token, :client => @client)
46
+
47
+ # Second attempt with same token
48
+ expect {
49
+ post token_endpoint_url(:code => @authorization.token, :client => @client)
50
+ }.to_not change { Doorkeeper::AccessToken.count }
51
+
52
+ should_not_have_json 'access_token'
53
+ should_have_json 'error', 'invalid_grant'
54
+ should_have_json 'error_description', translated_error_message('invalid_grant')
55
+ end
56
+
57
+ scenario "returns :invalid_grant error for invalid grant code" do
58
+ post token_endpoint_url(:code => "invalid", :client => @client)
59
+
60
+ access_token_should_not_exist
61
+
62
+ should_not_have_json 'access_token'
63
+ should_have_json 'error', 'invalid_grant'
64
+ should_have_json 'error_description', translated_error_message('invalid_grant')
65
+ end
66
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec_helper_integration'
2
+
3
+ feature 'Authorization Code Flow' do
4
+ background do
5
+ config_is_set(:authenticate_resource_owner) { User.first || redirect_to('/sign_in') }
6
+ client_exists
7
+ create_resource_owner
8
+ sign_in
9
+ end
10
+
11
+ scenario 'resource owner authorizes the client' do
12
+ visit authorization_endpoint_url(:client => @client)
13
+ click_on "Authorize"
14
+
15
+ access_grant_should_exist_for(@client, @resource_owner)
16
+
17
+ i_should_be_on_client_callback(@client)
18
+
19
+ url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
20
+ url_should_not_have_param("state")
21
+ url_should_not_have_param("error")
22
+ end
23
+
24
+ scenario 'resource owner authorizes using test url' do
25
+ @client.redirect_uri = Doorkeeper.configuration.test_redirect_uri
26
+ @client.save!
27
+ visit authorization_endpoint_url(:client => @client)
28
+ click_on "Authorize"
29
+
30
+ access_grant_should_exist_for(@client, @resource_owner)
31
+
32
+ i_should_see 'Authorization code:'
33
+ i_should_see Doorkeeper::AccessGrant.first.token
34
+ end
35
+
36
+ scenario 'resource owner authorizes the client with state parameter set' do
37
+ visit authorization_endpoint_url(:client => @client, :state => "return-me")
38
+ click_on "Authorize"
39
+ url_should_have_param("code", Doorkeeper::AccessGrant.first.token)
40
+ url_should_have_param("state", "return-me")
41
+ end
42
+
43
+ scenario 'returns the same token if it is still accessible' do
44
+ client_is_authorized(@client, @resource_owner)
45
+ visit authorization_endpoint_url(:client => @client)
46
+
47
+ authorization_code = Doorkeeper::AccessGrant.first.token
48
+ post token_endpoint_url(:code => authorization_code, :client => @client)
49
+
50
+ Doorkeeper::AccessToken.count.should be(1)
51
+
52
+ should_have_json 'access_token', Doorkeeper::AccessToken.first.token
53
+ end
54
+
55
+ scenario 'revokes and return new token if it is has expired' do
56
+ client_is_authorized(@client, @resource_owner)
57
+ token = Doorkeeper::AccessToken.first
58
+ token.update_column :expires_in, -100
59
+ visit authorization_endpoint_url(:client => @client)
60
+
61
+ authorization_code = Doorkeeper::AccessGrant.first.token
62
+ post token_endpoint_url(:code => authorization_code, :client => @client)
63
+
64
+ token.reload.should be_revoked
65
+ Doorkeeper::AccessToken.count.should be(2)
66
+
67
+ should_have_json 'access_token', Doorkeeper::AccessToken.last.token
68
+ end
69
+
70
+ scenario 'resource owner requests an access token with authorization code' do
71
+ visit authorization_endpoint_url(:client => @client)
72
+ click_on "Authorize"
73
+
74
+ authorization_code = Doorkeeper::AccessGrant.first.token
75
+ post token_endpoint_url(:code => authorization_code, :client => @client)
76
+
77
+ access_token_should_exist_for(@client, @resource_owner)
78
+
79
+ should_not_have_json 'error'
80
+
81
+ should_have_json 'access_token', Doorkeeper::AccessToken.first.token
82
+ should_have_json 'token_type', "bearer"
83
+ should_have_json 'expires_in', Doorkeeper::AccessToken.first.expires_in
84
+ end
85
+
86
+ context 'with scopes' do
87
+ background do
88
+ default_scopes_exist :public
89
+ optional_scopes_exist :write
90
+ end
91
+
92
+ scenario 'resource owner authorizes the client with default scopes' do
93
+ visit authorization_endpoint_url(:client => @client)
94
+ click_on "Authorize"
95
+ access_grant_should_exist_for(@client, @resource_owner)
96
+ access_grant_should_have_scopes :public
97
+ end
98
+
99
+ scenario 'resource owner authorizes the client with required scopes' do
100
+ visit authorization_endpoint_url(:client => @client, :scope => "public write")
101
+ click_on "Authorize"
102
+ access_grant_should_have_scopes :public, :write
103
+ end
104
+
105
+ scenario 'resource owner authorizes the client with required scopes (without defaults)' do
106
+ visit authorization_endpoint_url(:client => @client, :scope => "write")
107
+ click_on "Authorize"
108
+ access_grant_should_have_scopes :write
109
+ end
110
+
111
+ scenario 'new access token matches required scopes' do
112
+ visit authorization_endpoint_url(:client => @client, :scope => "public write")
113
+ click_on "Authorize"
114
+
115
+ authorization_code = Doorkeeper::AccessGrant.first.token
116
+ post token_endpoint_url(:code => authorization_code, :client => @client)
117
+
118
+ access_token_should_exist_for(@client, @resource_owner)
119
+ access_token_should_have_scopes :public, :write
120
+ end
121
+
122
+ scenario 'returns new token if scopes have changed' do
123
+ client_is_authorized(@client, @resource_owner, :scopes => "public write")
124
+ visit authorization_endpoint_url(:client => @client, :scope => "public")
125
+ click_on "Authorize"
126
+
127
+ authorization_code = Doorkeeper::AccessGrant.first.token
128
+ post token_endpoint_url(:code => authorization_code, :client => @client)
129
+
130
+ Doorkeeper::AccessToken.count.should be(2)
131
+
132
+ should_have_json 'access_token', Doorkeeper::AccessToken.last.token
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe 'Client Credentials Request' do
4
+ let(:client) { FactoryGirl.create :application }
5
+
6
+ context 'a valid request' do
7
+ it 'authorizes the client and returns the token response' do
8
+ headers = authorization client.uid, client.secret
9
+ params = { :grant_type => 'client_credentials' }
10
+
11
+ post '/oauth/token', params, headers
12
+
13
+ should_have_json 'access_token', Doorkeeper::AccessToken.first.token
14
+ should_have_json 'expires_in', Doorkeeper.configuration.access_token_expires_in
15
+ should_have_json 'scope', ''
16
+ should_have_json 'refresh_token', nil
17
+
18
+ should_not_have_json 'error'
19
+ should_not_have_json 'error_description'
20
+ end
21
+
22
+ context 'with scopes' do
23
+ before do
24
+ optional_scopes_exist :write
25
+ end
26
+
27
+ it 'adds the scope to the token an returns in the response' do
28
+ headers = authorization client.uid, client.secret
29
+ params = { :grant_type => 'client_credentials', :scope => 'write' }
30
+
31
+ post '/oauth/token', params, headers
32
+
33
+ should_have_json 'access_token', Doorkeeper::AccessToken.first.token
34
+ should_have_json 'scope', 'write'
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'an invalid request' do
40
+ it 'does not authorize the client and returns the error' do
41
+ headers = {}
42
+ params = { :grant_type => 'client_credentials' }
43
+
44
+ post '/oauth/token', params, headers
45
+
46
+ should_have_json 'error', 'invalid_client'
47
+ should_have_json 'error_description', translated_error_message(:invalid_client)
48
+ should_not_have_json 'access_token'
49
+
50
+ response.status.should == 401
51
+ end
52
+ end
53
+
54
+ def authorization(username, password)
55
+ credentials = ActionController::HttpAuthentication::Basic.encode_credentials username, password
56
+ { 'HTTP_AUTHORIZATION' => credentials }
57
+ end
58
+ end