doorkeeper-mongodb 5.3.0 → 5.5.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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/Rakefile +18 -4
  4. data/lib/doorkeeper/orm/mongoid9/access_grant.rb +26 -0
  5. data/lib/doorkeeper/orm/mongoid9/access_token.rb +38 -0
  6. data/lib/doorkeeper/orm/mongoid9/application.rb +43 -0
  7. data/lib/doorkeeper/orm/mongoid9/stale_records_cleaner.rb +11 -0
  8. data/lib/doorkeeper/orm/mongoid9.rb +50 -0
  9. data/lib/doorkeeper-mongodb/mixins/mongoid/access_grant_mixin.rb +6 -2
  10. data/lib/doorkeeper-mongodb/mixins/mongoid/access_token_mixin.rb +46 -6
  11. data/lib/doorkeeper-mongodb/mixins/mongoid/application_mixin.rb +2 -2
  12. data/lib/doorkeeper-mongodb/version.rb +1 -1
  13. data/lib/doorkeeper-mongodb.rb +1 -0
  14. data/spec/dummy/app/assets/config/manifest.js +0 -0
  15. data/spec/dummy/app/controllers/application_controller.rb +0 -0
  16. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -0
  17. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -0
  18. data/spec/dummy/app/controllers/home_controller.rb +0 -0
  19. data/spec/dummy/app/controllers/metal_controller.rb +0 -0
  20. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -0
  21. data/spec/dummy/app/helpers/application_helper.rb +0 -0
  22. data/spec/dummy/app/views/home/index.html.erb +0 -0
  23. data/spec/dummy/app/views/layouts/application.html.erb +0 -0
  24. data/spec/dummy/config/application.rb +0 -0
  25. data/spec/dummy/config/boot.rb +0 -0
  26. data/spec/dummy/config/database.yml +0 -0
  27. data/spec/dummy/config/environment.rb +0 -0
  28. data/spec/dummy/config/environments/development.rb +0 -0
  29. data/spec/dummy/config/environments/production.rb +0 -0
  30. data/spec/dummy/config/environments/test.rb +0 -0
  31. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -0
  32. data/spec/dummy/config/initializers/doorkeeper.rb +7 -2
  33. data/spec/dummy/config/initializers/secret_token.rb +0 -0
  34. data/spec/dummy/config/initializers/session_store.rb +0 -0
  35. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -0
  36. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -0
  37. data/spec/dummy/config/mongoid8.yml +19 -0
  38. data/spec/dummy/config/mongoid9.yml +19 -0
  39. data/spec/dummy/config/routes.rb +0 -0
  40. data/spec/dummy/config.ru +1 -1
  41. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -0
  42. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -0
  43. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -0
  44. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -0
  45. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -0
  46. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -0
  47. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -0
  48. data/spec/dummy/db/migrate/20230205064514_add_custom_attributes.rb +8 -0
  49. data/spec/dummy/db/schema.rb +3 -1
  50. data/spec/dummy/log/test.log +39440 -0
  51. data/spec/dummy/public/404.html +0 -0
  52. data/spec/dummy/public/422.html +0 -0
  53. data/spec/dummy/public/500.html +0 -0
  54. data/spec/dummy/public/favicon.ico +0 -0
  55. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/2L/2LdlR-88TqZc8vSU7Z58xiNpCGRZj0CIlOxSN4Vx2i4.cache +1 -0
  56. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{Pn/PnXU_mkG2fLZFm9BwiZ03BZdBTjKuInP-cRXjHS7yJo.cache → 2r/2r0L9eNOmETsg4Tm1IgBdw3J4ahcko41NpILRXu19_A.cache} +0 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/5y/5ywocFQgpSY36nyF_xDKPExhDRo-eqeiqfDvQee1K9k.cache +2 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{Qs/QsVgO6vM5Yn9oeYTYlrqtyVnK6sdVDWDa083N7zpfHw.cache → 8r/8rW0CpDDUJZ7xvg86t6jZ6WmyvaVZ0uTPEPRjghFIKo.cache} +0 -0
  59. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{PA/PAH_jI20wRw12tngeJ-V619c30avNLDu5U9Z-9Pc5SQ.cache → Cs/CsfBL8Dls9-jhjFsNYt4DZxu5LWChDMB-xXKjsEFSsU.cache} +0 -0
  60. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{8D/8DJG7JfPvShfLLyeSom6NZ_TcQc6QH27tJ7prEWZPfI.cache → Cv/Cv9WXE_0OqtPUZBXfTWaE8uKx9oFIzqO18ZkwVaBLSg.cache} +0 -0
  61. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Mf/MfB2-0nbsmC548XBSLftafi6BZ9nAquBA-6eu7mAmdE.cache +2 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/N2/N2cUP-Um_nQ5ZTCQr_H0bKIjOSIyV7Ry5sT6-DB9e4A.cache +1 -0
  63. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{FJ/FJlQpfMtpRbrM5P8A7d2FAelFKwo6GrVs2xks8z5GKU.cache → Ot/OtNAnT3d-csAKBtJ8UBLOSwUDyfmOdCWpS08RaSCGsQ.cache} +0 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/P3/P33RwiTMGEu2wZySBEUmf5U7hnfBhdL49wzdUWXYNRs.cache +1 -0
  65. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/RZ/RZAL9gIt4aD731Ikf7UZZNPSZXzhPqtDskLB7nQcWH4.cache +1 -0
  66. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/SQ/SQVJeYO2bM0qgQiOaeVBjYo3SWQZmvixa3tXUjsmuUs.cache +0 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{Ma/MaK3K1AoZZ4xM5fOOifhROd73hfZJpP4yGbkGdoYtEk.cache → V2/V2JApVhUSYhvWnNVIbpe58U4xheVkpi0gCStqjDN6-A.cache} +0 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{Lk/LklIq5hrBAPESXVUpFMwQ9L-1qTj90sPVi6U19_Xi-Q.cache → VA/VADOUaZFukufOb44ts4KoyQZumPcVJET0bi9RvC7c-o.cache} +1 -1
  69. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Vz/VzdPLfWn16XbpHNJdkDMamAf3QutM29cvvPkDNyy5nE.cache +1 -0
  70. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/W9/W9QfraySVwoRt-SgGOIS0e-iP8R1qP_URwXZw1l6M5E.cache +0 -0
  71. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Wy/Wyiw07ngOzgV6RPis_Lo2hhSRkwo2YSqKTEDAF0crhA.cache +0 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Z6/Z6rAtdVt3OXS26vLVCtdO3vmMlttI3ajdpbC2FHk7iQ.cache +0 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/b6/b6QRH6ZdCc0e6bUWu4qni_kZmptaMgWciO8Jl9q6_p8.cache +0 -0
  74. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{Pm/PmheG0PGFqDws1qgFOxOyIL-gpMof3Ar9eSRKVLYuik.cache → fP/fPihom3hnc1rQQxpviTvZPRJB_IghWYWP3dDcsGrcLk.cache} +0 -0
  75. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gD/gDU38plXvosMgFK47_PBI9xGVsmsE2tShWEZzxiek3k.cache +1 -0
  76. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/gR/gRqL5_jaFW7eA3d2frJmOzw_vFLuvfhwMhotAlsO8J4.cache +2 -0
  77. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/jC/jCTZ1jAldKBn4OTANBBmCKzxLrDgok1ur4meoTqlDNg.cache +0 -0
  78. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{yN/yNOFGOsnHmxXNMkuEAWuL1u3jlmdvrdeoTx6DDJ1in8.cache → jc/jcB8w1gBT7JP10DW4OOvvYpW1ZFeMyedngmMy3QbRLQ.cache} +0 -0
  79. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/jg/jgxXkkkXf1NPOPrpNdEJzhDt-2xHGzd_-mLkIHWrOr4.cache +2 -0
  80. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/nx/nxzZnvk5YyBhTUloQSZZ5zRuaqlsLiHy_AbOzQ3d788.cache +0 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/wr/wrlf8nUW2yftpcIA97qImyECR8f8o3OiOdHLdfkmw8c.cache +1 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/{qT/qTQIQsmS0Wbbg2JxNn9rxdI5qVOTg5SfyQdaTvr9vLo.cache → xd/xdD4KJ55W3jy5PIrwT0UnDp1toKpUfgrjJBgB4WaPIc.cache} +0 -0
  83. data/spec/support/doorkeeper_rspec.rb +0 -0
  84. data/spec/support/orm/mongoid.rb +18 -2
  85. data/spec/support/orm/mongoid8.rb +6 -0
  86. data/spec/support/orm/mongoid9.rb +6 -0
  87. data/spec/support/render_with_matcher.rb +26 -0
  88. metadata +126 -241
  89. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  90. data/spec/controllers/applications_controller_spec.rb +0 -270
  91. data/spec/controllers/authorizations_controller_spec.rb +0 -744
  92. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  93. data/spec/controllers/token_info_controller_spec.rb +0 -50
  94. data/spec/controllers/tokens_controller_spec.rb +0 -542
  95. data/spec/doorkeeper/redirect_uri_validator_spec.rb +0 -183
  96. data/spec/doorkeeper/server_spec.rb +0 -50
  97. data/spec/doorkeeper/stale_records_cleaner_spec.rb +0 -103
  98. data/spec/doorkeeper/version_spec.rb +0 -17
  99. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/-o/-ofn45zIfO5vx4VD6m6NXesLf6da5usA-Sbw2SVju3o.cache +0 -2
  100. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/0_/0_ouGcG_o_1zmVmBe-tdQYk594LBwVa1bumjrKtdfEw.cache +0 -0
  101. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/2X/2XMMcHbyTSRqh1GkV0xzyIETNtt-zgN6iniziShaKmQ.cache +0 -2
  102. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/4Q/4QQw-pMQ98JIj3xdcFhGBQdysdGPY9rWffRqWMmyjew.cache +0 -1
  103. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/7H/7HjRsym0tTpXFCVhWt6kteMs_-CozKVbr9s5syHm8es.cache +0 -1
  104. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/8B/8BxJyv22HPFHu1se_l2J8qW1N9NzZ16UOWOy1YMSgs4.cache +0 -1
  105. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/9x/9xjtGv-yKjj62x9uFwBZg8pTSh9ERPAgANwNo9uwIaA.cache +0 -1
  106. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Bt/BtXO7f0PZ8DNt3TMLYM-zY7LkbWa_KgyB0v1V98M1CQ.cache +0 -1
  107. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/E0/E02f1Q2tutWumMulGCFNfqQNjvEP_hMAK_5E83eWepI.cache +0 -0
  108. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/EZ/EZGpd6pUEJZxO6uT2yIS4Fpn5KX7VDgC9VB3AaemF5Q.cache +0 -2
  109. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/L8/L8mOWakJlWKr6MU85rj0V7yGFfNyIR6vE6YXtqArPGw.cache +0 -1
  110. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/MB/MBWRxa9S470ee8suxVKp0jYgv6K6FQOqKGV0kPGQNMs.cache +0 -1
  111. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Ph/Ph7RtH_NvG2I8XpTa8mA8SBQXZDzBPVIh4CH6g7OXJ0.cache +0 -2
  112. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/So/So59ksdx2dw-_A3-zFZ6Palr7fROjm7_0JDZb04temw.cache +0 -0
  113. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/Wt/WtXL_iDofLeTH_v0Yf3PM421r9b1V0g-VBvMPeu9KA0.cache +0 -0
  114. data/spec/dummy/tmp/cache/assets/sprockets/v4.0.0/dX/dX6FDdUIy8yBCOoaoXcjf71rX9N_bpiXGJ4Urt32NTk.cache +0 -0
  115. data/spec/factories.rb +0 -30
  116. data/spec/grape/grape_integration_spec.rb +0 -137
  117. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  118. data/spec/lib/config_spec.rb +0 -824
  119. data/spec/lib/doorkeeper_spec.rb +0 -27
  120. data/spec/lib/models/expirable_spec.rb +0 -61
  121. data/spec/lib/models/reusable_spec.rb +0 -40
  122. data/spec/lib/models/revocable_spec.rb +0 -55
  123. data/spec/lib/models/scopes_spec.rb +0 -61
  124. data/spec/lib/models/secret_storable_spec.rb +0 -136
  125. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -35
  126. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -180
  127. data/spec/lib/oauth/base_request_spec.rb +0 -210
  128. data/spec/lib/oauth/base_response_spec.rb +0 -45
  129. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  130. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -135
  131. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -110
  132. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -92
  133. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  134. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -105
  135. data/spec/lib/oauth/client_spec.rb +0 -38
  136. data/spec/lib/oauth/code_request_spec.rb +0 -46
  137. data/spec/lib/oauth/code_response_spec.rb +0 -36
  138. data/spec/lib/oauth/error_response_spec.rb +0 -65
  139. data/spec/lib/oauth/error_spec.rb +0 -21
  140. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  141. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  142. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  143. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  144. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  145. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  146. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -202
  147. data/spec/lib/oauth/pre_authorization_spec.rb +0 -230
  148. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -166
  149. data/spec/lib/oauth/scopes_spec.rb +0 -146
  150. data/spec/lib/oauth/token_request_spec.rb +0 -164
  151. data/spec/lib/oauth/token_response_spec.rb +0 -84
  152. data/spec/lib/oauth/token_spec.rb +0 -156
  153. data/spec/lib/option_spec.rb +0 -51
  154. data/spec/lib/request/strategy_spec.rb +0 -51
  155. data/spec/lib/secret_storing/base_spec.rb +0 -61
  156. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -50
  157. data/spec/lib/secret_storing/plain_spec.rb +0 -45
  158. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -49
  159. data/spec/models/doorkeeper/access_grant_spec.rb +0 -173
  160. data/spec/models/doorkeeper/access_token_spec.rb +0 -644
  161. data/spec/models/doorkeeper/application_spec.rb +0 -499
  162. data/spec/requests/applications/applications_request_spec.rb +0 -257
  163. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  164. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  165. data/spec/requests/endpoints/token_spec.rb +0 -85
  166. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -86
  167. data/spec/requests/flows/authorization_code_spec.rb +0 -559
  168. data/spec/requests/flows/client_credentials_spec.rb +0 -219
  169. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  170. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  171. data/spec/requests/flows/password_spec.rb +0 -356
  172. data/spec/requests/flows/refresh_token_spec.rb +0 -255
  173. data/spec/requests/flows/revoke_token_spec.rb +0 -196
  174. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  175. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  176. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  177. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  178. data/spec/routing/default_routes_spec.rb +0 -41
  179. data/spec/routing/scoped_routes_spec.rb +0 -47
  180. data/spec/spec_helper.rb +0 -54
  181. data/spec/spec_helper_integration.rb +0 -4
  182. data/spec/support/dependencies/factory_bot.rb +0 -4
  183. data/spec/support/helpers/access_token_request_helper.rb +0 -14
  184. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  185. data/spec/support/helpers/config_helper.rb +0 -11
  186. data/spec/support/helpers/model_helper.rb +0 -78
  187. data/spec/support/helpers/request_spec_helper.rb +0 -98
  188. data/spec/support/helpers/url_helper.rb +0 -62
  189. data/spec/support/orm/active_record.rb +0 -5
  190. data/spec/support/shared/controllers_shared_context.rb +0 -100
  191. data/spec/support/shared/hashing_shared_context.rb +0 -40
  192. data/spec/support/shared/models_shared_examples.rb +0 -56
@@ -1,542 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Doorkeeper::TokensController do
6
- subject { JSON.parse(response.body) }
7
-
8
- let(:client) { FactoryBot.create :application }
9
- let!(:user) { User.create!(name: "Joe", password: "sekret") }
10
-
11
- before do
12
- Doorkeeper.configure do
13
- orm DOORKEEPER_ORM
14
- resource_owner_from_credentials do
15
- User.first
16
- end
17
- end
18
-
19
- allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
20
- end
21
-
22
- describe "POST #create" do
23
- before do
24
- post :create, params: {
25
- client_id: client.uid,
26
- client_secret: client.secret,
27
- grant_type: "password",
28
- }
29
- end
30
-
31
- it "responds after authorization" do
32
- expect(response).to be_successful
33
- end
34
-
35
- it "includes access token in response" do
36
- expect(subject["access_token"]).to eq(Doorkeeper::AccessToken.first.token)
37
- end
38
-
39
- it "includes token type in response" do
40
- expect(subject["token_type"]).to eq("Bearer")
41
- end
42
-
43
- it "includes token expiration in response" do
44
- expect(subject["expires_in"].to_i).to eq(Doorkeeper.configuration.access_token_expires_in)
45
- end
46
-
47
- it "issues the token for the current client" do
48
- expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
49
- end
50
-
51
- it "issues the token for the current resource owner" do
52
- expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
53
- end
54
- end
55
-
56
- describe "POST #create with errors" do
57
- before do
58
- post :create, params: {
59
- client_id: client.uid,
60
- client_secret: "invalid",
61
- grant_type: "password",
62
- }
63
- end
64
-
65
- it "responds after authorization" do
66
- expect(response).to be_unauthorized
67
- end
68
-
69
- it "include error in response" do
70
- expect(subject["error"]).to eq("invalid_client")
71
- end
72
-
73
- it "include error_description in response" do
74
- expect(subject["error_description"]).to be_present
75
- end
76
-
77
- it "does not include access token in response" do
78
- expect(subject["access_token"]).to be_nil
79
- end
80
-
81
- it "does not include token type in response" do
82
- expect(subject["token_type"]).to be_nil
83
- end
84
-
85
- it "does not include token expiration in response" do
86
- expect(subject["expires_in"]).to be_nil
87
- end
88
-
89
- it "does not issue any access token" do
90
- expect(Doorkeeper::AccessToken.all).to be_empty
91
- end
92
- end
93
-
94
- describe "POST #create with callbacks" do
95
- after do
96
- client.update_attribute :redirect_uri, "urn:ietf:wg:oauth:2.0:oob"
97
- end
98
-
99
- describe "when successful" do
100
- after do
101
- post :create, params: {
102
- client_id: client.uid,
103
- client_secret: client.secret,
104
- grant_type: "password",
105
- }
106
- end
107
-
108
- it "calls :before_successful_authorization callback" do
109
- expect(Doorkeeper.configuration)
110
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
111
- end
112
-
113
- it "calls :after_successful_authorization callback" do
114
- expect(Doorkeeper.configuration)
115
- .to receive_message_chain(:after_successful_authorization, :call)
116
- .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
117
- end
118
- end
119
-
120
- describe "with errors" do
121
- after do
122
- post :create, params: {
123
- client_id: client.uid,
124
- client_secret: "invalid",
125
- grant_type: "password",
126
- }
127
- end
128
-
129
- it "calls :before_successful_authorization callback" do
130
- expect(Doorkeeper.configuration)
131
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
132
- end
133
-
134
- it "does not call :after_successful_authorization callback" do
135
- expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
136
- end
137
- end
138
- end
139
-
140
- describe "POST #create with custom error" do
141
- it "returns the error response with a custom message" do
142
- # I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
143
- custom_message = "my_message"
144
- allow(I18n).to receive(:translate)
145
- .with(
146
- custom_message,
147
- hash_including(scope: %i[doorkeeper errors messages]),
148
- )
149
- .and_return("Authorization custom message")
150
-
151
- doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
152
-
153
- strategy = double(:strategy)
154
- request = double(token_request: strategy)
155
- allow(strategy).to receive(:authorize).and_raise(doorkeeper_error)
156
- allow(controller).to receive(:server).and_return(request)
157
-
158
- post :create
159
-
160
- expected_response_body = {
161
- "error" => custom_message,
162
- "error_description" => "Authorization custom message",
163
- }
164
- expect(response.status).to eq 400
165
- expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
166
- expect(JSON.parse(response.body)).to eq expected_response_body
167
- end
168
- end
169
-
170
- # http://tools.ietf.org/html/rfc7009#section-2.2
171
- describe "POST #revoke" do
172
- let(:client) { FactoryBot.create(:application) }
173
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
174
-
175
- context "when associated app is public" do
176
- let(:client) { FactoryBot.create(:application, confidential: false) }
177
-
178
- it "returns 200" do
179
- post :revoke, params: { client_id: client.uid, token: access_token.token }
180
-
181
- expect(response.status).to eq 200
182
- end
183
-
184
- it "revokes the access token" do
185
- post :revoke, params: { client_id: client.uid, token: access_token.token }
186
-
187
- expect(access_token.reload).to have_attributes(revoked?: true)
188
- end
189
- end
190
-
191
- context "when associated app is confidential" do
192
- let(:client) { FactoryBot.create(:application, confidential: true) }
193
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(client) }
194
- let(:server) { instance_double(Doorkeeper::Server) }
195
-
196
- before do
197
- allow(Doorkeeper::Server).to receive(:new).and_return(server)
198
- allow(server).to receive(:client).and_return(oauth_client)
199
- end
200
-
201
- it "returns 200" do
202
- post :revoke, params: { token: access_token.token }
203
-
204
- expect(response.status).to eq 200
205
- end
206
-
207
- it "revokes the access token" do
208
- post :revoke, params: { token: access_token.token }
209
-
210
- expect(access_token.reload).to have_attributes(revoked?: true)
211
- end
212
-
213
- context "when authorization fails" do
214
- let(:some_other_client) { FactoryBot.create(:application, confidential: true) }
215
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
216
-
217
- it "returns 403" do
218
- post :revoke, params: { token: access_token.token }
219
-
220
- expect(response.status).to eq 403
221
- end
222
-
223
- it "does not revoke the access token" do
224
- post :revoke, params: { token: access_token.token }
225
-
226
- expect(access_token.reload).to have_attributes(revoked?: false)
227
- end
228
- end
229
- end
230
- end
231
-
232
- describe "POST #introspect" do
233
- let(:client) { FactoryBot.create(:application) }
234
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
235
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
236
-
237
- context "when authorized using valid Bearer token" do
238
- it "responds with full token introspection" do
239
- request.headers["Authorization"] = "Bearer #{access_token.token}"
240
-
241
- post :introspect, params: { token: token_for_introspection.token }
242
-
243
- expect(json_response).to include("active" => true)
244
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
245
- end
246
- end
247
-
248
- context "when authorized using Client Credentials of the client that token is issued to" do
249
- it "responds with full token introspection" do
250
- request.headers["Authorization"] = basic_auth_header_for_client(client)
251
-
252
- post :introspect, params: { token: token_for_introspection.token }
253
-
254
- expect(json_response).to match(
255
- "active" => true,
256
- "client_id" => client.uid,
257
- "token_type" => "Bearer",
258
- "scope" => nil,
259
- "exp" => an_instance_of(Integer),
260
- "iat" => an_instance_of(Integer),
261
- )
262
- end
263
- end
264
-
265
- context "when token introspection disabled" do
266
- before do
267
- Doorkeeper.configure do
268
- orm DOORKEEPER_ORM
269
- allow_token_introspection false
270
- end
271
- end
272
-
273
- it "responds with invalid_token error" do
274
- request.headers["Authorization"] = "Bearer #{access_token.token}"
275
-
276
- post :introspect, params: { token: token_for_introspection.token }
277
-
278
- response_status_should_be 401
279
-
280
- expect(json_response).not_to include("active")
281
- expect(json_response).to include("error" => "invalid_token")
282
- end
283
- end
284
-
285
- context "when custom introspection response configured" do
286
- before do
287
- Doorkeeper.configure do
288
- orm DOORKEEPER_ORM
289
- custom_introspection_response do |_token, _context|
290
- {
291
- sub: "Z5O3upPC88QrAjx00dis",
292
- aud: "https://protected.example.net/resource",
293
- }
294
- end
295
- end
296
- end
297
-
298
- it "responds with full token introspection" do
299
- request.headers["Authorization"] = "Bearer #{access_token.token}"
300
-
301
- post :introspect, params: { token: token_for_introspection.token }
302
-
303
- expect(json_response).to match(
304
- "active" => true,
305
- "client_id" => client.uid,
306
- "token_type" => "Bearer",
307
- "scope" => nil,
308
- "exp" => an_instance_of(Integer),
309
- "iat" => an_instance_of(Integer),
310
- "aud" => "https://protected.example.net/resource",
311
- "sub" => "Z5O3upPC88QrAjx00dis",
312
- )
313
- end
314
- end
315
-
316
- context "when access token is public" do
317
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: nil) }
318
-
319
- it "responds with full token introspection" do
320
- request.headers["Authorization"] = basic_auth_header_for_client(client)
321
-
322
- post :introspect, params: { token: token_for_introspection.token }
323
-
324
- expect(json_response).to match(
325
- "active" => true,
326
- "client_id" => nil,
327
- "token_type" => "Bearer",
328
- "scope" => nil,
329
- "exp" => an_instance_of(Integer),
330
- "iat" => an_instance_of(Integer),
331
- )
332
- end
333
- end
334
-
335
- context "when token was issued to a different client than is making this request" do
336
- let(:different_client) { FactoryBot.create(:application) }
337
-
338
- it "responds with only active state" do
339
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
340
-
341
- post :introspect, params: { token: token_for_introspection.token }
342
-
343
- expect(response).to be_successful
344
-
345
- expect(json_response).to match("active" => false)
346
- end
347
- end
348
-
349
- context "when introspection request authorized by a client and allow_token_introspection is true" do
350
- let(:different_client) { FactoryBot.create(:application) }
351
-
352
- before do
353
- allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do
354
- true
355
- end)
356
- end
357
-
358
- it "responds with full token introspection" do
359
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
360
-
361
- post :introspect, params: { token: token_for_introspection.token }
362
-
363
- expect(json_response).to match(
364
- "active" => true,
365
- "client_id" => client.uid,
366
- "token_type" => "Bearer",
367
- "scope" => nil,
368
- "exp" => an_instance_of(Integer),
369
- "iat" => an_instance_of(Integer),
370
- )
371
- end
372
- end
373
-
374
- context "when allow_token_introspection requires authorized token with special scope" do
375
- let(:access_token) { FactoryBot.create(:access_token, scopes: "introspection") }
376
-
377
- before do
378
- allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do |_token, _client, authorized_token|
379
- authorized_token.scopes.include?("introspection")
380
- end)
381
- end
382
-
383
- it "responds with full token introspection if authorized token has introspection scope" do
384
- request.headers["Authorization"] = "Bearer #{access_token.token}"
385
-
386
- post :introspect, params: { token: token_for_introspection.token }
387
-
388
- expect(json_response).to match(
389
- "active" => true,
390
- "client_id" => client.uid,
391
- "token_type" => "Bearer",
392
- "scope" => nil,
393
- "exp" => an_instance_of(Integer),
394
- "iat" => an_instance_of(Integer),
395
- )
396
- end
397
-
398
- it "responds with invalid_token error if authorized token doesn't have introspection scope" do
399
- access_token.update(scopes: "read write")
400
-
401
- request.headers["Authorization"] = "Bearer #{access_token.token}"
402
-
403
- post :introspect, params: { token: token_for_introspection.token }
404
-
405
- response_status_should_be 401
406
-
407
- expect(json_response).to match(
408
- "error" => "invalid_token",
409
- "error_description" => an_instance_of(String),
410
- "state" => "unauthorized",
411
- )
412
- end
413
- end
414
-
415
- context "when authorized using invalid Bearer token" do
416
- let(:access_token) do
417
- FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
418
- end
419
-
420
- it "responds with invalid_token error" do
421
- request.headers["Authorization"] = "Bearer #{access_token.token}"
422
-
423
- post :introspect, params: { token: token_for_introspection.token }
424
-
425
- response_status_should_be 401
426
-
427
- expect(json_response).to match(
428
- "error" => "invalid_token",
429
- "error_description" => an_instance_of(String),
430
- "state" => "unauthorized",
431
- )
432
- end
433
- end
434
-
435
- context "when authorized using the Bearer token that need to be introspected" do
436
- it "responds with invalid token error" do
437
- request.headers["Authorization"] = "Bearer #{access_token.token}"
438
-
439
- post :introspect, params: { token: access_token.token }
440
-
441
- response_status_should_be 401
442
-
443
- expect(json_response).to match(
444
- "error" => "invalid_token",
445
- "error_description" => an_instance_of(String),
446
- "state" => "unauthorized",
447
- )
448
- end
449
- end
450
-
451
- context "when invalid credentials used to authorize" do
452
- let(:client) { double(uid: "123123", secret: "666999") }
453
- let(:access_token) { FactoryBot.create(:access_token) }
454
-
455
- it "responds with invalid_client error" do
456
- request.headers["Authorization"] = basic_auth_header_for_client(client)
457
-
458
- post :introspect, params: { token: access_token.token }
459
-
460
- expect(response).not_to be_successful
461
- response_status_should_be 401
462
-
463
- expect(json_response).to match(
464
- "error" => "invalid_client",
465
- "error_description" => an_instance_of(String),
466
- )
467
- end
468
- end
469
-
470
- context "when wrong token value used" do
471
- context "when authorized using client credentials" do
472
- it "responds with only active state" do
473
- request.headers["Authorization"] = basic_auth_header_for_client(client)
474
-
475
- post :introspect, params: { token: SecureRandom.hex(16) }
476
-
477
- expect(json_response).to match("active" => false)
478
- end
479
- end
480
-
481
- context "when authorized using valid Bearer token" do
482
- it "responds with invalid_token error" do
483
- request.headers["Authorization"] = "Bearer #{access_token.token}"
484
-
485
- post :introspect, params: { token: SecureRandom.hex(16) }
486
-
487
- response_status_should_be 401
488
-
489
- expect(json_response).to match(
490
- "error" => "invalid_token",
491
- "error_description" => an_instance_of(String),
492
- "state" => "unauthorized",
493
- )
494
- end
495
- end
496
- end
497
-
498
- context "when requested access token expired" do
499
- let(:token_for_introspection) do
500
- FactoryBot.create(:access_token, application: client, created_at: 1.year.ago)
501
- end
502
-
503
- it "responds with only active state" do
504
- request.headers["Authorization"] = basic_auth_header_for_client(client)
505
-
506
- post :introspect, params: { token: token_for_introspection.token }
507
-
508
- expect(json_response).to match("active" => false)
509
- end
510
- end
511
-
512
- context "when requested Access Token revoked" do
513
- let(:token_for_introspection) do
514
- FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago)
515
- end
516
-
517
- it "responds with only active state" do
518
- request.headers["Authorization"] = basic_auth_header_for_client(client)
519
-
520
- post :introspect, params: { token: token_for_introspection.token }
521
-
522
- expect(json_response).to match("active" => false)
523
- end
524
- end
525
-
526
- context "when unauthorized (no bearer token or client credentials)" do
527
- let(:token_for_introspection) { FactoryBot.create(:access_token) }
528
-
529
- it "responds with invalid_request error" do
530
- post :introspect, params: { token: token_for_introspection.token }
531
-
532
- expect(response).not_to be_successful
533
- response_status_should_be 400
534
-
535
- expect(json_response).to match(
536
- "error" => "invalid_request",
537
- "error_description" => an_instance_of(String),
538
- )
539
- end
540
- end
541
- end
542
- end