doorkeeper 5.1.2 → 5.2.2
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 +854 -0
- data/CONTRIBUTING.md +11 -9
- data/Dangerfile +2 -2
- data/Dockerfile +29 -0
- data/Gemfile +3 -2
- data/NEWS.md +1 -819
- data/README.md +11 -3
- data/RELEASING.md +6 -5
- data/app/controllers/doorkeeper/application_controller.rb +1 -1
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
- data/app/controllers/doorkeeper/applications_controller.rb +5 -3
- data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
- data/app/views/doorkeeper/applications/_form.html.erb +0 -6
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/config/locales/en.yml +8 -2
- data/doorkeeper.gemspec +9 -1
- data/gemfiles/rails_5_0.gemfile +1 -0
- data/gemfiles/rails_5_1.gemfile +1 -0
- data/gemfiles/rails_5_2.gemfile +1 -0
- data/gemfiles/rails_6_0.gemfile +2 -1
- data/gemfiles/rails_master.gemfile +1 -0
- data/lib/doorkeeper/config/option.rb +13 -7
- data/lib/doorkeeper/config.rb +88 -6
- data/lib/doorkeeper/errors.rb +13 -18
- data/lib/doorkeeper/grape/helpers.rb +5 -1
- data/lib/doorkeeper/helpers/controller.rb +23 -4
- data/lib/doorkeeper/models/access_token_mixin.rb +43 -2
- data/lib/doorkeeper/oauth/authorization/code.rb +11 -13
- data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
- 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/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +18 -4
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -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 +13 -10
- data/lib/doorkeeper/oauth/token_introspection.rb +23 -13
- data/lib/doorkeeper/oauth/token_request.rb +4 -18
- data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_token.rb +2 -2
- data/lib/doorkeeper/orm/active_record/application.rb +15 -69
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
- data/lib/doorkeeper/orm/active_record.rb +19 -3
- 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/stale_records_cleaner.rb +6 -2
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +4 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +6 -6
- data/lib/generators/doorkeeper/templates/initializer.rb +110 -33
- data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
- data/spec/controllers/applications_controller_spec.rb +93 -0
- data/spec/controllers/authorizations_controller_spec.rb +143 -62
- data/spec/controllers/protected_resources_controller_spec.rb +3 -3
- data/spec/controllers/tokens_controller_spec.rb +205 -37
- data/spec/dummy/config/application.rb +3 -1
- data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +1 -1
- data/spec/lib/config_spec.rb +43 -1
- data/spec/lib/oauth/authorization_code_request_spec.rb +13 -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/helpers/uri_checker_spec.rb +17 -2
- data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
- data/spec/lib/oauth/pre_authorization_spec.rb +76 -66
- 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/models/doorkeeper/access_grant_spec.rb +21 -2
- data/spec/models/doorkeeper/access_token_spec.rb +35 -4
- data/spec/models/doorkeeper/application_spec.rb +275 -370
- 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 +93 -27
- 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/requests/flows/revoke_token_spec.rb +19 -11
- data/spec/support/doorkeeper_rspec.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +14 -2
- data/spec/validators/redirect_uri_validator_spec.rb +40 -15
- metadata +16 -15
- data/.coveralls.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -25
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- data/.gitignore +0 -20
- data/.gitlab-ci.yml +0 -16
- data/.hound.yml +0 -3
- data/.rspec +0 -1
- data/.rubocop.yml +0 -50
- data/.travis.yml +0 -35
- data/app/validators/redirect_uri_validator.rb +0 -50
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:
|
@@ -146,10 +154,10 @@ bundle exec rake doorkeeper:server
|
|
146
154
|
````
|
147
155
|
|
148
156
|
By default, it uses the latest Rails version with ActiveRecord. To run the
|
149
|
-
tests with a specific
|
157
|
+
tests with a specific Rails version:
|
150
158
|
|
151
159
|
```
|
152
|
-
|
160
|
+
BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake
|
153
161
|
```
|
154
162
|
|
155
163
|
## Contributing
|
data/RELEASING.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
# Releasing
|
1
|
+
# Releasing Doorkeeper
|
2
2
|
|
3
|
-
How to release
|
3
|
+
How to release Doorkeeper in five easy steps!
|
4
4
|
|
5
5
|
1. Update `lib/doorkeeper/version.rb` file accordingly.
|
6
|
-
2. Update `
|
7
|
-
3. Commit changes: `git commit -am 'Bump to vVERSION'
|
8
|
-
4.
|
6
|
+
2. Update `CHANGELOG.md` to reflect the changes since last release.
|
7
|
+
3. Commit changes: `git commit -am 'Bump to vVERSION'`.
|
8
|
+
4. Build and publish the gem.
|
9
|
+
4. Create GitHub release.
|
9
10
|
5. Announce the new release, making sure to say “thank you” to the contributors
|
10
11
|
who helped shape this version!
|
@@ -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,
|
@@ -4,6 +4,7 @@ module Doorkeeper
|
|
4
4
|
class ApplicationsController < Doorkeeper::ApplicationController
|
5
5
|
layout "doorkeeper/admin" unless Doorkeeper.configuration.api_only
|
6
6
|
|
7
|
+
add_flash_types :application_secret unless Doorkeeper.configuration.api_only
|
7
8
|
before_action :authenticate_admin!
|
8
9
|
before_action :set_application, only: %i[show edit update destroy]
|
9
10
|
|
@@ -19,7 +20,7 @@ module Doorkeeper
|
|
19
20
|
def show
|
20
21
|
respond_to do |format|
|
21
22
|
format.html
|
22
|
-
format.json { render json: @application
|
23
|
+
format.json { render json: @application }
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
@@ -32,10 +33,11 @@ module Doorkeeper
|
|
32
33
|
|
33
34
|
if @application.save
|
34
35
|
flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
|
36
|
+
flash[:application_secret] = @application.plaintext_secret
|
35
37
|
|
36
38
|
respond_to do |format|
|
37
39
|
format.html { redirect_to oauth_application_url(@application) }
|
38
|
-
format.json { render json: @application
|
40
|
+
format.json { render json: @application }
|
39
41
|
end
|
40
42
|
else
|
41
43
|
respond_to do |format|
|
@@ -57,7 +59,7 @@ module Doorkeeper
|
|
57
59
|
|
58
60
|
respond_to do |format|
|
59
61
|
format.html { redirect_to oauth_application_url(@application) }
|
60
|
-
format.json { render json: @application
|
62
|
+
format.json { render json: @application }
|
61
63
|
end
|
62
64
|
else
|
63
65
|
respond_to do |format|
|
@@ -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
|
@@ -6,8 +6,8 @@ module Doorkeeper
|
|
6
6
|
headers.merge!(authorize_response.headers)
|
7
7
|
render json: authorize_response.body,
|
8
8
|
status: authorize_response.status
|
9
|
-
rescue Errors::DoorkeeperError =>
|
10
|
-
handle_token_exception(
|
9
|
+
rescue Errors::DoorkeeperError => e
|
10
|
+
handle_token_exception(e)
|
11
11
|
end
|
12
12
|
|
13
13
|
# OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
|
@@ -18,12 +18,13 @@ module Doorkeeper
|
|
18
18
|
# Doorkeeper does not use the token_type_hint logic described in the
|
19
19
|
# RFC 7009 due to the refresh token implementation that is a field in
|
20
20
|
# the access token model.
|
21
|
-
revoke_token if authorized?
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
if authorized?
|
23
|
+
revoke_token
|
24
|
+
render json: {}, status: 200
|
25
|
+
else
|
26
|
+
render json: revocation_error_response, status: :forbidden
|
27
|
+
end
|
27
28
|
end
|
28
29
|
|
29
30
|
def introspect
|
@@ -71,7 +72,10 @@ module Doorkeeper
|
|
71
72
|
end
|
72
73
|
|
73
74
|
def revoke_token
|
74
|
-
|
75
|
+
# The authorization server responds with HTTP status code 200 if the token
|
76
|
+
# has been revoked successfully or if the client submitted an invalid
|
77
|
+
# token
|
78
|
+
token.revoke if token&.accessible?
|
75
79
|
end
|
76
80
|
|
77
81
|
def token
|
@@ -84,7 +88,26 @@ module Doorkeeper
|
|
84
88
|
end
|
85
89
|
|
86
90
|
def authorize_response
|
87
|
-
@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)
|
105
|
+
end
|
106
|
+
|
107
|
+
def revocation_error_response
|
108
|
+
error_description = I18n.t(:unauthorized, scope: %i[doorkeeper errors messages revoke])
|
109
|
+
|
110
|
+
{ error: :unauthorized_client, error_description: error_description }
|
88
111
|
end
|
89
112
|
end
|
90
113
|
end
|
@@ -20,12 +20,6 @@
|
|
20
20
|
<%= t('doorkeeper.applications.help.redirect_uri') %>
|
21
21
|
</span>
|
22
22
|
|
23
|
-
<% if Doorkeeper.configuration.native_redirect_uri %>
|
24
|
-
<span class="form-text text-secondary">
|
25
|
-
<%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, class: 'bg-light') { Doorkeeper.configuration.native_redirect_uri }) %>
|
26
|
-
</span>
|
27
|
-
<% end %>
|
28
|
-
|
29
23
|
<% if Doorkeeper.configuration.allow_blank_redirect_uri?(application) %>
|
30
24
|
<span class="form-text text-secondary">
|
31
25
|
<%= t('doorkeeper.applications.help.blank_redirect_uri') %>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<p><code class="bg-light" id="application_id"><%= @application.uid %></code></p>
|
9
9
|
|
10
10
|
<h4><%= t('.secret') %>:</h4>
|
11
|
-
<p><code class="bg-light" id="secret"><%= @application.plaintext_secret %></code></p>
|
11
|
+
<p><code class="bg-light" id="secret"><%= flash[:application_secret].presence || @application.plaintext_secret %></code></p>
|
12
12
|
|
13
13
|
<h4><%= t('.scopes') %>:</h4>
|
14
14
|
<p><code class="bg-light" id="scopes"><%= @application.scopes.presence || raw(' ') %></code></p>
|
data/config/locales/en.yml
CHANGED
@@ -11,6 +11,7 @@ en:
|
|
11
11
|
redirect_uri:
|
12
12
|
fragment_present: 'cannot contain a fragment.'
|
13
13
|
invalid_uri: 'must be a valid URI.'
|
14
|
+
unspecified_scheme: 'must specify a scheme.'
|
14
15
|
relative_uri: 'must be an absolute URI.'
|
15
16
|
secured_uri: 'must be an HTTPS/SSL URI.'
|
16
17
|
forbidden_uri: 'is forbidden by the server.'
|
@@ -33,7 +34,6 @@ en:
|
|
33
34
|
confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
|
34
35
|
redirect_uri: 'Use one line per URI'
|
35
36
|
blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
|
36
|
-
native_redirect_uri: 'Use %{native_redirect_uri} if you want to add localhost URIs for development purposes'
|
37
37
|
scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
|
38
38
|
edit:
|
39
39
|
title: 'Edit application'
|
@@ -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.'
|
@@ -114,6 +118,8 @@ en:
|
|
114
118
|
revoked: "The access token was revoked"
|
115
119
|
expired: "The access token expired"
|
116
120
|
unknown: "The access token is invalid"
|
121
|
+
revoke:
|
122
|
+
unauthorized: "You are not authorized to revoke this token"
|
117
123
|
|
118
124
|
flash:
|
119
125
|
applications:
|
data/doorkeeper.gemspec
CHANGED
@@ -14,10 +14,18 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.description = "Doorkeeper is an OAuth 2 provider for Rails and Grape."
|
15
15
|
gem.license = "MIT"
|
16
16
|
|
17
|
-
gem.files = `git ls-files`.split("\n")
|
17
|
+
gem.files = `git ls-files`.split("\n").reject { |file| file.start_with?(".") }
|
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_5_0.gemfile
CHANGED
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
9
|
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
10
10
|
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
11
11
|
gem "rubocop", "~> 0.66"
|
12
|
+
gem "rubocop-performance"
|
12
13
|
gem "bcrypt", "~> 3.1", require: false
|
13
14
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
14
15
|
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
data/gemfiles/rails_5_1.gemfile
CHANGED
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
9
|
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
10
10
|
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
11
11
|
gem "rubocop", "~> 0.66"
|
12
|
+
gem "rubocop-performance"
|
12
13
|
gem "bcrypt", "~> 3.1", require: false
|
13
14
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
14
15
|
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
data/gemfiles/rails_5_2.gemfile
CHANGED
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
9
|
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
10
10
|
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
11
11
|
gem "rubocop", "~> 0.66"
|
12
|
+
gem "rubocop-performance"
|
12
13
|
gem "bcrypt", "~> 3.1", require: false
|
13
14
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
14
15
|
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
data/gemfiles/rails_6_0.gemfile
CHANGED
@@ -2,13 +2,14 @@
|
|
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"
|
9
9
|
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
10
10
|
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
11
11
|
gem "rubocop", "~> 0.66"
|
12
|
+
gem "rubocop-performance"
|
12
13
|
gem "bcrypt", "~> 3.1", require: false
|
13
14
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
14
15
|
gem "sqlite3", "~> 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
@@ -9,6 +9,7 @@ gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
9
|
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
10
10
|
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
11
11
|
gem "rubocop", "~> 0.66"
|
12
|
+
gem "rubocop-performance"
|
12
13
|
gem "bcrypt", "~> 3.1", require: false
|
13
14
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
14
15
|
gem "sqlite3", "~> 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
@@ -38,14 +38,20 @@ module Doorkeeper
|
|
38
38
|
|
39
39
|
Builder.instance_eval do
|
40
40
|
remove_method name if method_defined?(name)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
if options[:deprecated]
|
42
|
+
define_method name do |*_, &_|
|
43
|
+
Kernel.warn "[DOORKEEPER] #{name} has been deprecated and will soon be removed"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
define_method name do |*args, &block|
|
47
|
+
value = if attribute_builder
|
48
|
+
attribute_builder.new(&block).build
|
49
|
+
else
|
50
|
+
block || args.first
|
51
|
+
end
|
47
52
|
|
48
|
-
|
53
|
+
@config.instance_variable_set(:"@#{attribute}", value)
|
54
|
+
end
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
data/lib/doorkeeper/config.rb
CHANGED
@@ -25,8 +25,8 @@ module Doorkeeper
|
|
25
25
|
|
26
26
|
def self.setup_orm_adapter
|
27
27
|
@orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
|
28
|
-
rescue NameError =>
|
29
|
-
raise
|
28
|
+
rescue NameError => e
|
29
|
+
raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
|
30
30
|
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
|
31
31
|
trying to load it.
|
32
32
|
|
@@ -254,11 +254,37 @@ module Doorkeeper
|
|
254
254
|
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
255
255
|
option :authorization_code_expires_in, default: 600
|
256
256
|
option :orm, default: :active_record
|
257
|
-
option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob"
|
257
|
+
option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
|
258
258
|
option :active_record_options, default: {}
|
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.
|
@@ -321,6 +356,36 @@ module Doorkeeper
|
|
321
356
|
grant_flows.exclude?("implicit")
|
322
357
|
end)
|
323
358
|
|
359
|
+
# Configure protection of token introspection request.
|
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)
|
364
|
+
#
|
365
|
+
# You can define any custom rule you need or just disable token
|
366
|
+
# introspection at all.
|
367
|
+
#
|
368
|
+
# @param token [Doorkeeper::AccessToken]
|
369
|
+
# token to be introspected
|
370
|
+
#
|
371
|
+
# @param authorized_client [Doorkeeper::Application]
|
372
|
+
# authorized client (if request is authorized using Basic auth with
|
373
|
+
# Client Credentials for example)
|
374
|
+
#
|
375
|
+
# @param authorized_token [Doorkeeper::AccessToken]
|
376
|
+
# Bearer token used to authorize the request
|
377
|
+
#
|
378
|
+
option :allow_token_introspection,
|
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
|
384
|
+
else
|
385
|
+
true
|
386
|
+
end
|
387
|
+
end)
|
388
|
+
|
324
389
|
attr_reader :api_only,
|
325
390
|
:enforce_content_type,
|
326
391
|
:reuse_access_token,
|
@@ -354,6 +419,17 @@ module Doorkeeper
|
|
354
419
|
@token_reuse_limit ||= 100
|
355
420
|
end
|
356
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
|
+
|
357
433
|
def enforce_configured_scopes?
|
358
434
|
option_set? :enforce_configured_scopes
|
359
435
|
end
|
@@ -422,6 +498,12 @@ module Doorkeeper
|
|
422
498
|
end
|
423
499
|
end
|
424
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
|
+
|
425
507
|
def option_defined?(name)
|
426
508
|
instance_variable_defined?("@#{name}")
|
427
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
|
@@ -4,6 +4,8 @@ require "doorkeeper/grape/authorization_decorator"
|
|
4
4
|
|
5
5
|
module Doorkeeper
|
6
6
|
module Grape
|
7
|
+
# Doorkeeper helpers for Grape applications.
|
8
|
+
# Provides helpers for endpoints authorization based on defined set of scopes.
|
7
9
|
module Helpers
|
8
10
|
# These helpers are for grape >= 0.10
|
9
11
|
extend ::Grape::API::Helpers
|
@@ -11,7 +13,9 @@ module Doorkeeper
|
|
11
13
|
|
12
14
|
# endpoint specific scopes > parameter scopes > default scopes
|
13
15
|
def doorkeeper_authorize!(*scopes)
|
14
|
-
endpoint_scopes = endpoint.route_setting(:scopes) ||
|
16
|
+
endpoint_scopes = endpoint.route_setting(:scopes) ||
|
17
|
+
endpoint.options[:route_options][:scopes]
|
18
|
+
|
15
19
|
scopes = if endpoint_scopes
|
16
20
|
Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
|
17
21
|
elsif scopes && !scopes.empty?
|