doorkeeper-sequel 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +13 -0
  6. data/.travis.yml +24 -0
  7. data/CHANGELOG.md +24 -0
  8. data/Gemfile +23 -0
  9. data/Gemfile.lock +172 -0
  10. data/LICENSE +21 -0
  11. data/README.md +76 -0
  12. data/Rakefile +56 -0
  13. data/config/locales/en.yml +16 -0
  14. data/doorkeeper-sequel.gemspec +32 -0
  15. data/gemfiles/rails-4.2.gemfile +11 -0
  16. data/gemfiles/rails-5.0.gemfile +11 -0
  17. data/lib/doorkeeper/orm/sequel/access_grant.rb +9 -0
  18. data/lib/doorkeeper/orm/sequel/access_token.rb +32 -0
  19. data/lib/doorkeeper/orm/sequel/application.rb +18 -0
  20. data/lib/doorkeeper/orm/sequel/models/access_grant_mixin.rb +50 -0
  21. data/lib/doorkeeper/orm/sequel/models/access_token_mixin.rb +163 -0
  22. data/lib/doorkeeper/orm/sequel/models/application_mixin.rb +70 -0
  23. data/lib/doorkeeper/orm/sequel/models/concerns/ownership.rb +19 -0
  24. data/lib/doorkeeper/orm/sequel/models/concerns/sequel_compat.rb +40 -0
  25. data/lib/doorkeeper/orm/sequel/validators/redirect_uri_validator.rb +49 -0
  26. data/lib/doorkeeper/orm/sequel.rb +18 -0
  27. data/lib/doorkeeper-sequel/gem_version.rb +13 -0
  28. data/lib/doorkeeper-sequel/version.rb +7 -0
  29. data/lib/doorkeeper-sequel.rb +18 -0
  30. data/lib/generators/doorkeeper/sequel/application_owner_generator.rb +23 -0
  31. data/lib/generators/doorkeeper/sequel/migration_generator.rb +23 -0
  32. data/lib/generators/doorkeeper/sequel/previous_refresh_token_generator.rb +23 -0
  33. data/lib/generators/doorkeeper/sequel/templates/add_owner_to_application.rb +9 -0
  34. data/lib/generators/doorkeeper/sequel/templates/add_previous_refresh_token_to_access_tokens.rb +7 -0
  35. data/lib/generators/doorkeeper/sequel/templates/migration.rb +59 -0
  36. data/spec/controllers/application_metal_controller.rb +10 -0
  37. data/spec/controllers/applications_controller_spec.rb +58 -0
  38. data/spec/controllers/authorizations_controller_spec.rb +189 -0
  39. data/spec/controllers/protected_resources_controller_spec.rb +300 -0
  40. data/spec/controllers/token_info_controller_spec.rb +52 -0
  41. data/spec/controllers/tokens_controller_spec.rb +88 -0
  42. data/spec/dummy/Rakefile +7 -0
  43. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  44. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +7 -0
  45. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  46. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  47. data/spec/dummy/app/controllers/metal_controller.rb +11 -0
  48. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  49. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  50. data/spec/dummy/app/models/user.rb +11 -0
  51. data/spec/dummy/app/views/home/index.html.erb +0 -0
  52. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  53. data/spec/dummy/config/application.rb +29 -0
  54. data/spec/dummy/config/boot.rb +9 -0
  55. data/spec/dummy/config/database.yml +15 -0
  56. data/spec/dummy/config/environment.rb +5 -0
  57. data/spec/dummy/config/environments/development.rb +29 -0
  58. data/spec/dummy/config/environments/production.rb +62 -0
  59. data/spec/dummy/config/environments/test.rb +44 -0
  60. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  61. data/spec/dummy/config/initializers/db.rb +74 -0
  62. data/spec/dummy/config/initializers/doorkeeper.rb +96 -0
  63. data/spec/dummy/config/initializers/secret_token.rb +9 -0
  64. data/spec/dummy/config/initializers/session_store.rb +8 -0
  65. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
  67. data/spec/dummy/config/routes.rb +52 -0
  68. data/spec/dummy/config.ru +4 -0
  69. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  70. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
  71. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +60 -0
  72. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +7 -0
  73. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +11 -0
  74. data/spec/dummy/db/schema.rb +67 -0
  75. data/spec/dummy/log/test.log +19813 -0
  76. data/spec/dummy/public/404.html +26 -0
  77. data/spec/dummy/public/422.html +26 -0
  78. data/spec/dummy/public/500.html +26 -0
  79. data/spec/dummy/public/favicon.ico +0 -0
  80. data/spec/dummy/script/rails +6 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-T/-TZF6Ae6YipbyKuHghb9wlTx4_b9itbSHRc_2PmqjiU.cache +1 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0p/0pa3wNbGHqFC6gxrMvdOJiP6gPwFv9VJ_npjEfRWxAE.cache +1 -0
  83. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2e/2eYh115US2lIRhM2KTEaJFa6aV_cX8iv6JAdjuq0Uio.cache +1 -0
  84. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3P/3PoguHEOEeItUjmwC74MWLLP-_Ijow7798bF5U6K2dw.cache +1 -0
  85. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6b/6b0anrSo7Fvoc05t4Ca0zZmfS_cpERy1DsG3ea6lBOg.cache +0 -0
  86. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/BA/BAC3ZaGoeZ9Od-kKg-UQYelvRgsCa0H72-52nLdcTNw.cache +1 -0
  87. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Bw/Bw6Nimjvy5Yv1AYbZb1t-v0eMNhv-bhwBzR-b5mY7FU.cache +0 -0
  88. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Fq/FqQWjMAz8yjZQlMC_dUsztaOxGruI2IXyGAAUF9SvQ0.cache +1 -0
  89. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/J_/J_D9clwKidN28hnVB1O3zEfKDwg90Usdb5ToKiPq_aw.cache +0 -0
  90. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ji/JitNKkP1dYdu9ObSdIkkEAsiFxEmRO5oy1UIyhT_hYs.cache +0 -0
  91. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Jq/JqTLVvnY2AgGkHftWPwqt_HkbwhYRsmgHxk37VqKJAY.cache +0 -0
  92. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QX/QXcp8DweOJ6BfMedGMfeHvVXv2hjDIleln1LSJk7vOE.cache +2 -0
  93. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Qy/Qy1ldbz6vKa_fv4E4ByxWslKFoV1qReQR5DKJ525z88.cache +1 -0
  94. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rl/RlCJ_X5xFsE3VBDhkYrY7r_R6sMgiAc03cT8nr7Q2vY.cache +0 -0
  95. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ta/TaYxNn81MhqC3DnMC6_y_Q7xap5Ntn4ggFo94EUaiak.cache +0 -0
  96. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wq/WqbLVKOcTMZtttygYt_ncr1mGIDrzevSTaPGNmzV1D8.cache +1 -0
  97. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/YF/YF60qiQ28QMoYDrLmrbHWZr7X7bl5MxVPR5QrrVCFak.cache +1 -0
  98. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Yf/YfJJZvm_NONHd4eCasDibCcRapZ_WYIO5MUxSUUbYFk.cache +0 -0
  99. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Z0/Z0e47cT2a-21U-w-3gkbgqC3o5jWnEzOB8vW06aJH1E.cache +0 -0
  100. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_u/_uy-z8SVnhffUNelRxbPDL2aAUPb_GbqREXVsfy8uGc.cache +0 -0
  101. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/dL/dL7SLUWUIeVdyA1UuH-rvif0nzesOar3LdEtqzdb4bE.cache +0 -0
  102. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/f8/f8WT8jqR1qNIdQaRDpXbyLN7E5AWkbYFBwdh9Ozk7gk.cache +1 -0
  103. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hk/hk2YB6skvc72qL4IzzQKU8Emyfe5vARjoD1bvQTw4zE.cache +1 -0
  104. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/iO/iOpDp_7ZvBNO5WIpTmqNewUl9bB2satqXWulyNvAaX8.cache +0 -0
  105. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ii/iiJRBZIsxKiwyzU_Z7UtQeUTXMRJRPTreTKRvAWO7_8.cache +1 -0
  106. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mj/mjuMepngMLrtgilLlJ9oTTSqoGO1YUww1rXphQ1pOm4.cache +0 -0
  107. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qo/qo6SpT75QykYB63Aqq5bgzpXyNU1Y4dGFvCCJgoWQpE.cache +1 -0
  108. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sp/sprzBMBliJDI__s-0D3q82tn1MpBkFV0N651hTr3XE8.cache +1 -0
  109. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tM/tM6A7CR8QluP_u4u59vN1GjSZGNqNH3TXkkNzb9EPXA.cache +0 -0
  110. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vO/vOXN0mER62j4JiPpMTSVS7MMqs0067cZx14vD5B8qiQ.cache +0 -0
  111. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zz/zzlQ_kom0liFOvGYDcjtVw6yAHOyA-bbzP8f0e_Tq1A.cache +1 -0
  112. data/spec/factories.rb +28 -0
  113. data/spec/generators/application_owner_generator_spec.rb +20 -0
  114. data/spec/generators/migration_generator_spec.rb +20 -0
  115. data/spec/generators/previous_refresh_token_generator_spec.rb +20 -0
  116. data/spec/generators/templates/routes.rb +3 -0
  117. data/spec/generators/tmp/dummy/db/migrate/20161012132809_create_doorkeeper_tables.rb +59 -0
  118. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +24 -0
  119. data/spec/lib/config_spec.rb +334 -0
  120. data/spec/lib/doorkeeper_spec.rb +28 -0
  121. data/spec/lib/models/expirable_spec.rb +51 -0
  122. data/spec/lib/models/revocable_spec.rb +59 -0
  123. data/spec/lib/models/scopes_spec.rb +43 -0
  124. data/spec/lib/oauth/authorization/uri_builder_spec.rb +42 -0
  125. data/spec/lib/oauth/authorization_code_request_spec.rb +80 -0
  126. data/spec/lib/oauth/client/credentials_spec.rb +47 -0
  127. data/spec/lib/oauth/client/methods_spec.rb +54 -0
  128. data/spec/lib/oauth/client_credentials/creator_spec.rb +44 -0
  129. data/spec/lib/oauth/client_credentials/issuer_spec.rb +86 -0
  130. data/spec/lib/oauth/client_credentials/validation_spec.rb +54 -0
  131. data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
  132. data/spec/lib/oauth/client_credentials_request_spec.rb +104 -0
  133. data/spec/lib/oauth/client_spec.rb +39 -0
  134. data/spec/lib/oauth/code_request_spec.rb +45 -0
  135. data/spec/lib/oauth/code_response_spec.rb +34 -0
  136. data/spec/lib/oauth/error_response_spec.rb +61 -0
  137. data/spec/lib/oauth/error_spec.rb +23 -0
  138. data/spec/lib/oauth/forbidden_token_response_spec.rb +23 -0
  139. data/spec/lib/oauth/helpers/scope_checker_spec.rb +64 -0
  140. data/spec/lib/oauth/helpers/unique_token_spec.rb +20 -0
  141. data/spec/lib/oauth/helpers/uri_checker_spec.rb +104 -0
  142. data/spec/lib/oauth/invalid_token_response_spec.rb +28 -0
  143. data/spec/lib/oauth/password_access_token_request_spec.rb +90 -0
  144. data/spec/lib/oauth/pre_authorization_spec.rb +155 -0
  145. data/spec/lib/oauth/refresh_token_request_spec.rb +154 -0
  146. data/spec/lib/oauth/scopes_spec.rb +122 -0
  147. data/spec/lib/oauth/token_request_spec.rb +98 -0
  148. data/spec/lib/oauth/token_response_spec.rb +85 -0
  149. data/spec/lib/oauth/token_spec.rb +116 -0
  150. data/spec/lib/request/strategy_spec.rb +53 -0
  151. data/spec/lib/server_spec.rb +52 -0
  152. data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
  153. data/spec/models/doorkeeper/access_token_spec.rb +394 -0
  154. data/spec/models/doorkeeper/application_spec.rb +179 -0
  155. data/spec/requests/applications/applications_request_spec.rb +94 -0
  156. data/spec/requests/applications/authorized_applications_spec.rb +30 -0
  157. data/spec/requests/endpoints/authorization_spec.rb +72 -0
  158. data/spec/requests/endpoints/token_spec.rb +64 -0
  159. data/spec/requests/flows/authorization_code_errors_spec.rb +66 -0
  160. data/spec/requests/flows/authorization_code_spec.rb +156 -0
  161. data/spec/requests/flows/client_credentials_spec.rb +58 -0
  162. data/spec/requests/flows/implicit_grant_errors_spec.rb +32 -0
  163. data/spec/requests/flows/implicit_grant_spec.rb +61 -0
  164. data/spec/requests/flows/password_spec.rb +115 -0
  165. data/spec/requests/flows/refresh_token_spec.rb +174 -0
  166. data/spec/requests/flows/revoke_token_spec.rb +157 -0
  167. data/spec/requests/flows/skip_authorization_spec.rb +59 -0
  168. data/spec/requests/protected_resources/metal_spec.rb +14 -0
  169. data/spec/requests/protected_resources/private_api_spec.rb +81 -0
  170. data/spec/routing/custom_controller_routes_spec.rb +71 -0
  171. data/spec/routing/default_routes_spec.rb +35 -0
  172. data/spec/routing/scoped_routes_spec.rb +31 -0
  173. data/spec/spec_helper.rb +2 -0
  174. data/spec/spec_helper_integration.rb +50 -0
  175. data/spec/stubs/config/application.rb +29 -0
  176. data/spec/stubs/config/initializers/db.rb +74 -0
  177. data/spec/stubs/generators/application_owner_generator_spec.rb +20 -0
  178. data/spec/stubs/generators/migration_generator_spec.rb +20 -0
  179. data/spec/stubs/generators/previous_refresh_token_generator_spec.rb +20 -0
  180. data/spec/stubs/generators/tmp/dummy/db/migrate/20161012132810_add_owner_to_application.rb +9 -0
  181. data/spec/stubs/models/user.rb +11 -0
  182. data/spec/stubs/spec_helper_integration.rb +50 -0
  183. data/spec/stubs/support/sequel.rb +0 -0
  184. data/spec/support/dependencies/factory_girl.rb +2 -0
  185. data/spec/support/helpers/access_token_request_helper.rb +11 -0
  186. data/spec/support/helpers/authorization_request_helper.rb +41 -0
  187. data/spec/support/helpers/config_helper.rb +9 -0
  188. data/spec/support/helpers/model_helper.rb +67 -0
  189. data/spec/support/helpers/request_spec_helper.rb +76 -0
  190. data/spec/support/helpers/url_helper.rb +55 -0
  191. data/spec/support/http_method_shim.rb +24 -0
  192. data/spec/support/orm/active_record.rb +3 -0
  193. data/spec/support/orm/sequel.rb +0 -0
  194. data/spec/support/shared/controllers_shared_context.rb +69 -0
  195. data/spec/support/shared/models_shared_examples.rb +52 -0
  196. data/spec/validators/redirect_uri_validator_spec.rb +78 -0
  197. metadata +570 -0
@@ -0,0 +1,189 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
4
+ include AuthorizationRequestHelper
5
+
6
+ def fragments(param)
7
+ fragment = URI.parse(response.location).fragment
8
+ Rack::Utils.parse_query(fragment)[param]
9
+ end
10
+
11
+ def translated_error_message(key)
12
+ I18n.translate key, scope: [:doorkeeper, :errors, :messages]
13
+ end
14
+
15
+ let(:client) { FactoryGirl.create :application }
16
+ let(:user) { User.create!(name: 'Joe', password: 'sekret') }
17
+
18
+ before do
19
+ allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["implicit"])
20
+ allow(controller).to receive(:current_resource_owner).and_return(user)
21
+ end
22
+
23
+ describe 'POST #create' do
24
+ before do
25
+ post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
26
+ end
27
+
28
+ it 'redirects after authorization' do
29
+ expect(response).to be_redirect
30
+ end
31
+
32
+ it 'redirects to client redirect uri' do
33
+ expect(response.location).to match(%r{^#{client.redirect_uri}})
34
+ end
35
+
36
+ it 'includes access token in fragment' do
37
+ expect(fragments('access_token')).to eq(Doorkeeper::AccessToken.first.token)
38
+ end
39
+
40
+ it 'includes token type in fragment' do
41
+ expect(fragments('token_type')).to eq('bearer')
42
+ end
43
+
44
+ it 'includes token expiration in fragment' do
45
+ expect(fragments('expires_in').to_i).to eq(2.hours.to_i)
46
+ end
47
+
48
+ it 'issues the token for the current client' do
49
+ expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
50
+ end
51
+
52
+ it 'issues the token for the current resource owner' do
53
+ expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
54
+ end
55
+ end
56
+
57
+ describe 'POST #create with errors' do
58
+ before do
59
+ default_scopes_exist :public
60
+ post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri
61
+ end
62
+
63
+ it 'redirects after authorization' do
64
+ expect(response).to be_redirect
65
+ end
66
+
67
+ it 'redirects to client redirect uri' do
68
+ expect(response.location).to match(%r{^#{client.redirect_uri}})
69
+ end
70
+
71
+ it 'does not include access token in fragment' do
72
+ expect(fragments('access_token')).to be_nil
73
+ end
74
+
75
+ it 'includes error in fragment' do
76
+ expect(fragments('error')).to eq('invalid_scope')
77
+ end
78
+
79
+ it 'includes error description in fragment' do
80
+ expect(fragments('error_description')).to eq(translated_error_message(:invalid_scope))
81
+ end
82
+
83
+ it 'does not issue any access token' do
84
+ expect(Doorkeeper::AccessToken.all).to be_empty
85
+ end
86
+ end
87
+
88
+ describe 'POST #create with application already authorized' do
89
+ it 'returns the existing access token in a fragment'
90
+ end
91
+
92
+ describe 'GET #new token request with native url and skip_authorization true' do
93
+ before do
94
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
95
+ true
96
+ end)
97
+ client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
98
+ get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
99
+ end
100
+
101
+ it 'should redirect immediately' do
102
+ expect(response).to be_redirect
103
+ expect(response.location).to match(/oauth\/token\/info\?access_token=/)
104
+ end
105
+
106
+ it 'should not issue a grant' do
107
+ expect(Doorkeeper::AccessGrant.count).to be 0
108
+ end
109
+
110
+ it 'should issue a token' do
111
+ expect(Doorkeeper::AccessToken.count).to be 1
112
+ end
113
+ end
114
+
115
+ describe 'GET #new code request with native url and skip_authorization true' do
116
+ before do
117
+ allow(Doorkeeper.configuration).to receive(:grant_flows).
118
+ and_return(%w(authorization_code))
119
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
120
+ true
121
+ end)
122
+ client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
123
+ get :new, client_id: client.uid, response_type: 'code', redirect_uri: client.redirect_uri
124
+ end
125
+
126
+ it 'should redirect immediately' do
127
+ expect(response).to be_redirect
128
+ expect(response.location).to match(/oauth\/authorize\//)
129
+ end
130
+
131
+ it 'should issue a grant' do
132
+ expect(Doorkeeper::AccessGrant.count).to be 1
133
+ end
134
+
135
+ it 'should not issue a token' do
136
+ expect(Doorkeeper::AccessToken.count).to be 0
137
+ end
138
+ end
139
+
140
+ describe 'GET #new with skip_authorization true' do
141
+ before do
142
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
143
+ true
144
+ end)
145
+ get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
146
+ end
147
+
148
+ it 'should redirect immediately' do
149
+ expect(response).to be_redirect
150
+ expect(response.location).to match(%r{^#{client.redirect_uri}})
151
+ end
152
+
153
+ it 'should issue a token' do
154
+ expect(Doorkeeper::AccessToken.count).to be 1
155
+ end
156
+
157
+ it 'includes token type in fragment' do
158
+ expect(fragments('token_type')).to eq('bearer')
159
+ end
160
+
161
+ it 'includes token expiration in fragment' do
162
+ expect(fragments('expires_in').to_i).to eq(2.hours.to_i)
163
+ end
164
+
165
+ it 'issues the token for the current client' do
166
+ expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
167
+ end
168
+
169
+ it 'issues the token for the current resource owner' do
170
+ expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
171
+ end
172
+ end
173
+
174
+ describe 'GET #new with errors' do
175
+ before do
176
+ default_scopes_exist :public
177
+ get :new, an_invalid: 'request'
178
+ end
179
+
180
+ it 'does not redirect' do
181
+ expect(response).to_not be_redirect
182
+ end
183
+
184
+ it 'does not issue any token' do
185
+ expect(Doorkeeper::AccessGrant.count).to eq 0
186
+ expect(Doorkeeper::AccessToken.count).to eq 0
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,300 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module ControllerActions
4
+ def index
5
+ render plain: 'index'
6
+ end
7
+
8
+ def show
9
+ render plain: 'show'
10
+ end
11
+
12
+ def doorkeeper_unauthorized_render_options(*)
13
+ end
14
+
15
+ def doorkeeper_forbidden_render_options(*)
16
+ end
17
+ end
18
+
19
+ describe 'doorkeeper authorize filter' do
20
+ context 'accepts token code specified as' do
21
+ controller do
22
+ before_action :doorkeeper_authorize!
23
+
24
+ def index
25
+ render plain: 'index'
26
+ end
27
+ end
28
+
29
+ let(:token_string) { '1A2BC3' }
30
+ let(:token) do
31
+ double(Doorkeeper::AccessToken,
32
+ acceptable?: true, previous_refresh_token: "",
33
+ revoke_previous_refresh_token!: true)
34
+ end
35
+
36
+ it 'access_token param' do
37
+ expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
38
+ get :index, access_token: token_string
39
+ end
40
+
41
+ it 'bearer_token param' do
42
+ expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
43
+ get :index, bearer_token: token_string
44
+ end
45
+
46
+ it 'Authorization header' do
47
+ expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
48
+ request.env['HTTP_AUTHORIZATION'] = "Bearer #{token_string}"
49
+ get :index
50
+ end
51
+
52
+ it 'different kind of Authorization header' do
53
+ expect(Doorkeeper::AccessToken).not_to receive(:by_token)
54
+ request.env['HTTP_AUTHORIZATION'] = "MAC #{token_string}"
55
+ get :index
56
+ end
57
+
58
+ it 'does not change Authorization header value' do
59
+ expect(Doorkeeper::AccessToken).to receive(:by_token).exactly(2).times.and_return(token)
60
+ request.env['HTTP_AUTHORIZATION'] = "Bearer #{token_string}"
61
+ get :index
62
+ controller.send(:remove_instance_variable, :@_doorkeeper_token)
63
+ get :index
64
+ end
65
+ end
66
+
67
+ context 'defined for all actions' do
68
+ controller do
69
+ before_action :doorkeeper_authorize!
70
+
71
+ include ControllerActions
72
+ end
73
+
74
+ context 'with valid token', token: :valid do
75
+ it 'allows into index action' do
76
+ get :index, access_token: token_string
77
+ expect(response).to be_success
78
+ end
79
+
80
+ it 'allows into show action' do
81
+ get :show, id: '4', access_token: token_string
82
+ expect(response).to be_success
83
+ end
84
+ end
85
+
86
+ context 'with invalid token', token: :invalid do
87
+ it 'does not allow into index action' do
88
+ get :index, access_token: token_string
89
+ expect(response.status).to eq 401
90
+ expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
91
+ end
92
+
93
+ it 'does not allow into show action' do
94
+ get :show, id: '4', access_token: token_string
95
+ expect(response.status).to eq 401
96
+ expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
97
+ end
98
+ end
99
+ end
100
+
101
+ context 'defined with scopes' do
102
+ controller do
103
+ before_action -> { doorkeeper_authorize! :write }
104
+
105
+ include ControllerActions
106
+ end
107
+
108
+ let(:token_string) { '1A2DUWE' }
109
+
110
+ it 'allows if the token has particular scopes' do
111
+ token = double(Doorkeeper::AccessToken,
112
+ accessible?: true, scopes: %w(write public),
113
+ previous_refresh_token: "",
114
+ revoke_previous_refresh_token!: true)
115
+ expect(token).to receive(:acceptable?).with([:write]).and_return(true)
116
+ expect(
117
+ Doorkeeper::AccessToken
118
+ ).to receive(:by_token).with(token_string).and_return(token)
119
+ get :index, access_token: token_string
120
+ expect(response).to be_success
121
+ end
122
+
123
+ it 'does not allow if the token does not include given scope' do
124
+ token = double(Doorkeeper::AccessToken,
125
+ accessible?: true, scopes: ['public'], revoked?: false,
126
+ expired?: false, previous_refresh_token: "",
127
+ revoke_previous_refresh_token!: true)
128
+ expect(
129
+ Doorkeeper::AccessToken
130
+ ).to receive(:by_token).with(token_string).and_return(token)
131
+ expect(token).to receive(:acceptable?).with([:write]).and_return(false)
132
+ get :index, access_token: token_string
133
+ expect(response.status).to eq 403
134
+ expect(response.header).to_not include('WWW-Authenticate')
135
+ end
136
+ end
137
+
138
+ context 'when custom unauthorized render options are configured' do
139
+ controller do
140
+ before_action :doorkeeper_authorize!
141
+
142
+ include ControllerActions
143
+ end
144
+
145
+ context 'with a JSON custom render', token: :invalid do
146
+ before do
147
+ module ControllerActions
148
+ remove_method :doorkeeper_unauthorized_render_options
149
+ def doorkeeper_unauthorized_render_options(error: nil)
150
+ { json: ActiveSupport::JSON.encode(error_message: error.description) }
151
+ end
152
+ end
153
+ end
154
+ after do
155
+ module ControllerActions
156
+ remove_method :doorkeeper_unauthorized_render_options
157
+ def doorkeeper_unauthorized_render_options(error: nil)
158
+ end
159
+ end
160
+ end
161
+
162
+ it 'it renders a custom JSON response', token: :invalid do
163
+ get :index, access_token: token_string
164
+ expect(response.status).to eq 401
165
+ expect(response.content_type).to eq('application/json')
166
+ expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
167
+ parsed_body = JSON.parse(response.body)
168
+ expect(parsed_body).not_to be_nil
169
+ expect(parsed_body['error_message']).to match('token is invalid')
170
+ end
171
+ end
172
+
173
+ context 'with a text custom render', token: :invalid do
174
+ before do
175
+ module ControllerActions
176
+ remove_method :doorkeeper_unauthorized_render_options
177
+ def doorkeeper_unauthorized_render_options(error: nil)
178
+ { plain: 'Unauthorized' }
179
+ end
180
+ end
181
+ end
182
+ after do
183
+ module ControllerActions
184
+ remove_method :doorkeeper_unauthorized_render_options
185
+ def doorkeeper_unauthorized_render_options(error: nil)
186
+ end
187
+ end
188
+ end
189
+
190
+ it 'it renders a custom text response', token: :invalid do
191
+ get :index, access_token: token_string
192
+ expect(response.status).to eq 401
193
+ expect(response.content_type).to eq('text/plain')
194
+ expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
195
+ expect(response.body).to eq('Unauthorized')
196
+ end
197
+ end
198
+ end
199
+
200
+ context 'when custom forbidden render options are configured' do
201
+ before do
202
+ expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
203
+ expect(token).to receive(:acceptable?).with([:write]).and_return(false)
204
+ end
205
+
206
+ after do
207
+ module ControllerActions
208
+ remove_method :doorkeeper_forbidden_render_options
209
+ def doorkeeper_forbidden_render_options(*)
210
+ end
211
+ end
212
+ end
213
+
214
+ controller do
215
+ before_action -> { doorkeeper_authorize! :write }
216
+
217
+ include ControllerActions
218
+ end
219
+
220
+ let(:token) do
221
+ double(Doorkeeper::AccessToken,
222
+ accessible?: true, scopes: ['public'], revoked?: false,
223
+ expired?: false, previous_refresh_token: "",
224
+ revoke_previous_refresh_token!: true)
225
+ end
226
+ let(:token_string) { '1A2DUWE' }
227
+
228
+ context 'with a JSON custom render' do
229
+ before do
230
+ module ControllerActions
231
+ remove_method :doorkeeper_forbidden_render_options
232
+ def doorkeeper_forbidden_render_options(*)
233
+ { json: { error_message: 'Forbidden' } }
234
+ end
235
+ end
236
+ end
237
+
238
+ it 'renders a custom JSON response' do
239
+ get :index, access_token: token_string
240
+ expect(response.header).to_not include('WWW-Authenticate')
241
+ expect(response.content_type).to eq('application/json')
242
+ expect(response.status).to eq 403
243
+ parsed_body = JSON.parse(response.body)
244
+ expect(parsed_body).not_to be_nil
245
+ expect(parsed_body['error_message']).to match('Forbidden')
246
+ end
247
+ end
248
+
249
+ context 'with a status and JSON custom render' do
250
+ before do
251
+ module ControllerActions
252
+ remove_method :doorkeeper_forbidden_render_options
253
+ def doorkeeper_forbidden_render_options(*)
254
+ { json: { error_message: 'Not Found' },
255
+ respond_not_found_when_forbidden: true }
256
+ end
257
+ end
258
+ end
259
+
260
+ it 'overrides the default status code' do
261
+ get :index, access_token: token_string
262
+ expect(response.status).to eq 404
263
+ end
264
+ end
265
+
266
+ context 'with a text custom render' do
267
+ before do
268
+ module ControllerActions
269
+ remove_method :doorkeeper_forbidden_render_options
270
+ def doorkeeper_forbidden_render_options(*)
271
+ { plain: 'Forbidden' }
272
+ end
273
+ end
274
+ end
275
+
276
+ it 'renders a custom status code and text response' do
277
+ get :index, access_token: token_string
278
+ expect(response.header).to_not include('WWW-Authenticate')
279
+ expect(response.status).to eq 403
280
+ expect(response.body).to eq('Forbidden')
281
+ end
282
+ end
283
+
284
+ context 'with a status and text custom render' do
285
+ before do
286
+ module ControllerActions
287
+ remove_method :doorkeeper_forbidden_render_options
288
+ def doorkeeper_forbidden_render_options(*)
289
+ { respond_not_found_when_forbidden: true, plain: 'Not Found' }
290
+ end
291
+ end
292
+ end
293
+
294
+ it 'overrides the default status code' do
295
+ get :index, access_token: token_string
296
+ expect(response.status).to eq 404
297
+ end
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Doorkeeper::TokenInfoController do
4
+ describe 'when requesting tokeninfo with valid token' do
5
+ let(:doorkeeper_token) { FactoryGirl.create(:access_token) }
6
+
7
+ before(:each) do
8
+ allow(controller).to receive(:doorkeeper_token) { doorkeeper_token }
9
+ end
10
+
11
+ def do_get
12
+ get :show
13
+ end
14
+
15
+ describe 'successful request' do
16
+
17
+ it 'responds with tokeninfo' do
18
+ do_get
19
+ expect(response.body).to eq(doorkeeper_token.to_json)
20
+ end
21
+
22
+ it 'responds with a 200 status' do
23
+ do_get
24
+ expect(response.status).to eq 200
25
+ end
26
+ end
27
+
28
+ describe 'invalid token response' do
29
+ before(:each) do
30
+ allow(controller).to receive(:doorkeeper_token).and_return(nil)
31
+ end
32
+ it 'responds with 401 when doorkeeper_token is not valid' do
33
+ do_get
34
+ expect(response.status).to eq 401
35
+ expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
36
+ end
37
+
38
+ it 'responds with 401 when doorkeeper_token is invalid, expired or revoked' do
39
+ allow(controller).to receive(:doorkeeper_token).and_return(doorkeeper_token)
40
+ allow(doorkeeper_token).to receive(:accessible?).and_return(false)
41
+ do_get
42
+ expect(response.status).to eq 401
43
+ expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
44
+ end
45
+
46
+ it 'responds body message for error' do
47
+ do_get
48
+ expect(response.body).to eq(Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Doorkeeper::TokensController do
4
+ describe 'when authorization has succeeded' do
5
+ let :token do
6
+ double(:token, authorize: true)
7
+ end
8
+
9
+ before do
10
+ allow(controller).to receive(:token) { token }
11
+ end
12
+
13
+ it 'returns the authorization' do
14
+ skip 'verify need of these specs'
15
+
16
+ expect(token).to receive(:authorization)
17
+
18
+ post :create
19
+ end
20
+ end
21
+
22
+ describe 'when authorization has failed' do
23
+ it 'returns the error response' do
24
+ token = double(:token, authorize: false)
25
+ allow(controller).to receive(:token) { token }
26
+
27
+ post :create
28
+
29
+ expect(response.status).to eq 401
30
+ expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
31
+ end
32
+ end
33
+
34
+ describe 'when there is a failure due to a custom error' do
35
+ it 'returns the error response with a custom message' do
36
+ # I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
37
+ custom_message = "my_message"
38
+ allow(I18n).to receive(:translate).
39
+ with(
40
+ custom_message,
41
+ hash_including(scope: [:doorkeeper, :errors, :messages]),
42
+ ).
43
+ and_return('Authorization custom message')
44
+
45
+ doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
46
+
47
+ strategy = double(:strategy)
48
+ request = double(token_request: strategy)
49
+ allow(strategy).to receive(:authorize).and_raise(doorkeeper_error)
50
+ allow(controller).to receive(:server).and_return(request)
51
+
52
+ post :create
53
+
54
+ expected_response_body = {
55
+ "error" => custom_message,
56
+ "error_description" => "Authorization custom message"
57
+ }
58
+ expect(response.status).to eq 401
59
+ expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
60
+ expect(JSON.load(response.body)).to eq expected_response_body
61
+ end
62
+ end
63
+
64
+ describe 'when revoke authorization has failed' do
65
+ # http://tools.ietf.org/html/rfc7009#section-2.2
66
+ it 'returns no error response' do
67
+ token = double(:token, authorize: false, application_id?: true)
68
+ allow(controller).to receive(:token) { token }
69
+
70
+ post :revoke
71
+
72
+ expect(response.status).to eq 200
73
+ end
74
+ end
75
+
76
+ describe 'authorize response memoization' do
77
+ it "memoizes the result of the authorization" do
78
+ strategy = double(:strategy, authorize: true)
79
+ expect(strategy).to receive(:authorize).once
80
+ allow(controller).to receive(:strategy) { strategy }
81
+ allow(controller).to receive(:create) do
82
+ controller.send :authorize_response
83
+ end
84
+
85
+ post :create
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,7 @@
1
+ class CustomAuthorizationsController < ::ApplicationController
2
+ %w(index show new create edit update destroy).each do |action|
3
+ define_method action do
4
+ render nothing: true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class FullProtectedResourcesController < ApplicationController
2
+ before_action -> { doorkeeper_authorize! :write, :admin }, only: :show
3
+ before_action :doorkeeper_authorize!, only: :index
4
+
5
+ def index
6
+ render plain: 'index'
7
+ end
8
+
9
+ def show
10
+ render plain: 'show'
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ class HomeController < ApplicationController
2
+ def index
3
+ end
4
+
5
+ def sign_in
6
+ session[:user_id] = if Rails.env.development?
7
+ User.first || User.create!(name: 'Joe', password: 'sekret')
8
+ else
9
+ User.first
10
+ end
11
+ redirect_to '/'
12
+ end
13
+
14
+ def callback
15
+ render plain: 'ok'
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class MetalController < ActionController::Metal
2
+ include AbstractController::Callbacks
3
+ include ActionController::Head
4
+ include Doorkeeper::Rails::Helpers
5
+
6
+ before_action :doorkeeper_authorize!
7
+
8
+ def index
9
+ self.response_body = { ok: true }.to_json
10
+ end
11
+ end