doorkeeper 4.2.5 → 4.3.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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +19 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +1 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +13 -0
- data/.travis.yml +13 -4
- data/Appraisals +6 -2
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +28 -0
- data/README.md +40 -10
- data/RELEASING.md +5 -12
- data/SECURITY.md +13 -0
- data/app/controllers/doorkeeper/application_controller.rb +1 -5
- data/app/controllers/doorkeeper/applications_controller.rb +14 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +13 -1
- data/app/helpers/doorkeeper/dashboard_helper.rb +4 -2
- data/app/validators/redirect_uri_validator.rb +12 -2
- data/app/views/doorkeeper/applications/_form.html.erb +2 -2
- data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/config/locales/en.yml +3 -5
- data/doorkeeper.gemspec +4 -4
- data/gemfiles/rails_4_2.gemfile +6 -4
- data/gemfiles/rails_5_0.gemfile +4 -4
- data/gemfiles/rails_5_1.gemfile +6 -7
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +55 -55
- data/lib/doorkeeper/engine.rb +3 -3
- data/lib/doorkeeper/errors.rb +18 -0
- data/lib/doorkeeper/grape/helpers.rb +13 -8
- data/lib/doorkeeper/helpers/controller.rb +9 -20
- data/lib/doorkeeper/models/access_token_mixin.rb +14 -7
- data/lib/doorkeeper/models/application_mixin.rb +11 -6
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -1
- data/lib/doorkeeper/oauth/base_request.rb +5 -5
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -2
- data/lib/doorkeeper/oauth/client.rb +2 -2
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +1 -2
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -3
- data/lib/doorkeeper/oauth/password_access_token_request.rb +1 -0
- data/lib/doorkeeper/oauth/refresh_token_request.rb +1 -0
- data/lib/doorkeeper/oauth/scopes.rb +18 -8
- data/lib/doorkeeper/oauth/token.rb +1 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_token.rb +1 -23
- data/lib/doorkeeper/orm/active_record/application.rb +1 -1
- data/lib/doorkeeper/orm/active_record/base_record.rb +11 -0
- data/lib/doorkeeper/orm/active_record.rb +20 -8
- data/lib/doorkeeper/rails/helpers.rb +5 -6
- data/lib/doorkeeper/rails/routes.rb +9 -7
- data/lib/doorkeeper/request.rb +7 -1
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +13 -1
- data/lib/doorkeeper.rb +1 -0
- data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
- data/lib/generators/doorkeeper/migration_generator.rb +13 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -1
- data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/initializer.rb +19 -3
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +1 -1
- data/spec/controllers/applications_controller_spec.rb +15 -4
- data/spec/controllers/authorizations_controller_spec.rb +31 -16
- data/spec/controllers/protected_resources_controller_spec.rb +28 -19
- data/spec/controllers/token_info_controller_spec.rb +17 -13
- data/spec/controllers/tokens_controller_spec.rb +138 -4
- data/spec/dummy/config/initializers/doorkeeper.rb +1 -1
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +1 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +24 -5
- data/spec/generators/migration_generator_spec.rb +24 -3
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +115 -12
- data/spec/lib/models/expirable_spec.rb +0 -1
- data/spec/lib/models/revocable_spec.rb +2 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +39 -11
- data/spec/lib/oauth/base_request_spec.rb +2 -7
- data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
- data/spec/lib/oauth/code_request_spec.rb +1 -3
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -0
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +9 -3
- data/spec/lib/oauth/refresh_token_request_spec.rb +19 -7
- data/spec/lib/oauth/scopes_spec.rb +28 -1
- data/spec/lib/oauth/token_request_spec.rb +6 -8
- data/spec/lib/server_spec.rb +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +72 -48
- data/spec/models/doorkeeper/application_spec.rb +51 -18
- data/spec/requests/applications/applications_request_spec.rb +5 -5
- data/spec/requests/endpoints/token_spec.rb +8 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
- data/spec/requests/flows/authorization_code_spec.rb +1 -0
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
- data/spec/requests/flows/refresh_token_spec.rb +4 -4
- data/spec/requests/flows/revoke_token_spec.rb +15 -15
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/routing/default_routes_spec.rb +5 -1
- data/spec/spec_helper_integration.rb +15 -5
- data/spec/support/dependencies/factory_girl.rb +2 -2
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +7 -3
- data/spec/support/helpers/url_helper.rb +8 -8
- data/spec/support/shared/controllers_shared_context.rb +2 -6
- data/spec/support/shared/models_shared_examples.rb +4 -4
- data/spec/validators/redirect_uri_validator_spec.rb +51 -6
- data/spec/version/version_spec.rb +15 -0
- metadata +42 -27
data/gemfiles/rails_5_1.gemfile
CHANGED
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "rails",
|
|
5
|
+
gem "rails", "~> 5.1.0"
|
|
6
6
|
gem "appraisal"
|
|
7
|
-
gem "activerecord-jdbcsqlite3-adapter", :
|
|
8
|
-
gem "sqlite3", :
|
|
9
|
-
gem "tzinfo-data", :
|
|
10
|
-
gem "
|
|
11
|
-
gem "rspec-rails", "~> 3.5"
|
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
|
|
8
|
+
gem "sqlite3", platforms: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
9
|
+
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
10
|
+
gem "rspec-rails", "~> 3.7"
|
|
12
11
|
|
|
13
|
-
gemspec :
|
|
12
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rails", "5.2.0.rc1"
|
|
6
|
+
gem "appraisal"
|
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
|
|
8
|
+
gem "sqlite3", platforms: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
9
|
+
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
10
|
+
gem "rspec-rails", "~> 3.7"
|
|
11
|
+
|
|
12
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rails", git: 'https://github.com/rails/rails'
|
|
6
|
+
gem "arel", git: 'https://github.com/rails/arel'
|
|
7
|
+
|
|
8
|
+
gem "appraisal"
|
|
9
|
+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
10
|
+
gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
11
|
+
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
12
|
+
gem "rspec-rails", "~> 3.7"
|
|
13
|
+
|
|
14
|
+
gemspec path: "../"
|
data/lib/doorkeeper/config.rb
CHANGED
|
@@ -59,12 +59,12 @@ doorkeeper.
|
|
|
59
59
|
# @option opts[Boolean] :confirmation (false)
|
|
60
60
|
# Set confirm_application_owner variable
|
|
61
61
|
def enable_application_owner(opts = {})
|
|
62
|
-
@config.instance_variable_set(
|
|
62
|
+
@config.instance_variable_set(:@enable_application_owner, true)
|
|
63
63
|
confirm_application_owner if opts[:confirmation].present? && opts[:confirmation]
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def confirm_application_owner
|
|
67
|
-
@config.instance_variable_set(
|
|
67
|
+
@config.instance_variable_set(:@confirm_application_owner, true)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
# Define default access token scopes for your provider
|
|
@@ -72,7 +72,7 @@ doorkeeper.
|
|
|
72
72
|
# @param scopes [Array] Default set of access (OAuth::Scopes.new)
|
|
73
73
|
# token scopes
|
|
74
74
|
def default_scopes(*scopes)
|
|
75
|
-
@config.instance_variable_set(
|
|
75
|
+
@config.instance_variable_set(:@default_scopes, OAuth::Scopes.from_array(scopes))
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Define default access token scopes for your provider
|
|
@@ -80,7 +80,7 @@ doorkeeper.
|
|
|
80
80
|
# @param scopes [Array] Optional set of access (OAuth::Scopes.new)
|
|
81
81
|
# token scopes
|
|
82
82
|
def optional_scopes(*scopes)
|
|
83
|
-
@config.instance_variable_set(
|
|
83
|
+
@config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
# Change the way client credentials are retrieved from the request object.
|
|
@@ -90,7 +90,7 @@ doorkeeper.
|
|
|
90
90
|
#
|
|
91
91
|
# @param methods [Array] Define client credentials
|
|
92
92
|
def client_credentials(*methods)
|
|
93
|
-
@config.instance_variable_set(
|
|
93
|
+
@config.instance_variable_set(:@client_credentials, methods)
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
# Change the way access token is authenticated from the request object.
|
|
@@ -100,57 +100,19 @@ doorkeeper.
|
|
|
100
100
|
#
|
|
101
101
|
# @param methods [Array] Define access token methods
|
|
102
102
|
def access_token_methods(*methods)
|
|
103
|
-
@config.instance_variable_set(
|
|
103
|
+
@config.instance_variable_set(:@access_token_methods, methods)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
# Issue access tokens with refresh token (disabled by default)
|
|
107
107
|
def use_refresh_token
|
|
108
|
-
@config.instance_variable_set(
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# WWW-Authenticate Realm (default "Doorkeeper").
|
|
112
|
-
#
|
|
113
|
-
# @param realm [String] ("Doorkeeper") Authentication realm
|
|
114
|
-
def realm(realm)
|
|
115
|
-
@config.instance_variable_set('@realm', realm)
|
|
108
|
+
@config.instance_variable_set(:@refresh_token_enabled, true)
|
|
116
109
|
end
|
|
117
110
|
|
|
118
111
|
# Reuse access token for the same resource owner within an application
|
|
119
112
|
# (disabled by default)
|
|
120
113
|
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
|
121
114
|
def reuse_access_token
|
|
122
|
-
@config.instance_variable_set(
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# Forces the usage of the HTTPS protocol in non-native redirect uris
|
|
126
|
-
# (enabled by default in non-development environments). OAuth2
|
|
127
|
-
# delegates security in communication to the HTTPS protocol so it is
|
|
128
|
-
# wise to keep this enabled.
|
|
129
|
-
#
|
|
130
|
-
# @param [Boolean] boolean value for the parameter, true by default in
|
|
131
|
-
# non-development environment
|
|
132
|
-
def force_ssl_in_redirect_uri(boolean)
|
|
133
|
-
@config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Use a custom class for generating the access token.
|
|
137
|
-
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
|
138
|
-
#
|
|
139
|
-
# @param access_token_generator [String]
|
|
140
|
-
# the name of the access token generator class
|
|
141
|
-
def access_token_generator(access_token_generator)
|
|
142
|
-
@config.instance_variable_set(
|
|
143
|
-
'@access_token_generator', access_token_generator
|
|
144
|
-
)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# The controller Doorkeeper::ApplicationController inherits from.
|
|
148
|
-
# Defaults to ActionController::Base.
|
|
149
|
-
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
|
150
|
-
#
|
|
151
|
-
# @param base_controller [String] the name of the base controller
|
|
152
|
-
def base_controller(base_controller)
|
|
153
|
-
@config.instance_variable_set('@base_controller', base_controller)
|
|
115
|
+
@config.instance_variable_set(:@reuse_access_token, true)
|
|
154
116
|
end
|
|
155
117
|
end
|
|
156
118
|
|
|
@@ -210,10 +172,6 @@ doorkeeper.
|
|
|
210
172
|
|
|
211
173
|
public attribute
|
|
212
174
|
end
|
|
213
|
-
|
|
214
|
-
def extended(base)
|
|
215
|
-
base.send(:private, :option)
|
|
216
|
-
end
|
|
217
175
|
end
|
|
218
176
|
|
|
219
177
|
extend Option
|
|
@@ -221,15 +179,17 @@ doorkeeper.
|
|
|
221
179
|
option :resource_owner_authenticator,
|
|
222
180
|
as: :authenticate_resource_owner,
|
|
223
181
|
default: (lambda do |_routes|
|
|
224
|
-
logger.warn(I18n.
|
|
182
|
+
::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
|
|
225
183
|
nil
|
|
226
184
|
end)
|
|
185
|
+
|
|
227
186
|
option :admin_authenticator,
|
|
228
187
|
as: :authenticate_admin,
|
|
229
188
|
default: ->(_routes) {}
|
|
189
|
+
|
|
230
190
|
option :resource_owner_from_credentials,
|
|
231
191
|
default: (lambda do |_routes|
|
|
232
|
-
warn(I18n.
|
|
192
|
+
::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.credential_flow_not_configured'))
|
|
233
193
|
nil
|
|
234
194
|
end)
|
|
235
195
|
|
|
@@ -240,11 +200,51 @@ doorkeeper.
|
|
|
240
200
|
option :orm, default: :active_record
|
|
241
201
|
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
|
|
242
202
|
option :active_record_options, default: {}
|
|
203
|
+
option :grant_flows, default: %w[authorization_code client_credentials]
|
|
204
|
+
|
|
205
|
+
# Allows to forbid specific Application redirect URI's by custom rules.
|
|
206
|
+
# Doesn't forbid any URI by default.
|
|
207
|
+
#
|
|
208
|
+
# @param forbid_redirect_uri [Proc] Block or any object respond to #call
|
|
209
|
+
#
|
|
210
|
+
option :forbid_redirect_uri, default: ->(_uri) { false }
|
|
211
|
+
|
|
212
|
+
# WWW-Authenticate Realm (default "Doorkeeper").
|
|
213
|
+
#
|
|
214
|
+
# @param realm [String] ("Doorkeeper") Authentication realm
|
|
215
|
+
#
|
|
243
216
|
option :realm, default: 'Doorkeeper'
|
|
217
|
+
|
|
218
|
+
# Forces the usage of the HTTPS protocol in non-native redirect uris
|
|
219
|
+
# (enabled by default in non-development environments). OAuth2
|
|
220
|
+
# delegates security in communication to the HTTPS protocol so it is
|
|
221
|
+
# wise to keep this enabled.
|
|
222
|
+
#
|
|
223
|
+
# @param [Boolean] boolean_or_block value for the parameter, true by default in
|
|
224
|
+
# non-development environment
|
|
225
|
+
#
|
|
226
|
+
# @yield [uri] Conditional usage of SSL redirect uris.
|
|
227
|
+
# @yieldparam [URI] Redirect URI
|
|
228
|
+
# @yieldreturn [Boolean] Indicates necessity of usage of the HTTPS protocol
|
|
229
|
+
# in non-native redirect uris
|
|
230
|
+
#
|
|
244
231
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
|
245
|
-
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# Use a custom class for generating the access token.
|
|
235
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
|
236
|
+
#
|
|
237
|
+
# @param access_token_generator [String]
|
|
238
|
+
# the name of the access token generator class
|
|
239
|
+
#
|
|
246
240
|
option :access_token_generator,
|
|
247
241
|
default: 'Doorkeeper::OAuth::Helpers::UniqueToken'
|
|
242
|
+
|
|
243
|
+
# The controller Doorkeeper::ApplicationController inherits from.
|
|
244
|
+
# Defaults to ActionController::Base.
|
|
245
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
|
246
|
+
#
|
|
247
|
+
# @param base_controller [String] the name of the base controller
|
|
248
248
|
option :base_controller,
|
|
249
249
|
default: 'ActionController::Base'
|
|
250
250
|
|
|
@@ -278,11 +278,11 @@ doorkeeper.
|
|
|
278
278
|
end
|
|
279
279
|
|
|
280
280
|
def client_credentials_methods
|
|
281
|
-
@client_credentials ||= [
|
|
281
|
+
@client_credentials ||= %i[from_basic from_params]
|
|
282
282
|
end
|
|
283
283
|
|
|
284
284
|
def access_token_methods
|
|
285
|
-
@access_token_methods ||= [
|
|
285
|
+
@access_token_methods ||= %i[from_bearer_authorization from_access_token_param from_bearer_param]
|
|
286
286
|
end
|
|
287
287
|
|
|
288
288
|
def authorization_response_types
|
data/lib/doorkeeper/engine.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Doorkeeper
|
|
2
2
|
class Engine < Rails::Engine
|
|
3
3
|
initializer "doorkeeper.params.filter" do |app|
|
|
4
|
-
parameters = %w
|
|
4
|
+
parameters = %w[client_secret code authentication_token access_token refresh_token]
|
|
5
5
|
app.config.filter_parameters << /^(#{Regexp.union parameters})$/
|
|
6
6
|
end
|
|
7
7
|
|
|
@@ -17,10 +17,10 @@ module Doorkeeper
|
|
|
17
17
|
|
|
18
18
|
if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
|
|
19
19
|
initializer 'doorkeeper.assets.precompile' do |app|
|
|
20
|
-
app.config.assets.precompile += %w
|
|
20
|
+
app.config.assets.precompile += %w[
|
|
21
21
|
doorkeeper/application.css
|
|
22
22
|
doorkeeper/admin/application.css
|
|
23
|
-
|
|
23
|
+
]
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
end
|
data/lib/doorkeeper/errors.rb
CHANGED
|
@@ -1,21 +1,39 @@
|
|
|
1
1
|
module Doorkeeper
|
|
2
2
|
module Errors
|
|
3
3
|
class DoorkeeperError < StandardError
|
|
4
|
+
def type
|
|
5
|
+
message
|
|
6
|
+
end
|
|
4
7
|
end
|
|
5
8
|
|
|
6
9
|
class InvalidAuthorizationStrategy < DoorkeeperError
|
|
10
|
+
def type
|
|
11
|
+
:unsupported_response_type
|
|
12
|
+
end
|
|
7
13
|
end
|
|
8
14
|
|
|
9
15
|
class InvalidTokenReuse < DoorkeeperError
|
|
16
|
+
def type
|
|
17
|
+
:invalid_request
|
|
18
|
+
end
|
|
10
19
|
end
|
|
11
20
|
|
|
12
21
|
class InvalidGrantReuse < DoorkeeperError
|
|
22
|
+
def type
|
|
23
|
+
:invalid_grant
|
|
24
|
+
end
|
|
13
25
|
end
|
|
14
26
|
|
|
15
27
|
class InvalidTokenStrategy < DoorkeeperError
|
|
28
|
+
def type
|
|
29
|
+
:unsupported_grant_type
|
|
30
|
+
end
|
|
16
31
|
end
|
|
17
32
|
|
|
18
33
|
class MissingRequestStrategy < DoorkeeperError
|
|
34
|
+
def type
|
|
35
|
+
:invalid_request
|
|
36
|
+
end
|
|
19
37
|
end
|
|
20
38
|
|
|
21
39
|
class UnableToGenerateToken < DoorkeeperError
|
|
@@ -9,7 +9,7 @@ module Doorkeeper
|
|
|
9
9
|
|
|
10
10
|
# endpoint specific scopes > parameter scopes > default scopes
|
|
11
11
|
def doorkeeper_authorize!(*scopes)
|
|
12
|
-
endpoint_scopes =
|
|
12
|
+
endpoint_scopes = endpoint.route_setting(:scopes) || endpoint.options[:route_options][:scopes]
|
|
13
13
|
scopes = if endpoint_scopes
|
|
14
14
|
Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
|
|
15
15
|
elsif scopes && !scopes.empty?
|
|
@@ -20,18 +20,16 @@ module Doorkeeper
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def doorkeeper_render_error_with(error)
|
|
23
|
-
status_code =
|
|
24
|
-
when :unauthorized
|
|
25
|
-
401
|
|
26
|
-
when :forbidden
|
|
27
|
-
403
|
|
28
|
-
end
|
|
29
|
-
|
|
23
|
+
status_code = error_status_codes[error.status]
|
|
30
24
|
error!({ error: error.description }, status_code, error.headers)
|
|
31
25
|
end
|
|
32
26
|
|
|
33
27
|
private
|
|
34
28
|
|
|
29
|
+
def endpoint
|
|
30
|
+
env['api.endpoint']
|
|
31
|
+
end
|
|
32
|
+
|
|
35
33
|
def doorkeeper_token
|
|
36
34
|
@_doorkeeper_token ||= OAuth::Token.authenticate(
|
|
37
35
|
decorated_request,
|
|
@@ -42,6 +40,13 @@ module Doorkeeper
|
|
|
42
40
|
def decorated_request
|
|
43
41
|
AuthorizationDecorator.new(request)
|
|
44
42
|
end
|
|
43
|
+
|
|
44
|
+
def error_status_codes
|
|
45
|
+
{
|
|
46
|
+
unauthorized: 401,
|
|
47
|
+
forbidden: 403
|
|
48
|
+
}
|
|
49
|
+
end
|
|
45
50
|
end
|
|
46
51
|
end
|
|
47
52
|
end
|
|
@@ -5,11 +5,13 @@ module Doorkeeper
|
|
|
5
5
|
module Controller
|
|
6
6
|
private
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
# :doc:
|
|
9
|
+
def authenticate_resource_owner!
|
|
9
10
|
current_resource_owner
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
# :doc:
|
|
14
|
+
def current_resource_owner
|
|
13
15
|
instance_eval(&Doorkeeper.configuration.authenticate_resource_owner)
|
|
14
16
|
end
|
|
15
17
|
|
|
@@ -17,7 +19,8 @@ module Doorkeeper
|
|
|
17
19
|
instance_eval(&Doorkeeper.configuration.resource_owner_from_credentials)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
# :doc:
|
|
23
|
+
def authenticate_admin!
|
|
21
24
|
instance_eval(&Doorkeeper.configuration.authenticate_admin)
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -25,7 +28,8 @@ module Doorkeeper
|
|
|
25
28
|
@server ||= Server.new(self)
|
|
26
29
|
end
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
# :doc:
|
|
32
|
+
def doorkeeper_token
|
|
29
33
|
@token ||= OAuth::Token.authenticate request, *config_methods
|
|
30
34
|
end
|
|
31
35
|
|
|
@@ -34,22 +38,7 @@ module Doorkeeper
|
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
def get_error_response_from_exception(exception)
|
|
37
|
-
|
|
38
|
-
when Errors::InvalidTokenStrategy
|
|
39
|
-
:unsupported_grant_type
|
|
40
|
-
when Errors::InvalidAuthorizationStrategy
|
|
41
|
-
:unsupported_response_type
|
|
42
|
-
when Errors::MissingRequestStrategy
|
|
43
|
-
:invalid_request
|
|
44
|
-
when Errors::InvalidTokenReuse
|
|
45
|
-
:invalid_request
|
|
46
|
-
when Errors::InvalidGrantReuse
|
|
47
|
-
:invalid_grant
|
|
48
|
-
when Errors::DoorkeeperError
|
|
49
|
-
exception.message
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
OAuth::ErrorResponse.new name: error_name, state: params[:state]
|
|
41
|
+
OAuth::ErrorResponse.new name: exception.type, state: params[:state]
|
|
53
42
|
end
|
|
54
43
|
|
|
55
44
|
def handle_token_exception(exception)
|
|
@@ -68,11 +68,11 @@ module Doorkeeper
|
|
|
68
68
|
# @param resource_owner [ActiveRecord::Base]
|
|
69
69
|
# instance of the Resource Owner model
|
|
70
70
|
#
|
|
71
|
-
def revoke_all_for(application_id, resource_owner)
|
|
71
|
+
def revoke_all_for(application_id, resource_owner, clock = Time)
|
|
72
72
|
where(application_id: application_id,
|
|
73
73
|
resource_owner_id: resource_owner.id,
|
|
74
74
|
revoked_at: nil).
|
|
75
|
-
|
|
75
|
+
update_all(revoked_at: clock.now.utc)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Looking for not expired Access Token with a matching set of scopes
|
|
@@ -168,7 +168,7 @@ module Doorkeeper
|
|
|
168
168
|
# nil if nothing was found
|
|
169
169
|
#
|
|
170
170
|
def last_authorized_token_for(application_id, resource_owner_id)
|
|
171
|
-
|
|
171
|
+
ordered_by(:created_at, :desc).
|
|
172
172
|
find_by(application_id: application_id,
|
|
173
173
|
resource_owner_id: resource_owner_id,
|
|
174
174
|
revoked_at: nil)
|
|
@@ -247,7 +247,11 @@ module Doorkeeper
|
|
|
247
247
|
def generate_token
|
|
248
248
|
self.created_at ||= Time.now.utc
|
|
249
249
|
|
|
250
|
-
generator =
|
|
250
|
+
generator = token_generator
|
|
251
|
+
unless generator.respond_to?(:generate)
|
|
252
|
+
raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
|
|
253
|
+
end
|
|
254
|
+
|
|
251
255
|
self.token = generator.generate(
|
|
252
256
|
resource_owner_id: resource_owner_id,
|
|
253
257
|
scopes: scopes,
|
|
@@ -255,10 +259,13 @@ module Doorkeeper
|
|
|
255
259
|
expires_in: expires_in,
|
|
256
260
|
created_at: created_at
|
|
257
261
|
)
|
|
258
|
-
|
|
259
|
-
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def token_generator
|
|
265
|
+
generator_name = Doorkeeper.configuration.access_token_generator
|
|
266
|
+
generator_name.constantize
|
|
260
267
|
rescue NameError
|
|
261
|
-
raise Errors::TokenGeneratorNotFound, "#{
|
|
268
|
+
raise Errors::TokenGeneratorNotFound, "#{generator_name} not found"
|
|
262
269
|
end
|
|
263
270
|
end
|
|
264
271
|
end
|
|
@@ -43,6 +43,15 @@ module Doorkeeper
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
# Set an application's valid redirect URIs.
|
|
47
|
+
#
|
|
48
|
+
# @param uris [String, Array] Newline-separated string or array the URI(s)
|
|
49
|
+
#
|
|
50
|
+
# @return [String] The redirect URI(s) seperated by newlines.
|
|
51
|
+
def redirect_uri=(uris)
|
|
52
|
+
super(uris.is_a?(Array) ? uris.join("\n") : uris)
|
|
53
|
+
end
|
|
54
|
+
|
|
46
55
|
private
|
|
47
56
|
|
|
48
57
|
def has_scopes?
|
|
@@ -51,15 +60,11 @@ module Doorkeeper
|
|
|
51
60
|
end
|
|
52
61
|
|
|
53
62
|
def generate_uid
|
|
54
|
-
if uid.blank?
|
|
55
|
-
self.uid = UniqueToken.generate
|
|
56
|
-
end
|
|
63
|
+
self.uid = UniqueToken.generate if uid.blank?
|
|
57
64
|
end
|
|
58
65
|
|
|
59
66
|
def generate_secret
|
|
60
|
-
if secret.blank?
|
|
61
|
-
self.secret = UniqueToken.generate
|
|
62
|
-
end
|
|
67
|
+
self.secret = UniqueToken.generate if secret.blank?
|
|
63
68
|
end
|
|
64
69
|
end
|
|
65
70
|
end
|
|
@@ -6,7 +6,7 @@ module Doorkeeper
|
|
|
6
6
|
#
|
|
7
7
|
# @return [Boolean] true if object expired and false in other case
|
|
8
8
|
def expired?
|
|
9
|
-
expires_in && Time.now.utc >
|
|
9
|
+
expires_in && Time.now.utc > expires_at
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# Calculates expiration time in seconds.
|
|
@@ -15,14 +15,16 @@ module Doorkeeper
|
|
|
15
15
|
# or nil if object never expires.
|
|
16
16
|
def expires_in_seconds
|
|
17
17
|
return nil if expires_in.nil?
|
|
18
|
-
expires =
|
|
18
|
+
expires = expires_at - Time.now.utc
|
|
19
19
|
expires_sec = expires.seconds.round(0)
|
|
20
20
|
expires_sec > 0 ? expires_sec : 0
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
# Expiration time (date time of creation + TTL).
|
|
24
|
+
#
|
|
25
|
+
# @return [Time] expiration time in UTC
|
|
26
|
+
#
|
|
27
|
+
def expires_at
|
|
26
28
|
created_at + expires_in.seconds
|
|
27
29
|
end
|
|
28
30
|
end
|
|
@@ -4,19 +4,33 @@ module Doorkeeper
|
|
|
4
4
|
class Token
|
|
5
5
|
attr_accessor :pre_auth, :resource_owner, :token
|
|
6
6
|
|
|
7
|
+
class << self
|
|
8
|
+
def access_token_expires_in(server, pre_auth_or_oauth_client)
|
|
9
|
+
if (expiration = custom_expiration(server, pre_auth_or_oauth_client))
|
|
10
|
+
expiration
|
|
11
|
+
else
|
|
12
|
+
server.access_token_expires_in
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def custom_expiration(server, pre_auth_or_oauth_client)
|
|
19
|
+
oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
|
|
20
|
+
pre_auth_or_oauth_client.client
|
|
21
|
+
else
|
|
22
|
+
pre_auth_or_oauth_client
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
server.custom_access_token_expires_in.call(oauth_client)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
7
29
|
def initialize(pre_auth, resource_owner)
|
|
8
30
|
@pre_auth = pre_auth
|
|
9
31
|
@resource_owner = resource_owner
|
|
10
32
|
end
|
|
11
33
|
|
|
12
|
-
def self.access_token_expires_in(server, pre_auth_or_oauth_client)
|
|
13
|
-
if expiration = custom_expiration(server, pre_auth_or_oauth_client)
|
|
14
|
-
expiration
|
|
15
|
-
else
|
|
16
|
-
server.access_token_expires_in
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
34
|
def issue_token
|
|
21
35
|
@token ||= AccessToken.find_or_create_for(
|
|
22
36
|
pre_auth.client,
|
|
@@ -37,16 +51,6 @@ module Doorkeeper
|
|
|
37
51
|
|
|
38
52
|
private
|
|
39
53
|
|
|
40
|
-
def self.custom_expiration(server, pre_auth_or_oauth_client)
|
|
41
|
-
oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
|
|
42
|
-
pre_auth_or_oauth_client.client
|
|
43
|
-
else
|
|
44
|
-
pre_auth_or_oauth_client
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
server.custom_access_token_expires_in.call(oauth_client)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
54
|
def configuration
|
|
51
55
|
Doorkeeper.configuration
|
|
52
56
|
end
|
|
@@ -4,6 +4,7 @@ module Doorkeeper
|
|
|
4
4
|
validate :attributes, error: :invalid_request
|
|
5
5
|
validate :client, error: :invalid_client
|
|
6
6
|
validate :grant, error: :invalid_grant
|
|
7
|
+
# @see https://tools.ietf.org/html/rfc6749#section-5.2
|
|
7
8
|
validate :redirect_uri, error: :invalid_grant
|
|
8
9
|
|
|
9
10
|
attr_accessor :server, :grant, :client, :redirect_uri, :access_token
|
|
@@ -28,6 +29,7 @@ module Doorkeeper
|
|
|
28
29
|
grant.scopes,
|
|
29
30
|
server)
|
|
30
31
|
end
|
|
32
|
+
super
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def validate_attributes
|
|
@@ -44,7 +46,10 @@ module Doorkeeper
|
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def validate_redirect_uri
|
|
47
|
-
|
|
49
|
+
Helpers::URIChecker.valid_for_authorization?(
|
|
50
|
+
redirect_uri,
|
|
51
|
+
grant.redirect_uri
|
|
52
|
+
)
|
|
48
53
|
end
|
|
49
54
|
end
|
|
50
55
|
end
|
|
@@ -5,6 +5,7 @@ module Doorkeeper
|
|
|
5
5
|
|
|
6
6
|
def authorize
|
|
7
7
|
validate
|
|
8
|
+
|
|
8
9
|
if valid?
|
|
9
10
|
before_successful_response
|
|
10
11
|
@response = TokenResponse.new(access_token)
|
|
@@ -37,14 +38,13 @@ module Doorkeeper
|
|
|
37
38
|
resource_owner_id,
|
|
38
39
|
scopes,
|
|
39
40
|
Authorization::Token.access_token_expires_in(server, client),
|
|
40
|
-
server.refresh_token_enabled?
|
|
41
|
+
server.refresh_token_enabled?
|
|
42
|
+
)
|
|
41
43
|
end
|
|
42
44
|
|
|
43
|
-
def before_successful_response
|
|
44
|
-
end
|
|
45
|
+
def before_successful_response; end
|
|
45
46
|
|
|
46
|
-
def after_successful_response
|
|
47
|
-
end
|
|
47
|
+
def after_successful_response; end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Doorkeeper
|
|
2
2
|
module OAuth
|
|
3
3
|
class Client
|
|
4
|
-
|
|
4
|
+
Credentials = Struct.new(:uid, :secret) do
|
|
5
5
|
class << self
|
|
6
6
|
def from_request(request, *credentials_methods)
|
|
7
7
|
credentials_methods.inject(nil) do |credentials, method|
|
|
@@ -18,7 +18,7 @@ module Doorkeeper
|
|
|
18
18
|
def from_basic(request)
|
|
19
19
|
authorization = request.authorization
|
|
20
20
|
if authorization.present? && authorization =~ /^Basic (.*)/m
|
|
21
|
-
Base64.decode64(
|
|
21
|
+
Base64.decode64(Regexp.last_match(1)).split(/:/, 2)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|