doorkeeper 3.1.0 → 4.4.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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +25 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  5. data/.gitignore +6 -1
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +26 -10
  9. data/Appraisals +18 -0
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/CONTRIBUTING.md +2 -0
  12. data/Gemfile +5 -5
  13. data/NEWS.md +141 -2
  14. data/README.md +149 -66
  15. data/RELEASING.md +5 -12
  16. data/Rakefile +1 -1
  17. data/SECURITY.md +15 -0
  18. data/app/controllers/doorkeeper/application_controller.rb +4 -6
  19. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  20. data/app/controllers/doorkeeper/applications_controller.rb +18 -8
  21. data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
  22. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  23. data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
  24. data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
  25. data/app/validators/redirect_uri_validator.rb +12 -2
  26. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  27. data/app/views/doorkeeper/applications/_form.html.erb +13 -2
  28. data/app/views/doorkeeper/applications/index.html.erb +2 -0
  29. data/app/views/doorkeeper/applications/show.html.erb +4 -1
  30. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  31. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
  34. data/config/locales/en.yml +12 -7
  35. data/doorkeeper.gemspec +16 -11
  36. data/gemfiles/rails_4_2.gemfile +13 -0
  37. data/gemfiles/rails_5_0.gemfile +12 -0
  38. data/gemfiles/rails_5_1.gemfile +12 -0
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +119 -46
  42. data/lib/doorkeeper/engine.rb +11 -7
  43. data/lib/doorkeeper/errors.rb +18 -0
  44. data/lib/doorkeeper/grape/helpers.rb +14 -8
  45. data/lib/doorkeeper/helpers/controller.rb +8 -19
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
  47. data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
  48. data/lib/doorkeeper/models/application_mixin.rb +33 -35
  49. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  50. data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
  51. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  52. data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
  53. data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
  54. data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
  57. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
  58. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  59. data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
  60. data/lib/doorkeeper/oauth/client.rb +2 -3
  61. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  62. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  63. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  64. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
  65. data/lib/doorkeeper/oauth/code_response.rb +16 -16
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +10 -10
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
  75. data/lib/doorkeeper/oauth/scopes.rb +18 -8
  76. data/lib/doorkeeper/oauth/token.rb +20 -21
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  79. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
  82. data/lib/doorkeeper/orm/active_record/application.rb +48 -11
  83. data/lib/doorkeeper/orm/active_record.rb +17 -22
  84. data/lib/doorkeeper/rails/helpers.rb +6 -9
  85. data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
  86. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  87. data/lib/doorkeeper/rails/routes.rb +17 -11
  88. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  89. data/lib/doorkeeper/request/password.rb +2 -2
  90. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  91. data/lib/doorkeeper/request.rb +7 -1
  92. data/lib/doorkeeper/server.rb +0 -8
  93. data/lib/doorkeeper/validations.rb +3 -2
  94. data/lib/doorkeeper/version.rb +34 -1
  95. data/lib/doorkeeper.rb +10 -2
  96. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
  97. data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
  98. data/lib/generators/doorkeeper/migration_generator.rb +13 -1
  99. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
  100. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
  101. data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
  102. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
  105. data/spec/controllers/application_metal_controller.rb +10 -0
  106. data/spec/controllers/applications_controller_spec.rb +15 -4
  107. data/spec/controllers/authorizations_controller_spec.rb +74 -27
  108. data/spec/controllers/protected_resources_controller_spec.rb +70 -32
  109. data/spec/controllers/token_info_controller_spec.rb +17 -13
  110. data/spec/controllers/tokens_controller_spec.rb +198 -12
  111. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
  112. data/spec/dummy/app/controllers/home_controller.rb +1 -1
  113. data/spec/dummy/app/controllers/metal_controller.rb +1 -1
  114. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
  115. data/spec/dummy/app/models/user.rb +0 -4
  116. data/spec/dummy/config/application.rb +2 -36
  117. data/spec/dummy/config/environment.rb +1 -1
  118. data/spec/dummy/config/environments/test.rb +4 -15
  119. data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
  120. data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
  121. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  122. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  123. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  124. data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
  125. data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
  126. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
  127. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
  128. data/spec/dummy/db/schema.rb +24 -22
  129. data/spec/factories.rb +4 -2
  130. data/spec/generators/application_owner_generator_spec.rb +24 -5
  131. data/spec/generators/migration_generator_spec.rb +24 -3
  132. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  133. data/spec/grape/grape_integration_spec.rb +135 -0
  134. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  135. data/spec/lib/config_spec.rb +159 -14
  136. data/spec/lib/doorkeeper_spec.rb +135 -13
  137. data/spec/lib/models/expirable_spec.rb +0 -1
  138. data/spec/lib/models/revocable_spec.rb +27 -4
  139. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  140. data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
  141. data/spec/lib/oauth/base_request_spec.rb +155 -0
  142. data/spec/lib/oauth/base_response_spec.rb +45 -0
  143. data/spec/lib/oauth/client/credentials_spec.rb +45 -2
  144. data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
  145. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  146. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
  147. data/spec/lib/oauth/code_request_spec.rb +1 -3
  148. data/spec/lib/oauth/code_response_spec.rb +34 -0
  149. data/spec/lib/oauth/error_response_spec.rb +9 -9
  150. data/spec/lib/oauth/error_spec.rb +1 -1
  151. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
  152. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  153. data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
  154. data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
  155. data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
  156. data/spec/lib/oauth/scopes_spec.rb +28 -2
  157. data/spec/lib/oauth/token_request_spec.rb +6 -8
  158. data/spec/lib/oauth/token_spec.rb +12 -5
  159. data/spec/lib/server_spec.rb +10 -3
  160. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  161. data/spec/models/doorkeeper/access_token_spec.rb +116 -48
  162. data/spec/models/doorkeeper/application_spec.rb +145 -29
  163. data/spec/requests/applications/applications_request_spec.rb +5 -5
  164. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  165. data/spec/requests/endpoints/token_spec.rb +8 -1
  166. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  167. data/spec/requests/flows/authorization_code_spec.rb +6 -13
  168. data/spec/requests/flows/client_credentials_spec.rb +29 -1
  169. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  170. data/spec/requests/flows/password_spec.rb +118 -15
  171. data/spec/requests/flows/refresh_token_spec.rb +89 -19
  172. data/spec/requests/flows/revoke_token_spec.rb +105 -91
  173. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  174. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  175. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  176. data/spec/routing/default_routes_spec.rb +5 -1
  177. data/spec/spec_helper.rb +2 -0
  178. data/spec/spec_helper_integration.rb +22 -4
  179. data/spec/support/dependencies/factory_girl.rb +2 -2
  180. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  181. data/spec/support/helpers/model_helper.rb +34 -7
  182. data/spec/support/helpers/request_spec_helper.rb +17 -5
  183. data/spec/support/helpers/url_helper.rb +9 -8
  184. data/spec/support/http_method_shim.rb +38 -0
  185. data/spec/support/shared/controllers_shared_context.rb +15 -10
  186. data/spec/support/shared/models_shared_examples.rb +5 -5
  187. data/spec/validators/redirect_uri_validator_spec.rb +51 -6
  188. data/spec/version/version_spec.rb +15 -0
  189. metadata +128 -46
  190. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  191. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  192. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  193. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
  194. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  195. data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -1,28 +1,150 @@
1
1
  require 'spec_helper_integration'
2
2
 
3
3
  describe Doorkeeper do
4
- describe 'authenticate' do
5
- let(:token) { double('Token') }
6
- let(:request) { double('ActionDispatch::Request') }
4
+ describe "#authenticate" do
5
+ let(:request) { double }
6
+
7
+ it "calls OAuth::Token#authenticate" do
8
+ token_strategies = Doorkeeper.configuration.access_token_methods
9
+
10
+ expect(Doorkeeper::OAuth::Token).to receive(:authenticate).
11
+ with(request, *token_strategies)
12
+
13
+ Doorkeeper.authenticate(request)
14
+ end
15
+
16
+ it "accepts custom token strategies" do
17
+ token_strategies = [:first_way, :second_way]
18
+
19
+ expect(Doorkeeper::OAuth::Token).to receive(:authenticate).
20
+ with(request, *token_strategies)
21
+
22
+ Doorkeeper.authenticate(request, token_strategies)
23
+ end
24
+ end
25
+
26
+ describe "#configured?" do
27
+ after do
28
+ Doorkeeper.remove_instance_variable(:@config)
29
+ end
30
+
31
+ context "@config is set" do
32
+ it "returns true" do
33
+ Doorkeeper.instance_variable_set(:@config, "hi")
34
+
35
+ expect(Doorkeeper.configured?).to eq(true)
36
+ end
37
+ end
38
+
39
+ context "@config is not set" do
40
+ it "returns false" do
41
+ Doorkeeper.instance_variable_set(:@config, nil)
42
+
43
+ expect(Doorkeeper.configured?).to eq(false)
44
+ end
45
+ end
46
+
47
+ it "is deprecated" do
48
+ expect(ActiveSupport::Deprecation).to receive(:warn).
49
+ with("Method `Doorkeeper#configured?` has been deprecated without replacement.")
50
+
51
+ Doorkeeper.configured?
52
+ end
53
+ end
54
+
55
+ describe "#database_installed?" do
7
56
  before do
8
- allow(Doorkeeper::OAuth::Token).to receive(:authenticate).
9
- with(request, *token_strategies) { token }
57
+ ["AccessToken", "AccessGrant", "Application"].each do |klass|
58
+ @original_classes ||= {}
59
+ @original_classes[klass] = Doorkeeper.const_get(klass)
60
+ Doorkeeper.send(:remove_const, klass)
61
+ end
62
+ end
63
+
64
+ after do
65
+ ["AccessToken", "AccessGrant", "Application"].each do |klass|
66
+ Doorkeeper.send(:remove_const, klass)
67
+ Doorkeeper.const_set(klass, @original_classes[klass])
68
+ end
10
69
  end
11
70
 
12
- context 'with specific access token strategies' do
13
- let(:token_strategies) { [:first_way, :second_way] }
71
+ context "all tables exist" do
72
+ before do
73
+ klass = double table_exists?: true
74
+
75
+ Doorkeeper.const_set(:AccessToken, klass)
76
+ Doorkeeper.const_set(:AccessGrant, klass)
77
+ Doorkeeper.const_set(:Application, klass)
78
+ end
14
79
 
15
- it 'authenticates the token from the request' do
16
- expect(Doorkeeper.authenticate(request, token_strategies)).to eq(token)
80
+ it "returns true" do
81
+ expect(Doorkeeper.database_installed?).to eq(true)
82
+ end
83
+
84
+ it "is deprecated" do
85
+ expect(ActiveSupport::Deprecation).to receive(:warn).
86
+ with("Method `Doorkeeper#database_installed?` has been deprecated without replacement.")
87
+
88
+ Doorkeeper.database_installed?
17
89
  end
18
90
  end
19
91
 
20
- context 'with default access token strategies' do
21
- let(:token_strategies) { Doorkeeper.configuration.access_token_methods }
92
+ context "all tables do not exist" do
93
+ before do
94
+ klass = double table_exists?: false
95
+
96
+ Doorkeeper.const_set(:AccessToken, klass)
97
+ Doorkeeper.const_set(:AccessGrant, klass)
98
+ Doorkeeper.const_set(:Application, klass)
99
+ end
100
+
101
+ it "returns false" do
102
+ expect(Doorkeeper.database_installed?).to eq(false)
103
+ end
104
+
105
+ it "is deprecated" do
106
+ expect(ActiveSupport::Deprecation).to receive(:warn).
107
+ with("Method `Doorkeeper#database_installed?` has been deprecated without replacement.")
22
108
 
23
- it 'authenticates the token from the request' do
24
- expect(Doorkeeper.authenticate(request)).to eq(token)
109
+ Doorkeeper.database_installed?
25
110
  end
26
111
  end
27
112
  end
113
+
114
+ describe "#installed?" do
115
+ context "methods return true" do
116
+ before do
117
+ allow(Doorkeeper).to receive(:configured?).and_return(true).once
118
+ allow(Doorkeeper).to receive(:database_installed?).and_return(true).once
119
+ end
120
+
121
+ it "returns true" do
122
+ expect(Doorkeeper.installed?).to eq(true)
123
+ end
124
+ end
125
+
126
+ context "methods return false" do
127
+ before do
128
+ allow(Doorkeeper).to receive(:configured?).and_return(false).once
129
+ allow(Doorkeeper).to receive(:database_installed?).and_return(false).once
130
+ end
131
+
132
+ it "returns false" do
133
+ expect(Doorkeeper.installed?).to eq(false)
134
+ end
135
+ end
136
+
137
+ it "is deprecated" do
138
+ expect(ActiveSupport::Deprecation).to receive(:warn).
139
+ with("Method `Doorkeeper#configured?` has been deprecated without replacement.")
140
+
141
+ expect(ActiveSupport::Deprecation).to receive(:warn).
142
+ with("Method `Doorkeeper#database_installed?` has been deprecated without replacement.")
143
+
144
+ expect(ActiveSupport::Deprecation).to receive(:warn).
145
+ with("Method `Doorkeeper#installed?` has been deprecated without replacement.")
146
+
147
+ Doorkeeper.installed?
148
+ end
149
+ end
28
150
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'timecop'
3
2
  require 'active_support/time'
4
3
  require 'doorkeeper/models/concerns/expirable'
5
4
 
@@ -11,20 +11,21 @@ describe 'Revocable' do
11
11
 
12
12
  describe :revoke do
13
13
  it 'updates :revoked_at attribute with current time' do
14
- clock = double now: double
15
- expect(subject).to receive(:update_attribute).with(:revoked_at, clock.now)
14
+ utc = double utc: double
15
+ clock = double now: utc
16
+ expect(subject).to receive(:update_attribute).with(:revoked_at, clock.now.utc)
16
17
  subject.revoke(clock)
17
18
  end
18
19
  end
19
20
 
20
21
  describe :revoked? do
21
22
  it 'is revoked if :revoked_at has passed' do
22
- allow(subject).to receive(:revoked_at).and_return(Time.now - 1000)
23
+ allow(subject).to receive(:revoked_at).and_return(Time.now.utc - 1000)
23
24
  expect(subject).to be_revoked
24
25
  end
25
26
 
26
27
  it 'is not revoked if :revoked_at has not passed' do
27
- allow(subject).to receive(:revoked_at).and_return(Time.now + 1000)
28
+ allow(subject).to receive(:revoked_at).and_return(Time.now.utc + 1000)
28
29
  expect(subject).not_to be_revoked
29
30
  end
30
31
 
@@ -33,4 +34,26 @@ describe 'Revocable' do
33
34
  expect(subject).not_to be_revoked
34
35
  end
35
36
  end
37
+
38
+ describe :revoke_previous_refresh_token! do
39
+ it "revokes the previous token if existing, and resets the
40
+ `previous_refresh_token` attribute" do
41
+ previous_token = FactoryBot.create(
42
+ :access_token,
43
+ refresh_token: "refresh_token"
44
+ )
45
+ current_token = FactoryBot.create(
46
+ :access_token,
47
+ previous_refresh_token: previous_token.refresh_token
48
+ )
49
+
50
+ expect_any_instance_of(
51
+ Doorkeeper::AccessToken
52
+ ).to receive(:revoke).and_call_original
53
+ current_token.revoke_previous_refresh_token!
54
+
55
+ expect(current_token.previous_refresh_token).to be_empty
56
+ expect(previous_token.reload).to be_revoked
57
+ end
58
+ end
36
59
  end
@@ -6,8 +6,7 @@ require 'doorkeeper/oauth/authorization/uri_builder'
6
6
 
7
7
  module Doorkeeper::OAuth::Authorization
8
8
  describe URIBuilder do
9
-
10
- subject { Object.new.class.send :include, URIBuilder }
9
+ subject { URIBuilder }
11
10
 
12
11
  describe :uri_with_query do
13
12
  it 'returns the uri with query' do
@@ -8,17 +8,20 @@ module Doorkeeper::OAuth
8
8
  refresh_token_enabled?: false,
9
9
  custom_access_token_expires_in: ->(_app) { nil }
10
10
  end
11
- let(:grant) { FactoryGirl.create :access_grant }
11
+
12
+ let(:grant) { FactoryBot.create :access_grant }
12
13
  let(:client) { grant.application }
14
+ let(:redirect_uri) { client.redirect_uri }
15
+ let(:params) { { redirect_uri: redirect_uri } }
13
16
 
14
17
  subject do
15
- AuthorizationCodeRequest.new server, grant, client, redirect_uri: client.redirect_uri
18
+ AuthorizationCodeRequest.new server, grant, client, params
16
19
  end
17
20
 
18
21
  it 'issues a new token for the client' do
19
22
  expect do
20
23
  subject.authorize
21
- end.to change { client.access_tokens.count }.by(1)
24
+ end.to change { client.reload.access_tokens.count }.by(1)
22
25
  end
23
26
 
24
27
  it "issues the token with same grant's scopes" do
@@ -27,9 +30,7 @@ module Doorkeeper::OAuth
27
30
  end
28
31
 
29
32
  it 'revokes the grant' do
30
- expect do
31
- subject.authorize
32
- end.to change { grant.reload.accessible? }
33
+ expect { subject.authorize }.to change { grant.reload.accessible? }
33
34
  end
34
35
 
35
36
  it 'requires the grant to be accessible' do
@@ -63,18 +64,60 @@ module Doorkeeper::OAuth
63
64
  end
64
65
 
65
66
  it "matches the client with grant's one" do
66
- subject.client = FactoryGirl.create :application
67
+ subject.client = FactoryBot.create :application
67
68
  subject.validate
68
69
  expect(subject.error).to eq(:invalid_grant)
69
70
  end
70
71
 
71
72
  it 'skips token creation if there is a matching one' do
72
- allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
73
- FactoryGirl.create(:access_token, application_id: client.id,
73
+ Doorkeeper.configure do
74
+ orm DOORKEEPER_ORM
75
+ reuse_access_token
76
+ end
77
+
78
+ FactoryBot.create(:access_token, application_id: client.id,
74
79
  resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s)
75
- expect do
76
- subject.authorize
77
- end.to_not change { Doorkeeper::AccessToken.count }
80
+
81
+ expect { subject.authorize }.to_not change { Doorkeeper::AccessToken.count }
82
+ end
83
+
84
+ it "calls configured request callback methods" do
85
+ expect(Doorkeeper.configuration.before_successful_strategy_response).to receive(:call).with(subject).once
86
+ expect(Doorkeeper.configuration.after_successful_strategy_response).to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
87
+ subject.authorize
88
+ end
89
+
90
+ context "when redirect_uri contains some query params" do
91
+ let(:redirect_uri) { client.redirect_uri + "?query=q" }
92
+
93
+ it "compares only host part with grant's redirect_uri" do
94
+ subject.validate
95
+ expect(subject.error).to eq(nil)
96
+ end
97
+ end
98
+
99
+ context "when redirect_uri is not an URI" do
100
+ let(:redirect_uri) { '123d#!s' }
101
+
102
+ it "responds with invalid_grant" do
103
+ subject.validate
104
+ expect(subject.error).to eq(:invalid_grant)
105
+ end
106
+ end
107
+
108
+ context "when redirect_uri is the native one" do
109
+ let(:redirect_uri) { 'urn:ietf:wg:oauth:2.0:oob' }
110
+
111
+ it "invalidates when redirect_uri of the grant is not native" do
112
+ subject.validate
113
+ expect(subject.error).to eq(:invalid_grant)
114
+ end
115
+
116
+ it "validates when redirect_uri of the grant is also native" do
117
+ allow(grant).to receive(:redirect_uri) { redirect_uri }
118
+ subject.validate
119
+ expect(subject.error).to eq(nil)
120
+ end
78
121
  end
79
122
  end
80
123
  end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe BaseRequest do
5
+ let(:access_token) do
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
14
+ end
15
+
16
+ let(:client) { double :client, id: '1' }
17
+
18
+ let(:scopes_array) { %w[public write] }
19
+
20
+ let(:server) do
21
+ double :server,
22
+ access_token_expires_in: 100,
23
+ custom_access_token_expires_in: ->(_) { nil },
24
+ refresh_token_enabled?: false
25
+ end
26
+
27
+ subject do
28
+ BaseRequest.new
29
+ end
30
+
31
+ describe "#authorize" do
32
+ before do
33
+ allow(subject).to receive(:access_token).and_return(access_token)
34
+ end
35
+
36
+ it "validates itself" do
37
+ expect(subject).to receive(:validate).once
38
+ subject.authorize
39
+ end
40
+
41
+ context "valid" do
42
+ before do
43
+ allow(subject).to receive(:valid?).and_return(true)
44
+ end
45
+
46
+ it "calls callback methods" do
47
+ expect(subject).to receive(:before_successful_response).once
48
+ expect(subject).to receive(:after_successful_response).once
49
+ subject.authorize
50
+ end
51
+
52
+ it "returns a TokenResponse object" do
53
+ result = subject.authorize
54
+
55
+ expect(result).to be_an_instance_of(TokenResponse)
56
+ expect(result.body).to eq(
57
+ TokenResponse.new(access_token).body
58
+ )
59
+ end
60
+ end
61
+
62
+ context "invalid" do
63
+ before do
64
+ allow(subject).to receive(:valid?).and_return(false)
65
+ allow(subject).to receive(:error).and_return("server_error")
66
+ allow(subject).to receive(:state).and_return("hello")
67
+ end
68
+
69
+ it "returns an ErrorResponse object" do
70
+ error_description = I18n.translate(
71
+ "server_error",
72
+ scope: %i[doorkeeper errors messages]
73
+ )
74
+
75
+ result = subject.authorize
76
+
77
+ expect(result).to be_an_instance_of(ErrorResponse)
78
+
79
+ expect(result.body).to eq(
80
+ error: "server_error",
81
+ error_description: error_description,
82
+ state: "hello"
83
+ )
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "#default_scopes" do
89
+ it "delegates to the server" do
90
+ expect(subject).to receive(:server).and_return(server).once
91
+ expect(server).to receive(:default_scopes).once
92
+
93
+ subject.default_scopes
94
+ end
95
+ end
96
+
97
+ describe "#find_or_create_access_token" do
98
+ it "returns an instance of AccessToken" do
99
+ result = subject.find_or_create_access_token(
100
+ client,
101
+ "1",
102
+ "public",
103
+ server
104
+ )
105
+
106
+ expect(result).to be_an_instance_of(Doorkeeper::AccessToken)
107
+ end
108
+ end
109
+
110
+ describe "#scopes" do
111
+ context "@original_scopes is present" do
112
+ before do
113
+ subject.instance_variable_set(:@original_scopes, "public write")
114
+ end
115
+
116
+ it "returns array of @original_scopes" do
117
+ result = subject.scopes
118
+
119
+ expect(result).to eq(scopes_array)
120
+ end
121
+ end
122
+
123
+ context "@original_scopes is not present" do
124
+ before do
125
+ subject.instance_variable_set(:@original_scopes, "")
126
+ end
127
+
128
+ it "calls #default_scopes" do
129
+ allow(subject).to receive(:server).and_return(server).once
130
+ allow(server).to receive(:default_scopes).and_return(scopes_array).once
131
+
132
+ result = subject.scopes
133
+
134
+ expect(result).to eq(scopes_array)
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "#valid?" do
140
+ context "error is nil" do
141
+ it "returns true" do
142
+ allow(subject).to receive(:error).and_return(nil).once
143
+ expect(subject.valid?).to eq(true)
144
+ end
145
+ end
146
+
147
+ context "error is not nil" do
148
+ it "returns false" do
149
+ allow(subject).to receive(:error).and_return(Object.new).once
150
+ expect(subject.valid?).to eq(false)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe BaseResponse do
5
+ subject do
6
+ BaseResponse.new
7
+ end
8
+
9
+ describe "#body" do
10
+ it "returns an empty Hash" do
11
+ expect(subject.body).to eq({})
12
+ end
13
+ end
14
+
15
+ describe "#description" do
16
+ it "returns an empty String" do
17
+ expect(subject.description).to eq("")
18
+ end
19
+ end
20
+
21
+ describe "#headers" do
22
+ it "returns an empty Hash" do
23
+ expect(subject.headers).to eq({})
24
+ end
25
+ end
26
+
27
+ describe "#redirectable?" do
28
+ it "returns false" do
29
+ expect(subject.redirectable?).to eq(false)
30
+ end
31
+ end
32
+
33
+ describe "#redirect_uri" do
34
+ it "returns an empty String" do
35
+ expect(subject.redirect_uri).to eq("")
36
+ end
37
+ end
38
+
39
+ describe "#status" do
40
+ it "returns :ok" do
41
+ expect(subject.status).to eq(:ok)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -4,9 +4,14 @@ require 'doorkeeper/oauth/client'
4
4
 
5
5
  class Doorkeeper::OAuth::Client
6
6
  describe Credentials do
7
- it 'is blank when any of the credentials is blank' do
7
+ let(:client_id) { 'some-uid' }
8
+ let(:client_secret) { 'some-secret' }
9
+
10
+ it 'is blank when the uid in credentials is blank' do
11
+ expect(Credentials.new(nil, nil)).to be_blank
8
12
  expect(Credentials.new(nil, 'something')).to be_blank
9
- expect(Credentials.new('something', nil)).to be_blank
13
+ expect(Credentials.new('something', nil)).to be_present
14
+ expect(Credentials.new('something', 'something')).to be_present
10
15
  end
11
16
 
12
17
  describe :from_request do
@@ -43,5 +48,43 @@ class Doorkeeper::OAuth::Client
43
48
  expect(credentials.secret).to eq('secret')
44
49
  end
45
50
  end
51
+
52
+ describe :from_params do
53
+ it 'returns credentials from parameters when Authorization header is not available' do
54
+ request = double parameters: { client_id: client_id, client_secret: client_secret }
55
+ uid, secret = Credentials.from_params(request)
56
+
57
+ expect(uid).to eq('some-uid')
58
+ expect(secret).to eq('some-secret')
59
+ end
60
+
61
+ it 'is blank when there are no credentials' do
62
+ request = double parameters: {}
63
+ uid, secret = Credentials.from_params(request)
64
+
65
+ expect(uid).to be_blank
66
+ expect(secret).to be_blank
67
+ end
68
+ end
69
+
70
+ describe :from_basic do
71
+ let(:credentials) { Base64.encode64("#{client_id}:#{client_secret}") }
72
+
73
+ it 'decodes the credentials' do
74
+ request = double authorization: "Basic #{credentials}"
75
+ uid, secret = Credentials.from_basic(request)
76
+
77
+ expect(uid).to eq('some-uid')
78
+ expect(secret).to eq('some-secret')
79
+ end
80
+
81
+ it 'is blank if Authorization is not Basic' do
82
+ request = double authorization: "#{credentials}"
83
+ uid, secret = Credentials.from_basic(request)
84
+
85
+ expect(uid).to be_blank
86
+ expect(secret).to be_blank
87
+ end
88
+ end
46
89
  end
47
90
  end
@@ -2,7 +2,7 @@ require 'spec_helper_integration'
2
2
 
3
3
  class Doorkeeper::OAuth::ClientCredentialsRequest
4
4
  describe Creator do
5
- let(:client) { FactoryGirl.create :application }
5
+ let(:client) { FactoryBot.create :application }
6
6
  let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public') }
7
7
 
8
8
  it 'creates a new token' do
@@ -5,7 +5,7 @@ module Doorkeeper::OAuth
5
5
  let(:server) { Doorkeeper.configuration }
6
6
 
7
7
  context 'with a valid request' do
8
- let(:client) { FactoryGirl.create :application }
8
+ let(:client) { FactoryBot.create :application }
9
9
 
10
10
  it 'issues an access token' do
11
11
  request = ClientCredentialsRequest.new(server, client, {})
@@ -11,6 +11,7 @@ module Doorkeeper::OAuth
11
11
  custom_access_token_expires_in: ->(_app) { nil }
12
12
  )
13
13
  end
14
+
14
15
  let(:application) { double :application, scopes: Scopes.from_string('') }
15
16
  let(:client) { double :client, application: application }
16
17
  let(:token_creator) { double :issuer, create: true, token: double }
@@ -32,9 +32,7 @@ module Doorkeeper::OAuth
32
32
 
33
33
  it 'does not create grant when not authorizable' do
34
34
  allow(pre_auth).to receive(:authorizable?).and_return(false)
35
- expect do
36
- subject.authorize
37
- end.to_not change { Doorkeeper::AccessGrant.count }
35
+ expect { subject.authorize }.not_to change { Doorkeeper::AccessGrant.count }
38
36
  end
39
37
 
40
38
  it 'returns a error response' do
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ describe CodeResponse do
6
+ describe '.redirect_uri' do
7
+ context 'when generating the redirect URI for an implicit grant' do
8
+ let :pre_auth do
9
+ double(
10
+ :pre_auth,
11
+ client: double(:application, id: 1),
12
+ redirect_uri: 'http://tst.com/cb',
13
+ state: nil,
14
+ scopes: Scopes.from_string('public'),
15
+ )
16
+ end
17
+
18
+ let :auth do
19
+ Authorization::Token.new(pre_auth, double(id: 1)).tap do |c|
20
+ c.issue_token
21
+ allow(c.token).to receive(:expires_in_seconds).and_return(3600)
22
+ end
23
+ end
24
+
25
+ subject { CodeResponse.new(pre_auth, auth, response_on_fragment: true).redirect_uri }
26
+
27
+ it 'includes the remaining TTL of the token relative to the time the token was generated' do
28
+ expect(subject).to include('expires_in=3600')
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end