doorkeeper 5.2.0.rc1 → 5.2.0
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.
- checksums.yaml +4 -4
- data/Appraisals +1 -1
- data/CHANGELOG.md +33 -2
- data/CONTRIBUTING.md +7 -0
- data/Dangerfile +1 -1
- data/Dockerfile +29 -0
- data/Gemfile +1 -1
- data/README.md +9 -1
- data/app/controllers/doorkeeper/application_controller.rb +1 -1
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
- data/app/controllers/doorkeeper/tokens_controller.rb +14 -1
- data/config/locales/en.yml +5 -1
- data/doorkeeper.gemspec +8 -0
- data/gemfiles/rails_6_0.gemfile +1 -1
- data/lib/doorkeeper/config.rb +64 -9
- data/lib/doorkeeper/errors.rb +13 -18
- data/lib/doorkeeper/helpers/controller.rb +6 -2
- data/lib/doorkeeper/models/access_token_mixin.rb +43 -2
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -5
- data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -9
- data/lib/doorkeeper/oauth/base_request.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +14 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +8 -0
- data/lib/doorkeeper/oauth/code_request.rb +5 -11
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +70 -37
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +16 -7
- data/lib/doorkeeper/oauth/token_request.rb +4 -18
- data/lib/doorkeeper/orm/active_record/application.rb +1 -1
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
- data/lib/doorkeeper/orm/active_record.rb +2 -2
- data/lib/doorkeeper/request/authorization_code.rb +2 -0
- data/lib/doorkeeper/request.rb +6 -11
- data/lib/doorkeeper/server.rb +2 -6
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +1 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +88 -43
- data/lib/generators/doorkeeper/templates/migration.rb.erb +1 -1
- data/spec/controllers/authorizations_controller_spec.rb +140 -61
- data/spec/controllers/protected_resources_controller_spec.rb +3 -3
- data/spec/controllers/tokens_controller_spec.rb +140 -40
- data/spec/dummy/config/initializers/doorkeeper.rb +47 -20
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +1 -1
- data/spec/lib/config_spec.rb +32 -1
- data/spec/lib/oauth/authorization_code_request_spec.rb +11 -1
- data/spec/lib/oauth/base_request_spec.rb +33 -16
- data/spec/lib/oauth/client_credentials/creator_spec.rb +3 -0
- data/spec/lib/oauth/code_request_spec.rb +27 -28
- data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -55
- data/spec/lib/oauth/refresh_token_request_spec.rb +1 -0
- data/spec/lib/oauth/token_request_spec.rb +20 -17
- data/spec/lib/server_spec.rb +0 -12
- data/spec/requests/endpoints/authorization_spec.rb +21 -5
- data/spec/requests/endpoints/token_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
- data/spec/requests/flows/authorization_code_spec.rb +77 -23
- data/spec/requests/flows/client_credentials_spec.rb +38 -0
- data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
- data/spec/requests/flows/implicit_grant_spec.rb +9 -8
- data/spec/requests/flows/password_spec.rb +37 -0
- data/spec/requests/flows/refresh_token_spec.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +14 -2
- data/spec/validators/redirect_uri_validator_spec.rb +1 -1
- metadata +15 -6
- data/app/validators/redirect_uri_validator.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5184a79d20bb22a118af7f53e465f3d16b4e8796819bc3d3787118b65e2faa5
|
4
|
+
data.tar.gz: 36dbd460edaad12e3550210d3edfa1c2f6b82bfa600c7a6fc3c1e730bc7d34c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b1183b93495fcaf34b7d1761d1e605e9203bdcfa483ebc6b3c11895b781ace879439f84d92d05dc9321bf28014b64e4c2a63666a20a389b26a34f1a5dc3c048
|
7
|
+
data.tar.gz: 75959d91b24d5a34538e9bf2d5fca263bbd9338a1cf20d808a6737b0ec4ee507f2d07ee47031d09ab7211e62be5803223f2a28d4099e91008741606162c3dafa
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -7,7 +7,38 @@ User-visible changes worth mentioning.
|
|
7
7
|
|
8
8
|
## master
|
9
9
|
|
10
|
-
- [#
|
10
|
+
- [#PR ID] Your PR description here.
|
11
|
+
|
12
|
+
## 5.2.0
|
13
|
+
|
14
|
+
- [#1305] Make `Doorkeeper::ApplicationController` to inherit from `ActionController::API` in cases
|
15
|
+
when `api_mode` enabled (fixes #1302).
|
16
|
+
|
17
|
+
## 5.2.0.rc3
|
18
|
+
|
19
|
+
- [#1298] Slice strong params so doesn't error with Rails forms.
|
20
|
+
- [#1300] Limiting access to attributes of pre_authorization.
|
21
|
+
- [#1296] Adding client_id to strong parameters.
|
22
|
+
- [#1293] Move ar specific redirect uri validator to ar orm directory.
|
23
|
+
- [#1288] Allow to pass attributes to the `Doorkeeper::OAuth::PreAuthorization#as_json` method to customize
|
24
|
+
the PreAuthorization response.
|
25
|
+
- [#1286] Add ability to customize grant flows per application (OAuth client) (#1245 , #1207)
|
26
|
+
- [#1283] Allow to customize base class for `Doorkeeper::ApplicationMetalController` (new configuration
|
27
|
+
option called `base_metal_controller` (fix #1273).
|
28
|
+
- [#1277] Prevent requested scope be empty on authorization request, handle and add description for invalid request.
|
29
|
+
|
30
|
+
## 5.2.0.rc2
|
31
|
+
|
32
|
+
- [#1270] Find matching tokens in batches for `reuse_access_token` option (fix #1193).
|
33
|
+
- [#1271] Reintroduce existing token revocation for client credentials.
|
34
|
+
- [#1269] Update initializer template documentation.
|
35
|
+
- [#1266] Use strong parameters within pre-authorization.
|
36
|
+
- [#1264] Add :before_successful_authorization and :after_successful_authorization hooks in TokensController
|
37
|
+
- [#1263] Response properly when introspection fails and fix configurations's user guide.
|
38
|
+
|
39
|
+
## 5.2.0.rc1
|
40
|
+
|
41
|
+
- [#1260], [#1262] Improve Token Introspection configuration option (access to tokens, client).
|
11
42
|
- [#1257] Add constraint configuration when using client authentication on introspection endpoint.
|
12
43
|
- [#1252] Returning `unauthorized` when the revocation of the token should not be performed due to wrong permissions.
|
13
44
|
- [#1249] Specify case sensitive uniqueness to remove Rails 6 deprecation message
|
@@ -31,7 +62,7 @@ User-visible changes worth mentioning.
|
|
31
62
|
|
32
63
|
- [#1208] Unify hashing implementation into secret storing strategies
|
33
64
|
|
34
|
-
**[IMPORTANT]
|
65
|
+
**[IMPORTANT]** If you have been using the master branch of doorkeeper with bcrypt in your Gemfile.lock,
|
35
66
|
your application secrets have been hashed using BCrypt. To restore this behavior, use the initializer option
|
36
67
|
`use_application_hashing using: 'Doorkeeper::SecretStoring::BCrypt`.
|
37
68
|
|
data/CONTRIBUTING.md
CHANGED
@@ -7,6 +7,13 @@ Fork, then clone the repo:
|
|
7
7
|
|
8
8
|
git clone git@github.com:your-username/doorkeeper.git
|
9
9
|
|
10
|
+
### Docker Setup
|
11
|
+
|
12
|
+
Build the container image with: `docker build --pull -t doorkeeper:test .`
|
13
|
+
Run the tests with: `docker run -it --rm doorkeeper:test`
|
14
|
+
|
15
|
+
### Local Setup
|
16
|
+
|
10
17
|
Set up Ruby dependencies via Bundler
|
11
18
|
|
12
19
|
bundle install
|
data/Dangerfile
CHANGED
@@ -11,7 +11,7 @@ def changelog_entry_example
|
|
11
11
|
.sub(/[?.!,;]?$/, '')
|
12
12
|
.capitalize
|
13
13
|
|
14
|
-
"- [##{pr_number}]
|
14
|
+
"- [##{pr_number}] #{pr_title}."
|
15
15
|
end
|
16
16
|
|
17
17
|
# --------------------------------------------------------------------------------------------------------------------
|
data/Dockerfile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
FROM ruby:2.6.3-alpine3.9
|
2
|
+
|
3
|
+
RUN apk add --no-cache \
|
4
|
+
ca-certificates \
|
5
|
+
wget \
|
6
|
+
openssl \
|
7
|
+
bash \
|
8
|
+
build-base \
|
9
|
+
git \
|
10
|
+
sqlite-dev \
|
11
|
+
tzdata
|
12
|
+
|
13
|
+
ENV LANG en_US.UTF-8
|
14
|
+
ENV LANGUAGE en_US:en
|
15
|
+
ENV LC_ALL en_US.UTF-8
|
16
|
+
|
17
|
+
ENV BUNDLER_VERSION 2.0.1
|
18
|
+
RUN gem install bundler -v ${BUNDLER_VERSION} -i /usr/local/lib/ruby/gems/$(ls /usr/local/lib/ruby/gems) --force
|
19
|
+
|
20
|
+
WORKDIR /srv
|
21
|
+
|
22
|
+
COPY Gemfile doorkeeper.gemspec /srv/
|
23
|
+
COPY lib/doorkeeper/version.rb /srv/lib/doorkeeper/version.rb
|
24
|
+
|
25
|
+
RUN bundle install
|
26
|
+
|
27
|
+
COPY . /srv/
|
28
|
+
|
29
|
+
CMD ["rake"]
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -21,10 +21,11 @@ Supported features:
|
|
21
21
|
- [Implicit grant](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.2)
|
22
22
|
- [Resource Owner Password Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.3)
|
23
23
|
- [Client Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.4)
|
24
|
-
- [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636)
|
25
24
|
- [OAuth 2.0 Token Revocation](http://tools.ietf.org/html/rfc7009)
|
26
25
|
- [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662)
|
27
26
|
- [OAuth 2.0 Threat Model and Security Considerations](http://tools.ietf.org/html/rfc6819)
|
27
|
+
- [OAuth 2.0 for Native Apps](https://tools.ietf.org/html/draft-ietf-oauth-native-apps-10)
|
28
|
+
- [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
|
28
29
|
|
29
30
|
## Table of Contents
|
30
31
|
|
@@ -93,6 +94,7 @@ Doorkeeper supports Active Record by default, but can be configured to work with
|
|
93
94
|
| MongoDB | [doorkeeper-gem/doorkeeper-mongodb](https://github.com/doorkeeper-gem/doorkeeper-mongodb) |
|
94
95
|
| Sequel | [nbulaj/doorkeeper-sequel](https://github.com/nbulaj/doorkeeper-sequel) |
|
95
96
|
| Couchbase | [acaprojects/doorkeeper-couchbase](https://github.com/acaprojects/doorkeeper-couchbase) |
|
97
|
+
| RethinkDB | [aca-labs/doorkeeper-rethinkdb](https://github.com/aca-labs/doorkeeper-rethinkdb) |
|
96
98
|
|
97
99
|
## Extensions
|
98
100
|
|
@@ -136,6 +138,12 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
|
|
136
138
|
|
137
139
|
> If you prefer not to deal with the gory details of OAuth 2, need dedicated customer support & consulting, try the cloud-based SaaS version: [https://oauth.io](https://oauth.io/?utm_source=doorkeeper-gem)
|
138
140
|
|
141
|
+
<br>
|
142
|
+
|
143
|
+
<a href="https://www.wealthsimple.com/?utm_source=doorkeeper-gem" target="_blank"><img src="https://wealthsimple.s3.amazonaws.com/branding/medium-black.svg"/></a>
|
144
|
+
|
145
|
+
> Wealthsimple is a financial company on a mission to help everyone achieve financial freedom by providing products and advice that are accessible and affordable. Using smart technology, Wealthsimple takes financial services that are often confusing, opaque and expensive and makes them simple, transparent, and low-cost. See what Investing on Autopilot is all about: [https://www.wealthsimple.com](https://www.wealthsimple.com/?utm_source=doorkeeper-gem)
|
146
|
+
|
139
147
|
## Development
|
140
148
|
|
141
149
|
To run the local engine server:
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
|
-
class ApplicationMetalController <
|
4
|
+
class ApplicationMetalController <
|
5
|
+
Doorkeeper.configuration.resolve_controller(:base_metal)
|
5
6
|
include Helpers::Controller
|
6
7
|
|
7
8
|
before_action :enforce_content_type,
|
@@ -12,7 +12,6 @@ module Doorkeeper
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
# TODO: Handle raise invalid authorization
|
16
15
|
def create
|
17
16
|
redirect_or_render authorize_response
|
18
17
|
end
|
@@ -66,9 +65,16 @@ module Doorkeeper
|
|
66
65
|
end
|
67
66
|
|
68
67
|
def pre_auth
|
69
|
-
@pre_auth ||= OAuth::PreAuthorization.new(Doorkeeper.configuration,
|
70
|
-
|
71
|
-
|
68
|
+
@pre_auth ||= OAuth::PreAuthorization.new(Doorkeeper.configuration, pre_auth_params)
|
69
|
+
end
|
70
|
+
|
71
|
+
def pre_auth_params
|
72
|
+
params.slice(*pre_auth_param_fields).permit(*pre_auth_param_fields)
|
73
|
+
end
|
74
|
+
|
75
|
+
def pre_auth_param_fields
|
76
|
+
%i[client_id response_type redirect_uri scope state code_challenge
|
77
|
+
code_challenge_method]
|
72
78
|
end
|
73
79
|
|
74
80
|
def authorization
|
@@ -81,10 +87,11 @@ module Doorkeeper
|
|
81
87
|
|
82
88
|
def authorize_response
|
83
89
|
@authorize_response ||= begin
|
84
|
-
|
85
|
-
|
90
|
+
return pre_auth.error_response unless pre_auth.authorizable?
|
91
|
+
|
92
|
+
before_successful_authorization
|
86
93
|
auth = strategy.authorize
|
87
|
-
after_successful_authorization
|
94
|
+
after_successful_authorization
|
88
95
|
auth
|
89
96
|
end
|
90
97
|
end
|
@@ -88,7 +88,20 @@ module Doorkeeper
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def authorize_response
|
91
|
-
@authorize_response ||=
|
91
|
+
@authorize_response ||= begin
|
92
|
+
before_successful_authorization
|
93
|
+
auth = strategy.authorize
|
94
|
+
after_successful_authorization unless auth.is_a?(Doorkeeper::OAuth::ErrorResponse)
|
95
|
+
auth
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def after_successful_authorization
|
100
|
+
Doorkeeper.configuration.after_successful_authorization.call(self)
|
101
|
+
end
|
102
|
+
|
103
|
+
def before_successful_authorization
|
104
|
+
Doorkeeper.configuration.before_successful_authorization.call(self)
|
92
105
|
end
|
93
106
|
|
94
107
|
def revocation_error_response
|
data/config/locales/en.yml
CHANGED
@@ -88,7 +88,11 @@ en:
|
|
88
88
|
errors:
|
89
89
|
messages:
|
90
90
|
# Common error messages
|
91
|
-
invalid_request:
|
91
|
+
invalid_request:
|
92
|
+
unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
|
93
|
+
missing_param: 'Missing required parameter: #{value}.'
|
94
|
+
not_support_pkce: 'Invalid code_verifier parameter. Server does not support pkce.'
|
95
|
+
request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
|
92
96
|
invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
|
93
97
|
unauthorized_client: 'The client is not authorized to perform this request using this method.'
|
94
98
|
access_denied: 'The resource owner or authorization server denied the request.'
|
data/doorkeeper.gemspec
CHANGED
@@ -18,6 +18,14 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = `git ls-files -- spec/*`.split("\n")
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
+
gem.metadata = {
|
22
|
+
"homepage_uri" => "https://github.com/doorkeeper-gem/doorkeeper",
|
23
|
+
"changelog_uri" => "https://github.com/doorkeeper-gem/doorkeeper/blob/master/CHANGELOG.md",
|
24
|
+
"source_code_uri" => "https://github.com/doorkeeper-gem/doorkeeper",
|
25
|
+
"bug_tracker_uri" => "https://github.com/doorkeeper-gem/doorkeeper/issues",
|
26
|
+
"documentation_uri" => "https://doorkeeper.gitbook.io/guides/",
|
27
|
+
}
|
28
|
+
|
21
29
|
gem.add_dependency "railties", ">= 5"
|
22
30
|
gem.required_ruby_version = ">= 2.4"
|
23
31
|
|
data/gemfiles/rails_6_0.gemfile
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem "rails", "~> 6.0.0
|
5
|
+
gem "rails", "~> 6.0.0"
|
6
6
|
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
7
7
|
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
8
8
|
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
data/lib/doorkeeper/config.rb
CHANGED
@@ -259,6 +259,32 @@ module Doorkeeper
|
|
259
259
|
option :grant_flows, default: %w[authorization_code client_credentials]
|
260
260
|
option :handle_auth_errors, default: :render
|
261
261
|
|
262
|
+
# Allows to customize OAuth grant flows that +each+ application support.
|
263
|
+
# You can configure a custom block (or use a class respond to `#call`) that must
|
264
|
+
# return `true` in case Application instance supports requested OAuth grant flow
|
265
|
+
# during the authorization request to the server. This configuration +doesn't+
|
266
|
+
# set flows per application, it only allows to check if application supports
|
267
|
+
# specific grant flow.
|
268
|
+
#
|
269
|
+
# For example you can add an additional database column to `oauth_applications` table,
|
270
|
+
# say `t.array :grant_flows, default: []`, and store allowed grant flows that can
|
271
|
+
# be used with this application there. Then when authorization requested Doorkeeper
|
272
|
+
# will call this block to check if specific Application (passed with client_id and/or
|
273
|
+
# client_secret) is allowed to perform the request for the specific grant type
|
274
|
+
# (authorization, password, client_credentials, etc).
|
275
|
+
#
|
276
|
+
# Example of the block:
|
277
|
+
#
|
278
|
+
# ->(flow, client) { client.grant_flows.include?(flow) }
|
279
|
+
#
|
280
|
+
# In case this option invocation result is `false`, Doorkeeper server returns
|
281
|
+
# :unauthorized_client error and stops the request.
|
282
|
+
#
|
283
|
+
# @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
|
284
|
+
# @return [Boolean] `true` if allow or `false` if forbid the request
|
285
|
+
#
|
286
|
+
option :allow_grant_flow_for_client, default: ->(_grant_flow, _client) { true }
|
287
|
+
|
262
288
|
# Allows to forbid specific Application redirect URI's by custom rules.
|
263
289
|
# Doesn't forbid any URI by default.
|
264
290
|
#
|
@@ -288,7 +314,7 @@ module Doorkeeper
|
|
288
314
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
289
315
|
|
290
316
|
# Use a custom class for generating the access token.
|
291
|
-
# https://
|
317
|
+
# https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
|
292
318
|
#
|
293
319
|
# @param access_token_generator [String]
|
294
320
|
# the name of the access token generator class
|
@@ -306,11 +332,20 @@ module Doorkeeper
|
|
306
332
|
|
307
333
|
# The controller Doorkeeper::ApplicationController inherits from.
|
308
334
|
# Defaults to ActionController::Base.
|
309
|
-
# https://
|
335
|
+
# https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
|
310
336
|
#
|
311
337
|
# @param base_controller [String] the name of the base controller
|
312
338
|
option :base_controller,
|
313
|
-
default:
|
339
|
+
default: (lambda do
|
340
|
+
api_only ? "ActionController::API" : "ActionController::Base"
|
341
|
+
end)
|
342
|
+
|
343
|
+
# The controller Doorkeeper::ApplicationMetalController inherits from.
|
344
|
+
# Defaults to ActionController::API.
|
345
|
+
#
|
346
|
+
# @param base_metal_controller [String] the name of the base controller
|
347
|
+
option :base_metal_controller,
|
348
|
+
default: "ActionController::API"
|
314
349
|
|
315
350
|
# Allows to set blank redirect URIs for Applications in case
|
316
351
|
# server configured to use URI-less grant flows.
|
@@ -322,9 +357,10 @@ module Doorkeeper
|
|
322
357
|
end)
|
323
358
|
|
324
359
|
# Configure protection of token introspection request.
|
325
|
-
# By default
|
326
|
-
#
|
327
|
-
#
|
360
|
+
# By default this configuration allows to introspect a token by
|
361
|
+
# another token of the same application, or to introspect the token
|
362
|
+
# that belongs to authorized client, or access token has been introspected
|
363
|
+
# is a public one (doesn't belong to any client)
|
328
364
|
#
|
329
365
|
# You can define any custom rule you need or just disable token
|
330
366
|
# introspection at all.
|
@@ -340,9 +376,11 @@ module Doorkeeper
|
|
340
376
|
# Bearer token used to authorize the request
|
341
377
|
#
|
342
378
|
option :allow_token_introspection,
|
343
|
-
default: (lambda do |token, authorized_client,
|
344
|
-
if
|
345
|
-
|
379
|
+
default: (lambda do |token, authorized_client, authorized_token|
|
380
|
+
if authorized_token
|
381
|
+
authorized_token.application == token&.application
|
382
|
+
elsif token.application
|
383
|
+
authorized_client == token.application
|
346
384
|
else
|
347
385
|
true
|
348
386
|
end
|
@@ -381,6 +419,17 @@ module Doorkeeper
|
|
381
419
|
@token_reuse_limit ||= 100
|
382
420
|
end
|
383
421
|
|
422
|
+
def resolve_controller(name)
|
423
|
+
config_option = public_send(:"#{name}_controller")
|
424
|
+
controller_name = if config_option.respond_to?(:call)
|
425
|
+
instance_exec(&config_option)
|
426
|
+
else
|
427
|
+
config_option
|
428
|
+
end
|
429
|
+
|
430
|
+
controller_name.constantize
|
431
|
+
end
|
432
|
+
|
384
433
|
def enforce_configured_scopes?
|
385
434
|
option_set? :enforce_configured_scopes
|
386
435
|
end
|
@@ -449,6 +498,12 @@ module Doorkeeper
|
|
449
498
|
end
|
450
499
|
end
|
451
500
|
|
501
|
+
def allow_grant_flow_for_client?(grant_flow, client)
|
502
|
+
return true unless option_defined?(:allow_grant_flow_for_client)
|
503
|
+
|
504
|
+
allow_grant_flow_for_client.call(grant_flow, client)
|
505
|
+
end
|
506
|
+
|
452
507
|
def option_defined?(name)
|
453
508
|
instance_variable_defined?("@#{name}")
|
454
509
|
end
|
data/lib/doorkeeper/errors.rb
CHANGED
@@ -8,18 +8,6 @@ module Doorkeeper
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
class InvalidAuthorizationStrategy < DoorkeeperError
|
12
|
-
def type
|
13
|
-
:unsupported_response_type
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class InvalidTokenReuse < DoorkeeperError
|
18
|
-
def type
|
19
|
-
:invalid_request
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
11
|
class InvalidGrantReuse < DoorkeeperError
|
24
12
|
def type
|
25
13
|
:invalid_grant
|
@@ -32,7 +20,14 @@ module Doorkeeper
|
|
32
20
|
end
|
33
21
|
end
|
34
22
|
|
35
|
-
class
|
23
|
+
class MissingRequiredParameter < DoorkeeperError
|
24
|
+
attr_reader :missing_param
|
25
|
+
|
26
|
+
def initialize(missing_param)
|
27
|
+
super
|
28
|
+
@missing_param = missing_param
|
29
|
+
end
|
30
|
+
|
36
31
|
def type
|
37
32
|
:invalid_request
|
38
33
|
end
|
@@ -50,10 +45,10 @@ module Doorkeeper
|
|
50
45
|
TokenGeneratorNotFound = Class.new(DoorkeeperError)
|
51
46
|
NoOrmCleaner = Class.new(DoorkeeperError)
|
52
47
|
|
53
|
-
InvalidToken = Class.new
|
54
|
-
TokenExpired = Class.new
|
55
|
-
TokenRevoked = Class.new
|
56
|
-
TokenUnknown = Class.new
|
57
|
-
TokenForbidden = Class.new
|
48
|
+
InvalidToken = Class.new(BaseResponseError)
|
49
|
+
TokenExpired = Class.new(InvalidToken)
|
50
|
+
TokenRevoked = Class.new(InvalidToken)
|
51
|
+
TokenUnknown = Class.new(InvalidToken)
|
52
|
+
TokenForbidden = Class.new(InvalidToken)
|
58
53
|
end
|
59
54
|
end
|
@@ -44,8 +44,12 @@ module Doorkeeper
|
|
44
44
|
def get_error_response_from_exception(exception)
|
45
45
|
if exception.respond_to?(:response)
|
46
46
|
exception.response
|
47
|
+
elsif exception.type == :invalid_request
|
48
|
+
OAuth::InvalidRequestResponse.new(name: exception.type,
|
49
|
+
state: params[:state],
|
50
|
+
missing_param: exception.missing_param)
|
47
51
|
else
|
48
|
-
OAuth::ErrorResponse.new
|
52
|
+
OAuth::ErrorResponse.new(name: exception.type, state: params[:state])
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
@@ -58,7 +62,7 @@ module Doorkeeper
|
|
58
62
|
|
59
63
|
def skip_authorization?
|
60
64
|
!!instance_exec(
|
61
|
-
[
|
65
|
+
[server.current_resource_owner, @pre_auth.client],
|
62
66
|
&Doorkeeper.configuration.skip_authorization
|
63
67
|
)
|
64
68
|
end
|
@@ -76,9 +76,50 @@ module Doorkeeper
|
|
76
76
|
end
|
77
77
|
|
78
78
|
tokens = authorized_tokens_for(application.try(:id), resource_owner_id)
|
79
|
-
tokens
|
80
|
-
|
79
|
+
find_matching_token(tokens, application, scopes)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Interface to enumerate access token records in batches in order not
|
83
|
+
# to bloat the memory. Could be overloaded in any ORM extension.
|
84
|
+
#
|
85
|
+
def find_access_token_in_batches(relation, *args, &block)
|
86
|
+
relation.find_in_batches(*args, &block)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Enumerates AccessToken records in batches to find a matching token.
|
90
|
+
# Batching is required in order not to pollute the memory if Application
|
91
|
+
# has huge amount of associated records.
|
92
|
+
#
|
93
|
+
# ActiveRecord 5.x - 6.x ignores custom ordering so we can't perform a
|
94
|
+
# database sort by created_at, so we need to load all the matching records,
|
95
|
+
# sort them and find latest one. Probably it would be better to rewrite this
|
96
|
+
# query using Time math if possible, but we n eed to consider ORM and
|
97
|
+
# different databases support.
|
98
|
+
#
|
99
|
+
# @param relation [ActiveRecord::Relation]
|
100
|
+
# Access tokens relation
|
101
|
+
# @param application [Doorkeeper::Application]
|
102
|
+
# Application instance
|
103
|
+
# @param scopes [String, Doorkeeper::OAuth::Scopes]
|
104
|
+
# set of scopes
|
105
|
+
#
|
106
|
+
# @return [Doorkeeper::AccessToken, nil] Access Token instance or
|
107
|
+
# nil if matching record was not found
|
108
|
+
#
|
109
|
+
def find_matching_token(relation, application, scopes)
|
110
|
+
return nil unless relation
|
111
|
+
|
112
|
+
matching_tokens = []
|
113
|
+
|
114
|
+
find_access_token_in_batches(relation) do |batch|
|
115
|
+
tokens = batch.select do |token|
|
116
|
+
scopes_match?(token.scopes, scopes, application.try(:scopes))
|
117
|
+
end
|
118
|
+
|
119
|
+
matching_tokens.concat(tokens)
|
81
120
|
end
|
121
|
+
|
122
|
+
matching_tokens.max_by(&:created_at)
|
82
123
|
end
|
83
124
|
|
84
125
|
# Checks whether the token scopes match the scopes from the parameters
|
@@ -19,14 +19,10 @@ module Doorkeeper
|
|
19
19
|
{ action: :show, code: token.plaintext_token }
|
20
20
|
end
|
21
21
|
|
22
|
-
def configuration
|
23
|
-
Doorkeeper.configuration
|
24
|
-
end
|
25
|
-
|
26
22
|
private
|
27
23
|
|
28
24
|
def authorization_code_expires_in
|
29
|
-
configuration.authorization_code_expires_in
|
25
|
+
Doorkeeper.configuration.authorization_code_expires_in
|
30
26
|
end
|
31
27
|
|
32
28
|
def access_grant_attributes
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module Doorkeeper
|
4
4
|
module OAuth
|
5
5
|
class AuthorizationCodeRequest < BaseRequest
|
6
|
-
validate :
|
6
|
+
validate :pkce_support, error: :invalid_request
|
7
|
+
validate :params, error: :invalid_request
|
7
8
|
validate :client, error: :invalid_client
|
8
9
|
validate :grant, error: :invalid_grant
|
9
10
|
# @see https://tools.ietf.org/html/rfc6749#section-5.2
|
@@ -12,6 +13,7 @@ module Doorkeeper
|
|
12
13
|
|
13
14
|
attr_accessor :server, :grant, :client, :redirect_uri, :access_token,
|
14
15
|
:code_verifier
|
16
|
+
attr_reader :invalid_request_reason, :missing_param
|
15
17
|
|
16
18
|
def initialize(server, grant, client, parameters = {})
|
17
19
|
@server = server
|
@@ -24,10 +26,6 @@ module Doorkeeper
|
|
24
26
|
|
25
27
|
private
|
26
28
|
|
27
|
-
def client_by_uid(parameters)
|
28
|
-
Doorkeeper::Application.by_uid(parameters[:client_id])
|
29
|
-
end
|
30
|
-
|
31
29
|
def before_successful_response
|
32
30
|
grant.transaction do
|
33
31
|
grant.lock!
|
@@ -42,11 +40,22 @@ module Doorkeeper
|
|
42
40
|
super
|
43
41
|
end
|
44
42
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
43
|
+
def validate_pkce_support
|
44
|
+
@invalid_request_reason = :not_support_pkce if grant &&
|
45
|
+
!grant.pkce_supported? &&
|
46
|
+
code_verifier.present?
|
47
|
+
|
48
|
+
@invalid_request_reason.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_params
|
52
|
+
@missing_param = if grant&.uses_pkce? && code_verifier.blank?
|
53
|
+
:code_verifier
|
54
|
+
elsif redirect_uri.blank?
|
55
|
+
:redirect_uri
|
56
|
+
end
|
48
57
|
|
49
|
-
|
58
|
+
@missing_param.nil?
|
50
59
|
end
|
51
60
|
|
52
61
|
def validate_client
|
@@ -15,6 +15,8 @@ module Doorkeeper
|
|
15
15
|
@response = TokenResponse.new(access_token)
|
16
16
|
after_successful_response
|
17
17
|
@response
|
18
|
+
elsif error == :invalid_request
|
19
|
+
@response = InvalidRequestResponse.from_request(self)
|
18
20
|
else
|
19
21
|
@response = ErrorResponse.from_request(self)
|
20
22
|
end
|
@@ -5,11 +5,25 @@ module Doorkeeper
|
|
5
5
|
class ClientCredentialsRequest < BaseRequest
|
6
6
|
class Creator
|
7
7
|
def call(client, scopes, attributes = {})
|
8
|
+
existing_token = existing_token_for(client, scopes)
|
9
|
+
|
10
|
+
if Doorkeeper.configuration.reuse_access_token && existing_token&.reusable?
|
11
|
+
return existing_token
|
12
|
+
end
|
13
|
+
|
14
|
+
existing_token&.revoke
|
15
|
+
|
8
16
|
AccessToken.find_or_create_for(
|
9
17
|
client, nil, scopes, attributes[:expires_in],
|
10
18
|
attributes[:use_refresh_token]
|
11
19
|
)
|
12
20
|
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def existing_token_for(client, scopes)
|
25
|
+
Doorkeeper::AccessToken.matching_token_for client, nil, scopes
|
26
|
+
end
|
13
27
|
end
|
14
28
|
end
|
15
29
|
end
|