doorkeeper 4.4.3 → 5.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

Files changed (223) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +16 -0
  4. data/.travis.yml +7 -0
  5. data/Appraisals +2 -2
  6. data/Dangerfile +64 -0
  7. data/Gemfile +1 -1
  8. data/NEWS.md +98 -8
  9. data/README.md +110 -12
  10. data/Rakefile +6 -0
  11. data/UPGRADE.md +2 -0
  12. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  13. data/app/controllers/doorkeeper/application_controller.rb +6 -3
  14. data/app/controllers/doorkeeper/application_metal_controller.rb +6 -0
  15. data/app/controllers/doorkeeper/applications_controller.rb +46 -24
  16. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  17. data/app/controllers/doorkeeper/authorized_applications_controller.rb +21 -2
  18. data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
  19. data/app/controllers/doorkeeper/tokens_controller.rb +4 -6
  20. data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
  21. data/app/validators/redirect_uri_validator.rb +5 -2
  22. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  23. data/app/views/doorkeeper/applications/_form.html.erb +25 -24
  24. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  25. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  26. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  27. data/app/views/doorkeeper/applications/show.html.erb +6 -6
  28. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  29. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  30. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  31. data/config/locales/en.yml +10 -1
  32. data/doorkeeper.gemspec +25 -26
  33. data/gemfiles/rails_5_2.gemfile +1 -1
  34. data/gemfiles/rails_master.gemfile +4 -1
  35. data/lib/doorkeeper/config.rb +81 -40
  36. data/lib/doorkeeper/engine.rb +6 -0
  37. data/lib/doorkeeper/errors.rb +17 -3
  38. data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
  39. data/lib/doorkeeper/grape/helpers.rb +3 -1
  40. data/lib/doorkeeper/helpers/controller.rb +9 -2
  41. data/lib/doorkeeper/models/access_grant_mixin.rb +73 -0
  42. data/lib/doorkeeper/models/access_token_mixin.rb +44 -25
  43. data/lib/doorkeeper/models/application_mixin.rb +2 -0
  44. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  45. data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
  46. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  47. data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
  48. data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
  49. data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
  50. data/lib/doorkeeper/oauth/authorization/code.rb +33 -8
  51. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  52. data/lib/doorkeeper/oauth/authorization/token.rb +38 -14
  53. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
  54. data/lib/doorkeeper/oauth/authorization_code_request.rb +29 -2
  55. data/lib/doorkeeper/oauth/base_request.rb +22 -9
  56. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  57. data/lib/doorkeeper/oauth/client/credentials.rb +3 -1
  58. data/lib/doorkeeper/oauth/client.rb +1 -1
  59. data/lib/doorkeeper/oauth/client_credentials/creator.rb +4 -1
  60. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -2
  61. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -5
  62. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -3
  63. data/lib/doorkeeper/oauth/code_request.rb +2 -0
  64. data/lib/doorkeeper/oauth/code_response.rb +2 -0
  65. data/lib/doorkeeper/oauth/error.rb +2 -0
  66. data/lib/doorkeeper/oauth/error_response.rb +21 -3
  67. data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
  68. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  69. data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +43 -11
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +16 -3
  75. data/lib/doorkeeper/oauth/scopes.rb +3 -1
  76. data/lib/doorkeeper/oauth/token.rb +7 -2
  77. data/lib/doorkeeper/oauth/token_introspection.rb +4 -2
  78. data/lib/doorkeeper/oauth/token_request.rb +2 -0
  79. data/lib/doorkeeper/oauth/token_response.rb +6 -2
  80. data/lib/doorkeeper/oauth.rb +13 -0
  81. data/lib/doorkeeper/orm/active_record/application.rb +75 -12
  82. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  83. data/lib/doorkeeper/orm/active_record.rb +4 -0
  84. data/lib/doorkeeper/rails/helpers.rb +6 -4
  85. data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
  86. data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
  87. data/lib/doorkeeper/rails/routes.rb +23 -8
  88. data/lib/doorkeeper/rake/db.rake +40 -0
  89. data/lib/doorkeeper/rake/setup.rake +6 -0
  90. data/lib/doorkeeper/rake.rb +14 -0
  91. data/lib/doorkeeper/request/authorization_code.rb +1 -1
  92. data/lib/doorkeeper/request/client_credentials.rb +1 -1
  93. data/lib/doorkeeper/request/code.rb +1 -1
  94. data/lib/doorkeeper/request/password.rb +1 -1
  95. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  96. data/lib/doorkeeper/request/strategy.rb +2 -0
  97. data/lib/doorkeeper/request/token.rb +1 -1
  98. data/lib/doorkeeper/request.rb +29 -34
  99. data/lib/doorkeeper/server.rb +2 -0
  100. data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
  101. data/lib/doorkeeper/validations.rb +2 -0
  102. data/lib/doorkeeper/version.rb +6 -24
  103. data/lib/doorkeeper.rb +20 -17
  104. data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
  105. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  106. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  107. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  108. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  109. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
  110. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  111. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  112. data/lib/generators/doorkeeper/templates/initializer.rb +96 -13
  113. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
  114. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  115. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  116. data/spec/controllers/applications_controller_spec.rb +123 -14
  117. data/spec/controllers/authorizations_controller_spec.rb +334 -51
  118. data/spec/controllers/protected_resources_controller_spec.rb +60 -18
  119. data/spec/controllers/token_info_controller_spec.rb +4 -12
  120. data/spec/controllers/tokens_controller_spec.rb +17 -20
  121. data/spec/dummy/Rakefile +1 -1
  122. data/spec/dummy/app/assets/config/manifest.js +2 -0
  123. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
  124. data/spec/dummy/app/controllers/home_controller.rb +1 -2
  125. data/spec/dummy/config/application.rb +1 -1
  126. data/spec/dummy/config/boot.rb +2 -4
  127. data/spec/dummy/config/environment.rb +1 -1
  128. data/spec/dummy/config/environments/test.rb +5 -6
  129. data/spec/dummy/config/initializers/doorkeeper.rb +12 -6
  130. data/spec/dummy/config/initializers/new_framework_defaults.rb +2 -0
  131. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  132. data/spec/dummy/config/routes.rb +3 -42
  133. data/spec/dummy/config.ru +1 -1
  134. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
  135. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
  136. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  137. data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
  138. data/spec/dummy/db/schema.rb +36 -36
  139. data/spec/dummy/script/rails +4 -3
  140. data/spec/factories.rb +6 -6
  141. data/spec/generators/application_owner_generator_spec.rb +1 -1
  142. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  143. data/spec/generators/install_generator_spec.rb +5 -2
  144. data/spec/generators/migration_generator_spec.rb +1 -1
  145. data/spec/generators/pkce_generator_spec.rb +43 -0
  146. data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
  147. data/spec/generators/templates/routes.rb +0 -1
  148. data/spec/generators/views_generator_spec.rb +2 -2
  149. data/spec/grape/grape_integration_spec.rb +2 -2
  150. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  151. data/spec/lib/config_spec.rb +105 -39
  152. data/spec/lib/doorkeeper_spec.rb +6 -131
  153. data/spec/lib/models/expirable_spec.rb +0 -3
  154. data/spec/lib/models/revocable_spec.rb +0 -2
  155. data/spec/lib/models/scopes_spec.rb +0 -4
  156. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  157. data/spec/lib/oauth/authorization_code_request_spec.rb +17 -7
  158. data/spec/lib/oauth/base_request_spec.rb +49 -11
  159. data/spec/lib/oauth/base_response_spec.rb +1 -1
  160. data/spec/lib/oauth/client/credentials_spec.rb +2 -4
  161. data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
  162. data/spec/lib/oauth/client_credentials/issuer_spec.rb +24 -7
  163. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  164. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  165. data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
  166. data/spec/lib/oauth/client_spec.rb +0 -3
  167. data/spec/lib/oauth/code_request_spec.rb +5 -3
  168. data/spec/lib/oauth/code_response_spec.rb +1 -1
  169. data/spec/lib/oauth/error_response_spec.rb +0 -3
  170. data/spec/lib/oauth/error_spec.rb +0 -2
  171. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  172. data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -11
  173. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  174. data/spec/lib/oauth/helpers/uri_checker_spec.rb +22 -13
  175. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
  176. data/spec/lib/oauth/password_access_token_request_spec.rb +53 -6
  177. data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
  178. data/spec/lib/oauth/refresh_token_request_spec.rb +22 -14
  179. data/spec/lib/oauth/scopes_spec.rb +0 -3
  180. data/spec/lib/oauth/token_request_spec.rb +8 -9
  181. data/spec/lib/oauth/token_response_spec.rb +0 -1
  182. data/spec/lib/oauth/token_spec.rb +40 -14
  183. data/spec/lib/request/strategy_spec.rb +0 -1
  184. data/spec/lib/server_spec.rb +7 -7
  185. data/spec/lib/stale_records_cleaner_spec.rb +89 -0
  186. data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
  187. data/spec/models/doorkeeper/access_token_spec.rb +80 -32
  188. data/spec/models/doorkeeper/application_spec.rb +293 -221
  189. data/spec/requests/applications/applications_request_spec.rb +134 -1
  190. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  191. data/spec/requests/endpoints/authorization_spec.rb +3 -3
  192. data/spec/requests/endpoints/token_spec.rb +7 -5
  193. data/spec/requests/flows/authorization_code_errors_spec.rb +2 -2
  194. data/spec/requests/flows/authorization_code_spec.rb +258 -2
  195. data/spec/requests/flows/client_credentials_spec.rb +46 -6
  196. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  197. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  198. data/spec/requests/flows/password_spec.rb +61 -3
  199. data/spec/requests/flows/refresh_token_spec.rb +59 -2
  200. data/spec/requests/flows/revoke_token_spec.rb +20 -20
  201. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  202. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  203. data/spec/requests/protected_resources/private_api_spec.rb +3 -3
  204. data/spec/routing/custom_controller_routes_spec.rb +59 -7
  205. data/spec/routing/default_routes_spec.rb +2 -2
  206. data/spec/routing/scoped_routes_spec.rb +16 -2
  207. data/spec/spec_helper.rb +54 -3
  208. data/spec/spec_helper_integration.rb +2 -74
  209. data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
  210. data/spec/support/doorkeeper_rspec.rb +20 -0
  211. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  212. data/spec/support/helpers/model_helper.rb +8 -4
  213. data/spec/support/helpers/request_spec_helper.rb +10 -2
  214. data/spec/support/helpers/url_helper.rb +18 -14
  215. data/spec/support/http_method_shim.rb +12 -16
  216. data/spec/support/shared/controllers_shared_context.rb +56 -0
  217. data/spec/validators/redirect_uri_validator_spec.rb +9 -3
  218. data/spec/version/version_spec.rb +3 -3
  219. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  220. metadata +54 -35
  221. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  222. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  223. data/spec/controllers/application_metal_controller.rb +0 -10
@@ -1,16 +1,16 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe BaseRequest do
5
5
  let(:access_token) do
6
6
  double :access_token,
7
- token: "some-token",
8
- expires_in: "3600",
9
- expires_in_seconds: "300",
10
- scopes_string: "two scopes",
11
- refresh_token: "some-refresh-token",
12
- token_type: "bearer",
13
- created_at: 0
7
+ token: "some-token",
8
+ expires_in: "3600",
9
+ expires_in_seconds: "300",
10
+ scopes_string: "two scopes",
11
+ refresh_token: "some-refresh-token",
12
+ token_type: "bearer",
13
+ created_at: 0
14
14
  end
15
15
 
16
16
  let(:client) { double :client, id: '1' }
@@ -19,9 +19,9 @@ module Doorkeeper::OAuth
19
19
 
20
20
  let(:server) do
21
21
  double :server,
22
- access_token_expires_in: 100,
23
- custom_access_token_expires_in: ->(_) { nil },
24
- refresh_token_enabled?: false
22
+ access_token_expires_in: 100,
23
+ custom_access_token_expires_in: ->(_context) { nil },
24
+ refresh_token_enabled?: false
25
25
  end
26
26
 
27
27
  subject do
@@ -105,6 +105,44 @@ module Doorkeeper::OAuth
105
105
 
106
106
  expect(result).to be_an_instance_of(Doorkeeper::AccessToken)
107
107
  end
108
+
109
+ it "respects custom_access_token_expires_in" do
110
+ server = double(:server,
111
+ access_token_expires_in: 100,
112
+ custom_access_token_expires_in: ->(context) { context.scopes == "public" ? 500 : nil },
113
+ refresh_token_enabled?: false)
114
+ result = subject.find_or_create_access_token(
115
+ client,
116
+ "1",
117
+ "public",
118
+ server
119
+ )
120
+ expect(result.expires_in).to eql(500)
121
+ end
122
+
123
+ it "respects use_refresh_token with a block" do
124
+ server = double(:server,
125
+ access_token_expires_in: 100,
126
+ custom_access_token_expires_in: ->(_context) { nil },
127
+ refresh_token_enabled?: lambda { |context|
128
+ context.scopes == "public"
129
+ })
130
+ result = subject.find_or_create_access_token(
131
+ client,
132
+ "1",
133
+ "public",
134
+ server
135
+ )
136
+ expect(result.refresh_token).to_not be_nil
137
+
138
+ result = subject.find_or_create_access_token(
139
+ client,
140
+ "1",
141
+ "private",
142
+ server
143
+ )
144
+ expect(result.refresh_token).to be_nil
145
+ end
108
146
  end
109
147
 
110
148
  describe "#scopes" do
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe BaseResponse do
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/core_ext/string'
3
- require 'doorkeeper/oauth/client'
4
2
 
5
3
  class Doorkeeper::OAuth::Client
6
4
  describe Credentials do
@@ -18,7 +16,7 @@ class Doorkeeper::OAuth::Client
18
16
  let(:request) { double.as_null_object }
19
17
 
20
18
  let(:method) do
21
- ->(_request) { return 'uid', 'secret' }
19
+ ->(_request) { %w[uid secret] }
22
20
  end
23
21
 
24
22
  it 'accepts anything that responds to #call' do
@@ -79,7 +77,7 @@ class Doorkeeper::OAuth::Client
79
77
  end
80
78
 
81
79
  it 'is blank if Authorization is not Basic' do
82
- request = double authorization: "#{credentials}"
80
+ request = double authorization: credentials.to_s
83
81
  uid, secret = Credentials.from_basic(request)
84
82
 
85
83
  expect(uid).to be_blank
@@ -1,10 +1,14 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  class Doorkeeper::OAuth::ClientCredentialsRequest
4
4
  describe Creator do
5
5
  let(:client) { FactoryBot.create :application }
6
6
  let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public') }
7
7
 
8
+ before do
9
+ default_scopes_exist :public
10
+ end
11
+
8
12
  it 'creates a new token' do
9
13
  expect do
10
14
  subject.call(client, scopes)
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/all'
3
- require 'doorkeeper/oauth/client_credentials/issuer'
4
2
 
5
3
  class Doorkeeper::OAuth::ClientCredentialsRequest
6
4
  describe Issuer do
@@ -9,7 +7,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
9
7
  double(
10
8
  :server,
11
9
  access_token_expires_in: 100,
12
- custom_access_token_expires_in: ->(_app) { nil }
10
+ custom_access_token_expires_in: ->(_context) { nil }
13
11
  )
14
12
  end
15
13
  let(:validation) { double :validation, valid?: true }
@@ -63,23 +61,42 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
63
61
  end
64
62
 
65
63
  context 'with custom expirations' do
66
- let(:custom_ttl) { 1233 }
64
+ let(:custom_ttl_grant) { 1234 }
65
+ let(:custom_ttl_scope) { 1235 }
66
+ let(:custom_scope) { 'special' }
67
67
  let(:server) do
68
68
  double(
69
69
  :server,
70
- custom_access_token_expires_in: ->(_app) { custom_ttl }
70
+ custom_access_token_expires_in: lambda { |context|
71
+ # scopes is normally an object but is a string in this test
72
+ if context.scopes == custom_scope
73
+ custom_ttl_scope
74
+ elsif context.grant_type == Doorkeeper::OAuth::CLIENT_CREDENTIALS
75
+ custom_ttl_grant
76
+ end
77
+ }
71
78
  )
72
79
  end
73
80
 
74
- it 'creates with correct token parameters' do
81
+ it 'respects grant based rules' do
75
82
  expect(creator).to receive(:call).with(
76
83
  client,
77
84
  scopes,
78
- expires_in: custom_ttl,
85
+ expires_in: custom_ttl_grant,
79
86
  use_refresh_token: false
80
87
  )
81
88
  subject.create client, scopes, creator
82
89
  end
90
+
91
+ it 'respects scope based rules' do
92
+ expect(creator).to receive(:call).with(
93
+ client,
94
+ custom_scope,
95
+ expires_in: custom_ttl_scope,
96
+ use_refresh_token: false
97
+ )
98
+ subject.create client, custom_scope, creator
99
+ end
83
100
  end
84
101
  end
85
102
  end
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/all'
3
- require 'doorkeeper/oauth/client_credentials/validation'
4
2
 
5
3
  class Doorkeeper::OAuth::ClientCredentialsRequest
6
4
  describe Validation do
@@ -25,7 +23,8 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
25
23
  server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email'
26
24
  allow(server).to receive(:scopes).and_return(server_scopes)
27
25
  allow(request).to receive(:scopes).and_return(
28
- Doorkeeper::OAuth::Scopes.from_string 'invalid')
26
+ Doorkeeper::OAuth::Scopes.from_string('invalid')
27
+ )
29
28
  expect(subject).not_to be_valid
30
29
  end
31
30
 
@@ -45,7 +44,8 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
45
44
  allow(application).to receive(:scopes).and_return(application_scopes)
46
45
  allow(server).to receive(:scopes).and_return(server_scopes)
47
46
  allow(request).to receive(:scopes).and_return(
48
- Doorkeeper::OAuth::Scopes.from_string 'email')
47
+ Doorkeeper::OAuth::Scopes.from_string('email')
48
+ )
49
49
  expect(subject).not_to be_valid
50
50
  end
51
51
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe ClientCredentialsRequest do
@@ -20,7 +20,7 @@ module Doorkeeper::OAuth
20
20
  request = ClientCredentialsRequest.new(server, nil, {})
21
21
  expect do
22
22
  request.authorize
23
- end.to_not change { Doorkeeper::AccessToken.count }
23
+ end.to_not(change { Doorkeeper::AccessToken.count })
24
24
  end
25
25
  end
26
26
  end
@@ -1,18 +1,16 @@
1
1
  require 'spec_helper'
2
- require 'active_support/all'
3
- require 'active_model'
4
- require 'doorkeeper/oauth/client_credentials_request'
5
2
 
6
3
  module Doorkeeper::OAuth
7
4
  describe ClientCredentialsRequest do
8
5
  let(:server) do
9
6
  double(
10
7
  default_scopes: nil,
11
- custom_access_token_expires_in: ->(_app) { nil }
8
+ access_token_expires_in: 2.hours,
9
+ custom_access_token_expires_in: ->(_context) { nil }
12
10
  )
13
11
  end
14
12
 
15
- let(:application) { double :application, scopes: Scopes.from_string('') }
13
+ let(:application) { FactoryBot.create(:application, scopes: '') }
16
14
  let(:client) { double :client, application: application }
17
15
  let(:token_creator) { double :issuer, create: true, token: double }
18
16
 
@@ -1,7 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/string'
4
- require 'doorkeeper/oauth/client'
5
2
 
6
3
  module Doorkeeper::OAuth
7
4
  describe Client do
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe CodeRequest do
@@ -10,7 +10,9 @@ module Doorkeeper::OAuth
10
10
  scopes: nil,
11
11
  state: nil,
12
12
  error: nil,
13
- authorizable?: true
13
+ authorizable?: true,
14
+ code_challenge: nil,
15
+ code_challenge_method: nil
14
16
  )
15
17
  end
16
18
 
@@ -32,7 +34,7 @@ module Doorkeeper::OAuth
32
34
 
33
35
  it 'does not create grant when not authorizable' do
34
36
  allow(pre_auth).to receive(:authorizable?).and_return(false)
35
- expect { subject.authorize }.not_to change { Doorkeeper::AccessGrant.count }
37
+ expect { subject.authorize }.not_to(change { Doorkeeper::AccessGrant.count })
36
38
  end
37
39
 
38
40
  it 'returns a error response' do
@@ -11,7 +11,7 @@ module Doorkeeper
11
11
  client: double(:application, id: 1),
12
12
  redirect_uri: 'http://tst.com/cb',
13
13
  state: nil,
14
- scopes: Scopes.from_string('public'),
14
+ scopes: Scopes.from_string('public')
15
15
  )
16
16
  end
17
17
 
@@ -1,7 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_model'
3
- require 'doorkeeper/oauth/error'
4
- require 'doorkeeper/oauth/error_response'
5
2
 
6
3
  module Doorkeeper::OAuth
7
4
  describe ErrorResponse do
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/i18n'
3
- require 'doorkeeper/oauth/error'
4
2
 
5
3
  module Doorkeeper::OAuth
6
4
  describe Error do
@@ -1,12 +1,9 @@
1
1
  require 'spec_helper'
2
- require 'active_model'
3
- require 'doorkeeper'
4
- require 'doorkeeper/oauth/forbidden_token_response'
5
2
 
6
3
  module Doorkeeper::OAuth
7
4
  describe ForbiddenTokenResponse do
8
5
  describe '#name' do
9
- it { expect(subject.name).to eq(:invalid_scope) }
6
+ it { expect(subject.name).to eq(:invalid_scope) }
10
7
  end
11
8
 
12
9
  describe '#status' do
@@ -1,7 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/core_ext/string'
3
- require 'doorkeeper/oauth/helpers/scope_checker'
4
- require 'doorkeeper/oauth/scopes'
5
2
 
6
3
  module Doorkeeper::OAuth::Helpers
7
4
  describe ScopeChecker, '.valid?' do
@@ -46,18 +43,18 @@ module Doorkeeper::OAuth::Helpers
46
43
 
47
44
  it 'is valid if scope is included in the application scope list' do
48
45
  expect(ScopeChecker.valid?(
49
- 'app123',
50
- server_scopes,
51
- application_scopes
52
- )).to be_truthy
46
+ 'app123',
47
+ server_scopes,
48
+ application_scopes
49
+ )).to be_truthy
53
50
  end
54
51
 
55
52
  it 'is invalid if any scope is not included in the application' do
56
53
  expect(ScopeChecker.valid?(
57
- 'svr',
58
- server_scopes,
59
- application_scopes
60
- )).to be_falsey
54
+ 'svr',
55
+ server_scopes,
56
+ application_scopes
57
+ )).to be_falsey
61
58
  end
62
59
  end
63
60
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'doorkeeper/oauth/helpers/unique_token'
3
2
 
4
3
  module Doorkeeper::OAuth::Helpers
5
4
  describe UniqueToken do
@@ -1,15 +1,8 @@
1
1
  require 'spec_helper'
2
- require 'uri'
3
- require 'doorkeeper/oauth/helpers/uri_checker'
4
2
 
5
3
  module Doorkeeper::OAuth::Helpers
6
4
  describe URIChecker do
7
5
  describe '.valid?' do
8
- it 'is valid for native uris' do
9
- uri = 'urn:ietf:wg:oauth:2.0:oob'
10
- expect(URIChecker.valid?(uri)).to be_truthy
11
- end
12
-
13
6
  it 'is valid for valid uris' do
14
7
  uri = 'http://app.co'
15
8
  expect(URIChecker.valid?(uri)).to be_truthy
@@ -49,6 +42,11 @@ module Doorkeeper::OAuth::Helpers
49
42
  uri = ' '
50
43
  expect(URIChecker.valid?(uri)).to be_falsey
51
44
  end
45
+
46
+ it 'is valid for native uris' do
47
+ uri = 'urn:ietf:wg:oauth:2.0:oob'
48
+ expect(URIChecker.valid?(uri)).to be_truthy
49
+ end
52
50
  end
53
51
 
54
52
  describe '.matches?' do
@@ -118,6 +116,22 @@ module Doorkeeper::OAuth::Helpers
118
116
  it 'is true if valid and matches' do
119
117
  uri = client_uri = 'http://app.co/aaa'
120
118
  expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
119
+
120
+ uri = client_uri = 'http://app.co/aaa?b=c'
121
+ expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
122
+ end
123
+
124
+ it 'is true if uri includes blank query' do
125
+ uri = client_uri = 'http://app.co/aaa?'
126
+ expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
127
+
128
+ uri = 'http://app.co/aaa?'
129
+ client_uri = 'http://app.co/aaa'
130
+ expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
131
+
132
+ uri = 'http://app.co/aaa'
133
+ client_uri = 'http://app.co/aaa?'
134
+ expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
121
135
  end
122
136
 
123
137
  it 'is false if valid and mismatches' do
@@ -138,12 +152,7 @@ module Doorkeeper::OAuth::Helpers
138
152
  expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
139
153
  end
140
154
 
141
- it 'is true if valid and matches' do
142
- uri = client_uri = 'http://app.co/aaa'
143
- expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be true
144
- end
145
-
146
- it 'is false if invalid' do
155
+ it 'is false if queries does not match' do
147
156
  uri = 'http://app.co/aaa?pankcakes=abc'
148
157
  client_uri = 'http://app.co/aaa?waffles=abc'
149
158
  expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be false
@@ -1,12 +1,9 @@
1
1
  require 'spec_helper'
2
- require 'active_model'
3
- require 'doorkeeper'
4
- require 'doorkeeper/oauth/invalid_token_response'
5
2
 
6
3
  module Doorkeeper::OAuth
7
4
  describe InvalidTokenResponse do
8
5
  describe "#name" do
9
- it { expect(subject.name).to eq(:invalid_token) }
6
+ it { expect(subject.name).to eq(:invalid_token) }
10
7
  end
11
8
 
12
9
  describe "#status" do
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe PasswordAccessTokenRequest do
@@ -8,7 +8,9 @@ module Doorkeeper::OAuth
8
8
  default_scopes: Doorkeeper::OAuth::Scopes.new,
9
9
  access_token_expires_in: 2.hours,
10
10
  refresh_token_enabled?: false,
11
- custom_access_token_expires_in: ->(_app) { nil }
11
+ custom_access_token_expires_in: lambda { |context|
12
+ context.grant_type == Doorkeeper::OAuth::PASSWORD ? 1234 : nil
13
+ }
12
14
  )
13
15
  end
14
16
  let(:client) { FactoryBot.create(:application) }
@@ -22,6 +24,8 @@ module Doorkeeper::OAuth
22
24
  expect do
23
25
  subject.authorize
24
26
  end.to change { client.reload.access_tokens.count }.by(1)
27
+
28
+ expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
25
29
  end
26
30
 
27
31
  it 'issues a new token without a client' do
@@ -36,7 +40,7 @@ module Doorkeeper::OAuth
36
40
  subject.client = nil
37
41
  subject.parameters = { client_id: 'bad_id' }
38
42
  subject.authorize
39
- end.to_not change { Doorkeeper::AccessToken.count }
43
+ end.not_to(change { Doorkeeper::AccessToken.count })
40
44
 
41
45
  expect(subject.error).to eq(:invalid_client)
42
46
  end
@@ -54,6 +58,7 @@ module Doorkeeper::OAuth
54
58
 
55
59
  it 'creates token even when there is already one (default)' do
56
60
  FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
61
+
57
62
  expect do
58
63
  subject.authorize
59
64
  end.to change { Doorkeeper::AccessToken.count }.by(1)
@@ -62,14 +67,19 @@ module Doorkeeper::OAuth
62
67
  it 'skips token creation if there is already one' do
63
68
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
64
69
  FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
70
+
65
71
  expect do
66
72
  subject.authorize
67
- end.to_not change { Doorkeeper::AccessToken.count }
73
+ end.not_to(change { Doorkeeper::AccessToken.count })
68
74
  end
69
75
 
70
76
  it "calls configured request callback methods" do
71
- expect(Doorkeeper.configuration.before_successful_strategy_response).to receive(:call).with(subject).once
72
- expect(Doorkeeper.configuration.after_successful_strategy_response).to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
77
+ expect(Doorkeeper.configuration.before_successful_strategy_response)
78
+ .to receive(:call).with(subject).once
79
+
80
+ expect(Doorkeeper.configuration.after_successful_strategy_response)
81
+ .to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
82
+
73
83
  subject.authorize
74
84
  end
75
85
 
@@ -89,8 +99,45 @@ module Doorkeeper::OAuth
89
99
  expect do
90
100
  subject.authorize
91
101
  end.to change { Doorkeeper::AccessToken.count }.by(1)
102
+
92
103
  expect(Doorkeeper::AccessToken.last.scopes).to include('public')
93
104
  end
94
105
  end
106
+
107
+ describe 'with custom expiry' do
108
+ let(:server) do
109
+ double(
110
+ :server,
111
+ default_scopes: Doorkeeper::OAuth::Scopes.new,
112
+ access_token_expires_in: 2.hours,
113
+ refresh_token_enabled?: false,
114
+ custom_access_token_expires_in: lambda { |context|
115
+ context.scopes.exists?('public') ? 222 : nil
116
+ }
117
+ )
118
+ end
119
+
120
+ it 'checks scopes' do
121
+ subject = PasswordAccessTokenRequest.new(server, client, owner, scope: 'public')
122
+ allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string('public'))
123
+
124
+ expect do
125
+ subject.authorize
126
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
127
+
128
+ expect(Doorkeeper::AccessToken.last.expires_in).to eq(222)
129
+ end
130
+
131
+ it 'falls back to the default otherwise' do
132
+ subject = PasswordAccessTokenRequest.new(server, client, owner, scope: 'private')
133
+ allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string('private'))
134
+
135
+ expect do
136
+ subject.authorize
137
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
138
+
139
+ expect(Doorkeeper::AccessToken.last.expires_in).to eq(2.hours)
140
+ end
141
+ end
95
142
  end
96
143
  end
@@ -1,13 +1,13 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe PreAuthorization do
5
- let(:server) {
5
+ let(:server) do
6
6
  server = Doorkeeper.configuration
7
7
  allow(server).to receive(:default_scopes).and_return(Scopes.new)
8
8
  allow(server).to receive(:scopes).and_return(Scopes.from_string('public profile'))
9
9
  server
10
- }
10
+ end
11
11
 
12
12
  let(:application) do
13
13
  application = double :application
@@ -133,11 +133,16 @@ module Doorkeeper::OAuth
133
133
  end
134
134
 
135
135
  it 'invalidates redirect_uri when it does\'n match with the client' do
136
- subject.redirect_uri = native_redirect_uri
136
+ subject.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
137
137
  expect(subject).not_to be_authorizable
138
138
  end
139
139
  end
140
140
 
141
+ it 'matches the redirect uri against client\'s one' do
142
+ subject.redirect_uri = 'http://nothesame.com'
143
+ expect(subject).not_to be_authorizable
144
+ end
145
+
141
146
  it 'stores the state' do
142
147
  expect(subject.state).to eq('save-this')
143
148
  end
@@ -156,5 +161,29 @@ module Doorkeeper::OAuth
156
161
  subject.redirect_uri = nil
157
162
  expect(subject).not_to be_authorizable
158
163
  end
164
+
165
+ describe "as_json" do
166
+ let(:client_id) { "client_uid_123" }
167
+ let(:client_name) { "Acme Co." }
168
+
169
+ before do
170
+ allow(client).to receive(:uid).and_return client_id
171
+ allow(client).to receive(:name).and_return client_name
172
+ end
173
+
174
+ let(:json) { subject.as_json({}) }
175
+
176
+ it { is_expected.to respond_to :as_json }
177
+
178
+ it "returns correct values" do
179
+ expect(json[:client_id]).to eq client_id
180
+ expect(json[:redirect_uri]).to eq subject.redirect_uri
181
+ expect(json[:state]).to eq subject.state
182
+ expect(json[:response_type]).to eq subject.response_type
183
+ expect(json[:scope]).to eq subject.scope
184
+ expect(json[:client_name]).to eq client_name
185
+ expect(json[:status]).to eq I18n.t('doorkeeper.pre_authorization.status')
186
+ end
187
+ end
159
188
  end
160
189
  end