doorkeeper 3.1.0 → 4.4.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +6 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +26 -10
- data/Appraisals +18 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -5
- data/NEWS.md +141 -2
- data/README.md +149 -66
- data/RELEASING.md +5 -12
- data/Rakefile +1 -1
- data/SECURITY.md +15 -0
- data/app/controllers/doorkeeper/application_controller.rb +4 -6
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +18 -8
- data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
- data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
- data/app/validators/redirect_uri_validator.rb +12 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/applications/_form.html.erb +13 -2
- data/app/views/doorkeeper/applications/index.html.erb +2 -0
- data/app/views/doorkeeper/applications/show.html.erb +4 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
- data/config/locales/en.yml +12 -7
- data/doorkeeper.gemspec +16 -11
- data/gemfiles/rails_4_2.gemfile +13 -0
- data/gemfiles/rails_5_0.gemfile +12 -0
- data/gemfiles/rails_5_1.gemfile +12 -0
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +119 -46
- data/lib/doorkeeper/engine.rb +11 -7
- data/lib/doorkeeper/errors.rb +18 -0
- data/lib/doorkeeper/grape/helpers.rb +14 -8
- data/lib/doorkeeper/helpers/controller.rb +8 -19
- data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
- data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
- data/lib/doorkeeper/models/application_mixin.rb +33 -35
- data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
- data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
- data/lib/doorkeeper/oauth/base_response.rb +29 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
- data/lib/doorkeeper/oauth/client.rb +2 -3
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
- data/lib/doorkeeper/oauth/code_response.rb +16 -16
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +10 -10
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
- data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
- data/lib/doorkeeper/oauth/scopes.rb +18 -8
- data/lib/doorkeeper/oauth/token.rb +20 -21
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_request.rb +1 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
- data/lib/doorkeeper/orm/active_record/application.rb +48 -11
- data/lib/doorkeeper/orm/active_record.rb +17 -22
- data/lib/doorkeeper/rails/helpers.rb +6 -9
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
- data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +17 -11
- data/lib/doorkeeper/request/authorization_code.rb +7 -1
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request.rb +7 -1
- data/lib/doorkeeper/server.rb +0 -8
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +34 -1
- data/lib/doorkeeper.rb +10 -2
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -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 +35 -0
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
- data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
- data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
- data/spec/controllers/application_metal_controller.rb +10 -0
- data/spec/controllers/applications_controller_spec.rb +15 -4
- data/spec/controllers/authorizations_controller_spec.rb +74 -27
- data/spec/controllers/protected_resources_controller_spec.rb +70 -32
- data/spec/controllers/token_info_controller_spec.rb +17 -13
- data/spec/controllers/tokens_controller_spec.rb +198 -12
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
- data/spec/dummy/app/controllers/home_controller.rb +1 -1
- data/spec/dummy/app/controllers/metal_controller.rb +1 -1
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
- data/spec/dummy/app/models/user.rb +0 -4
- data/spec/dummy/config/application.rb +2 -36
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +4 -15
- data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
- data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
- data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
- data/spec/dummy/db/schema.rb +24 -22
- data/spec/factories.rb +4 -2
- 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 +159 -14
- data/spec/lib/doorkeeper_spec.rb +135 -13
- data/spec/lib/models/expirable_spec.rb +0 -1
- data/spec/lib/models/revocable_spec.rb +27 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
- data/spec/lib/oauth/base_request_spec.rb +155 -0
- data/spec/lib/oauth/base_response_spec.rb +45 -0
- data/spec/lib/oauth/client/credentials_spec.rb +45 -2
- 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/code_response_spec.rb +34 -0
- data/spec/lib/oauth/error_response_spec.rb +9 -9
- data/spec/lib/oauth/error_spec.rb +1 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
- data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
- data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
- data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
- data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
- data/spec/lib/oauth/scopes_spec.rb +28 -2
- data/spec/lib/oauth/token_request_spec.rb +6 -8
- data/spec/lib/oauth/token_spec.rb +12 -5
- data/spec/lib/server_spec.rb +10 -3
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +116 -48
- data/spec/models/doorkeeper/application_spec.rb +145 -29
- data/spec/requests/applications/applications_request_spec.rb +5 -5
- data/spec/requests/endpoints/authorization_spec.rb +5 -6
- 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 +6 -13
- data/spec/requests/flows/client_credentials_spec.rb +29 -1
- data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
- data/spec/requests/flows/password_spec.rb +118 -15
- data/spec/requests/flows/refresh_token_spec.rb +89 -19
- data/spec/requests/flows/revoke_token_spec.rb +105 -91
- 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.rb +2 -0
- data/spec/spec_helper_integration.rb +22 -4
- 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 +34 -7
- data/spec/support/helpers/request_spec_helper.rb +17 -5
- data/spec/support/helpers/url_helper.rb +9 -8
- data/spec/support/http_method_shim.rb +38 -0
- data/spec/support/shared/controllers_shared_context.rb +15 -10
- data/spec/support/shared/models_shared_examples.rb +5 -5
- data/spec/validators/redirect_uri_validator_spec.rb +51 -6
- data/spec/version/version_spec.rb +15 -0
- metadata +128 -46
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -1,15 +1,19 @@
|
|
1
|
-
module Doorkeeper
|
2
|
-
|
3
|
-
|
4
|
-
object.errors[method].
|
5
|
-
|
6
|
-
|
1
|
+
module Doorkeeper
|
2
|
+
module DashboardHelper
|
3
|
+
def doorkeeper_errors_for(object, method)
|
4
|
+
if object.errors[method].present?
|
5
|
+
output = object.errors[method].map do |msg|
|
6
|
+
content_tag(:span, class: 'help-block') do
|
7
|
+
msg.capitalize
|
8
|
+
end
|
7
9
|
end
|
8
|
-
|
10
|
+
|
11
|
+
safe_join(output)
|
12
|
+
end
|
9
13
|
end
|
10
|
-
end
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
def doorkeeper_submit_path(application)
|
16
|
+
application.persisted? ? oauth_application_path(application) : oauth_applications_path
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
@@ -11,7 +11,8 @@ class RedirectUriValidator < ActiveModel::EachValidator
|
|
11
11
|
else
|
12
12
|
value.split.each do |val|
|
13
13
|
uri = ::URI.parse(val)
|
14
|
-
|
14
|
+
next if native_redirect_uri?(uri)
|
15
|
+
record.errors.add(attribute, :forbidden_uri) if forbidden_uri?(uri)
|
15
16
|
record.errors.add(attribute, :fragment_present) unless uri.fragment.nil?
|
16
17
|
record.errors.add(attribute, :relative_uri) if uri.scheme.nil? || uri.host.nil?
|
17
18
|
record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
|
@@ -27,8 +28,17 @@ class RedirectUriValidator < ActiveModel::EachValidator
|
|
27
28
|
self.class.native_redirect_uri.present? && uri.to_s == self.class.native_redirect_uri.to_s
|
28
29
|
end
|
29
30
|
|
31
|
+
def forbidden_uri?(uri)
|
32
|
+
Doorkeeper.configuration.forbid_redirect_uri.call(uri)
|
33
|
+
end
|
34
|
+
|
30
35
|
def invalid_ssl_uri?(uri)
|
31
36
|
forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
|
32
|
-
|
37
|
+
|
38
|
+
if forces_ssl.respond_to?(:call)
|
39
|
+
forces_ssl.call(uri)
|
40
|
+
else
|
41
|
+
forces_ssl && uri.try(:scheme) == 'http'
|
42
|
+
end
|
33
43
|
end
|
34
44
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
<%- submit_btn_css ||= 'btn btn-link' %>
|
2
|
-
<%= form_tag oauth_application_path(application) do %>
|
3
|
-
<input type="hidden" name="_method" value="delete">
|
2
|
+
<%= form_tag oauth_application_path(application), method: :delete do %>
|
4
3
|
<%= submit_tag t('doorkeeper.applications.buttons.destroy'), onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')", class: submit_btn_css %>
|
5
4
|
<% end %>
|
@@ -21,12 +21,23 @@
|
|
21
21
|
</span>
|
22
22
|
<% if Doorkeeper.configuration.native_redirect_uri %>
|
23
23
|
<span class="help-block">
|
24
|
-
<%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri:
|
24
|
+
<%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code) { Doorkeeper.configuration.native_redirect_uri }) %>
|
25
25
|
</span>
|
26
26
|
<% end %>
|
27
27
|
</div>
|
28
28
|
<% end %>
|
29
29
|
|
30
|
+
<%= content_tag :div, class: "form-group#{' has-error' if application.errors[:confidential].present?}" do %>
|
31
|
+
<%= f.label :confidential, class: 'col-sm-2 control-label' %>
|
32
|
+
<div class="col-sm-10">
|
33
|
+
<%= f.check_box :confidential, class: 'form-control', disabled: !Doorkeeper::Application.supports_confidentiality? %>
|
34
|
+
<%= doorkeeper_errors_for application, :confidential %>
|
35
|
+
<span class="help-block">
|
36
|
+
<%= t('doorkeeper.applications.help.confidential') %>
|
37
|
+
</span>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
40
|
+
|
30
41
|
<%= content_tag :div, class: "form-group#{' has-error' if application.errors[:scopes].present?}" do %>
|
31
42
|
<%= f.label :scopes, class: 'col-sm-2 control-label' %>
|
32
43
|
<div class="col-sm-10">
|
@@ -41,7 +52,7 @@
|
|
41
52
|
<div class="form-group">
|
42
53
|
<div class="col-sm-offset-2 col-sm-10">
|
43
54
|
<%= f.submit t('doorkeeper.applications.buttons.submit'), class: "btn btn-primary" %>
|
44
|
-
<%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, :
|
55
|
+
<%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, class: "btn btn-default" %>
|
45
56
|
</div>
|
46
57
|
</div>
|
47
58
|
<% end %>
|
@@ -9,6 +9,7 @@
|
|
9
9
|
<tr>
|
10
10
|
<th><%= t('.name') %></th>
|
11
11
|
<th><%= t('.callback_url') %></th>
|
12
|
+
<th><%= t('.confidential') %></th>
|
12
13
|
<th></th>
|
13
14
|
<th></th>
|
14
15
|
</tr>
|
@@ -18,6 +19,7 @@
|
|
18
19
|
<tr id="application_<%= application.id %>">
|
19
20
|
<td><%= link_to application.name, oauth_application_path(application) %></td>
|
20
21
|
<td><%= application.redirect_uri %></td>
|
22
|
+
<td><%= application.confidential? ? t('doorkeeper.applications.index.confidentiality.yes') : t('doorkeeper.applications.index.confidentiality.no') %></td>
|
21
23
|
<td><%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td>
|
22
24
|
<td><%= render 'delete_form', application: application %></td>
|
23
25
|
</tr>
|
@@ -13,6 +13,9 @@
|
|
13
13
|
<h4><%= t('.scopes') %>:</h4>
|
14
14
|
<p><code id="scopes"><%= @application.scopes %></code></p>
|
15
15
|
|
16
|
+
<h4><%= t('.confidential') %>:</h4>
|
17
|
+
<p><code id="confidential"><%= @application.confidential? %></code></p>
|
18
|
+
|
16
19
|
<h4><%= t('.callback_urls') %>:</h4>
|
17
20
|
|
18
21
|
<table>
|
@@ -22,7 +25,7 @@
|
|
22
25
|
<code><%= uri %></code>
|
23
26
|
</td>
|
24
27
|
<td>
|
25
|
-
<%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code'), class: 'btn btn-success', target: '_blank' %>
|
28
|
+
<%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code', scope: @application.scopes), class: 'btn btn-success', target: '_blank' %>
|
26
29
|
</td>
|
27
30
|
</tr>
|
28
31
|
<% end %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
<main role="main">
|
6
6
|
<p class="h4">
|
7
|
-
<%= raw t('.prompt', client_name:
|
7
|
+
<%= raw t('.prompt', client_name: content_tag(:strong, class: 'text-info') { @pre_auth.client.name }) %>
|
8
8
|
</p>
|
9
9
|
|
10
10
|
<% if @pre_auth.scopes.count > 0 %>
|
@@ -1,5 +1,4 @@
|
|
1
1
|
<%- submit_btn_css ||= 'btn btn-link' %>
|
2
|
-
<%= form_tag oauth_authorized_application_path(application) do %>
|
3
|
-
<input type="hidden" name="_method" value="delete">
|
2
|
+
<%= form_tag oauth_authorized_application_path(application), method: :delete do %>
|
4
3
|
<%= submit_tag t('doorkeeper.authorized_applications.buttons.revoke'), onclick: "return confirm('#{ t('doorkeeper.authorized_applications.confirmations.revoke') }')", class: submit_btn_css %>
|
5
4
|
<% end %>
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path %>
|
20
20
|
<% end %>
|
21
21
|
<%= content_tag :li do %>
|
22
|
-
<%= link_to '
|
22
|
+
<%= link_to t('doorkeeper.layouts.admin.nav.home'), root_path %>
|
23
23
|
<% end %>
|
24
24
|
</ul>
|
25
25
|
</div>
|
data/config/locales/en.yml
CHANGED
@@ -13,6 +13,7 @@ en:
|
|
13
13
|
invalid_uri: 'must be a valid URI.'
|
14
14
|
relative_uri: 'must be an absolute URI.'
|
15
15
|
secured_uri: 'must be an HTTPS/SSL URI.'
|
16
|
+
forbidden_uri: 'is forbidden by the server.'
|
16
17
|
|
17
18
|
doorkeeper:
|
18
19
|
applications:
|
@@ -27,8 +28,9 @@ en:
|
|
27
28
|
form:
|
28
29
|
error: 'Whoops! Check your form for possible errors'
|
29
30
|
help:
|
31
|
+
confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
|
30
32
|
redirect_uri: 'Use one line per URI'
|
31
|
-
native_redirect_uri: 'Use %{native_redirect_uri} for
|
33
|
+
native_redirect_uri: 'Use %{native_redirect_uri} if you want to add localhost URIs for development purposes'
|
32
34
|
scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
|
33
35
|
edit:
|
34
36
|
title: 'Edit application'
|
@@ -37,6 +39,10 @@ en:
|
|
37
39
|
new: 'New Application'
|
38
40
|
name: 'Name'
|
39
41
|
callback_url: 'Callback URL'
|
42
|
+
confidential: 'Confidential?'
|
43
|
+
confidentiality:
|
44
|
+
'yes': 'Yes'
|
45
|
+
'no': 'No'
|
40
46
|
new:
|
41
47
|
title: 'New Application'
|
42
48
|
show:
|
@@ -44,6 +50,7 @@ en:
|
|
44
50
|
application_id: 'Application Id'
|
45
51
|
secret: 'Secret'
|
46
52
|
scopes: 'Scopes'
|
53
|
+
confidential: 'Confidential'
|
47
54
|
callback_urls: 'Callback urls'
|
48
55
|
actions: 'Actions'
|
49
56
|
|
@@ -75,16 +82,16 @@ en:
|
|
75
82
|
messages:
|
76
83
|
# Common error messages
|
77
84
|
invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
|
78
|
-
invalid_redirect_uri:
|
85
|
+
invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
|
79
86
|
unauthorized_client: 'The client is not authorized to perform this request using this method.'
|
80
87
|
access_denied: 'The resource owner or authorization server denied the request.'
|
81
88
|
invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
|
82
89
|
server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
|
83
90
|
temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
|
84
91
|
|
85
|
-
#
|
92
|
+
# Configuration error messages
|
86
93
|
credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
|
87
|
-
resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being
|
94
|
+
resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfigured.'
|
88
95
|
|
89
96
|
# Access grant errors
|
90
97
|
unsupported_response_type: 'The authorization server does not support this response type.'
|
@@ -94,9 +101,6 @@ en:
|
|
94
101
|
invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
|
95
102
|
unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
|
96
103
|
|
97
|
-
# Password Access token errors
|
98
|
-
invalid_resource_owner: 'The provided resource owner credentials are not valid, or resource owner cannot be found'
|
99
|
-
|
100
104
|
invalid_token:
|
101
105
|
revoked: "The access token was revoked"
|
102
106
|
expired: "The access token expired"
|
@@ -119,5 +123,6 @@ en:
|
|
119
123
|
nav:
|
120
124
|
oauth2_provider: 'OAuth2 Provider'
|
121
125
|
applications: 'Applications'
|
126
|
+
home: 'Home'
|
122
127
|
application:
|
123
128
|
title: 'OAuth authorization required'
|
data/doorkeeper.gemspec
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
2
2
|
|
3
3
|
require "doorkeeper/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "doorkeeper"
|
7
|
-
s.version = Doorkeeper
|
8
|
-
s.authors = ["Felipe Elias Philipp", "Tute Costa"]
|
9
|
-
s.email = %w(
|
7
|
+
s.version = Doorkeeper.gem_version
|
8
|
+
s.authors = ["Felipe Elias Philipp", "Tute Costa", "Jon Moss", "Nikita Bulai"]
|
9
|
+
s.email = %w(bulaj.nikita@gmail.com)
|
10
10
|
s.homepage = "https://github.com/doorkeeper-gem/doorkeeper"
|
11
11
|
s.summary = "OAuth 2 provider for Rails and Grape"
|
12
12
|
s.description = "Doorkeeper is an OAuth 2 provider for Rails and Grape."
|
@@ -16,12 +16,17 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_dependency "railties", ">=
|
19
|
+
s.add_dependency "railties", ">= 4.2"
|
20
|
+
s.required_ruby_version = ">= 2.1"
|
20
21
|
|
21
|
-
s.add_development_dependency "
|
22
|
-
s.add_development_dependency "
|
23
|
-
s.add_development_dependency "
|
24
|
-
s.add_development_dependency "
|
25
|
-
s.add_development_dependency "
|
26
|
-
s.add_development_dependency "
|
22
|
+
s.add_development_dependency "capybara"
|
23
|
+
s.add_development_dependency "coveralls"
|
24
|
+
s.add_development_dependency "grape"
|
25
|
+
s.add_development_dependency "database_cleaner", "~> 1.6"
|
26
|
+
s.add_development_dependency "factory_bot", "~> 4.8"
|
27
|
+
s.add_development_dependency "generator_spec", "~> 0.9.3"
|
28
|
+
s.add_development_dependency "rake", ">= 11.3.0"
|
29
|
+
s.add_development_dependency "rspec-rails"
|
30
|
+
|
31
|
+
s.post_install_message = Doorkeeper::CVE_2018_1000211_WARNING
|
27
32
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 4.2.0"
|
6
|
+
gem "appraisal"
|
7
|
+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
8
|
+
gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
9
|
+
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
10
|
+
# Older Grape requires Ruby >= 2.2.2
|
11
|
+
gem "grape", '~> 0.16', '< 0.19.2'
|
12
|
+
|
13
|
+
gemspec path: "../"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 5.0.0"
|
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.5"
|
11
|
+
|
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.1.0"
|
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,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
@@ -1,5 +1,7 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
class MissingConfiguration < StandardError
|
3
|
+
# Defines a MissingConfiguration error for a missing Doorkeeper
|
4
|
+
# configuration
|
3
5
|
def initialize
|
4
6
|
super('Configuration for doorkeeper missing. Do you have doorkeeper initializer?')
|
5
7
|
end
|
@@ -10,15 +12,10 @@ module Doorkeeper
|
|
10
12
|
setup_orm_adapter
|
11
13
|
setup_orm_models
|
12
14
|
setup_application_owner if @config.enable_application_owner?
|
13
|
-
check_requirements
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.configuration
|
17
|
-
@config || (fail MissingConfiguration
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.check_requirements
|
21
|
-
@orm_adapter.check_requirements!(configuration)
|
18
|
+
@config || (fail MissingConfiguration)
|
22
19
|
end
|
23
20
|
|
24
21
|
def self.setup_orm_adapter
|
@@ -52,51 +49,79 @@ doorkeeper.
|
|
52
49
|
@config
|
53
50
|
end
|
54
51
|
|
52
|
+
# Provide support for an owner to be assigned to each registered
|
53
|
+
# application (disabled by default)
|
54
|
+
# Optional parameter confirmation: true (default false) if you want
|
55
|
+
# to enforce ownership of a registered application
|
56
|
+
#
|
57
|
+
# @param opts [Hash] the options to confirm if an application owner
|
58
|
+
# is present
|
59
|
+
# @option opts[Boolean] :confirmation (false)
|
60
|
+
# Set confirm_application_owner variable
|
55
61
|
def enable_application_owner(opts = {})
|
56
|
-
@config.instance_variable_set(
|
62
|
+
@config.instance_variable_set(:@enable_application_owner, true)
|
57
63
|
confirm_application_owner if opts[:confirmation].present? && opts[:confirmation]
|
58
64
|
end
|
59
65
|
|
60
66
|
def confirm_application_owner
|
61
|
-
@config.instance_variable_set(
|
67
|
+
@config.instance_variable_set(:@confirm_application_owner, true)
|
62
68
|
end
|
63
69
|
|
70
|
+
# Define default access token scopes for your provider
|
71
|
+
#
|
72
|
+
# @param scopes [Array] Default set of access (OAuth::Scopes.new)
|
73
|
+
# token scopes
|
64
74
|
def default_scopes(*scopes)
|
65
|
-
@config.instance_variable_set(
|
75
|
+
@config.instance_variable_set(:@default_scopes, OAuth::Scopes.from_array(scopes))
|
66
76
|
end
|
67
77
|
|
78
|
+
# Define default access token scopes for your provider
|
79
|
+
#
|
80
|
+
# @param scopes [Array] Optional set of access (OAuth::Scopes.new)
|
81
|
+
# token scopes
|
68
82
|
def optional_scopes(*scopes)
|
69
|
-
@config.instance_variable_set(
|
83
|
+
@config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
|
70
84
|
end
|
71
85
|
|
86
|
+
# Change the way client credentials are retrieved from the request object.
|
87
|
+
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
88
|
+
# falls back to the `:client_id` and `:client_secret` params from the
|
89
|
+
# `params` object.
|
90
|
+
#
|
91
|
+
# @param methods [Array] Define client credentials
|
72
92
|
def client_credentials(*methods)
|
73
|
-
@config.instance_variable_set(
|
93
|
+
@config.instance_variable_set(:@client_credentials, methods)
|
74
94
|
end
|
75
95
|
|
96
|
+
# Change the way access token is authenticated from the request object.
|
97
|
+
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
98
|
+
# falls back to the `:access_token` or `:bearer_token` params from the
|
99
|
+
# `params` object.
|
100
|
+
#
|
101
|
+
# @param methods [Array] Define access token methods
|
76
102
|
def access_token_methods(*methods)
|
77
|
-
@config.instance_variable_set(
|
103
|
+
@config.instance_variable_set(:@access_token_methods, methods)
|
78
104
|
end
|
79
105
|
|
106
|
+
# Issue access tokens with refresh token (disabled by default)
|
80
107
|
def use_refresh_token
|
81
|
-
@config.instance_variable_set(
|
82
|
-
end
|
83
|
-
|
84
|
-
def realm(realm)
|
85
|
-
@config.instance_variable_set('@realm', realm)
|
108
|
+
@config.instance_variable_set(:@refresh_token_enabled, true)
|
86
109
|
end
|
87
110
|
|
111
|
+
# Reuse access token for the same resource owner within an application
|
112
|
+
# (disabled by default)
|
113
|
+
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
88
114
|
def reuse_access_token
|
89
|
-
@config.instance_variable_set(
|
90
|
-
end
|
91
|
-
|
92
|
-
def force_ssl_in_redirect_uri(boolean)
|
93
|
-
@config.instance_variable_set("@force_ssl_in_redirect_uri", boolean)
|
115
|
+
@config.instance_variable_set(:@reuse_access_token, true)
|
94
116
|
end
|
95
117
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
118
|
+
# Opt out of breaking api change to the native authorization code flow.
|
119
|
+
# Opting out sets the authorization code response route for native
|
120
|
+
# redirect uris to oauth/authorize/<code>. The default is
|
121
|
+
# oauth/authorize/native?code=<code>.
|
122
|
+
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1143
|
123
|
+
def opt_out_native_route_change
|
124
|
+
@config.instance_variable_set(:@opt_out_native_route_change, true)
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
@@ -133,19 +158,20 @@ doorkeeper.
|
|
133
158
|
attribute_builder = options[:builder_class]
|
134
159
|
|
135
160
|
Builder.instance_eval do
|
161
|
+
remove_method name if method_defined?(name)
|
136
162
|
define_method name do |*args, &block|
|
137
163
|
# TODO: is builder_class option being used?
|
138
|
-
value =
|
139
|
-
block ? block : args.first
|
140
|
-
else
|
164
|
+
value = if attribute_builder
|
141
165
|
attribute_builder.new(&block).build
|
166
|
+
else
|
167
|
+
block ? block : args.first
|
142
168
|
end
|
143
169
|
|
144
170
|
@config.instance_variable_set(:"@#{attribute}", value)
|
145
171
|
end
|
146
172
|
end
|
147
173
|
|
148
|
-
define_method attribute do |*
|
174
|
+
define_method attribute do |*_args|
|
149
175
|
if instance_variable_defined?(:"@#{attribute}")
|
150
176
|
instance_variable_get(:"@#{attribute}")
|
151
177
|
else
|
@@ -155,10 +181,6 @@ doorkeeper.
|
|
155
181
|
|
156
182
|
public attribute
|
157
183
|
end
|
158
|
-
|
159
|
-
def extended(base)
|
160
|
-
base.send(:private, :option)
|
161
|
-
end
|
162
184
|
end
|
163
185
|
|
164
186
|
extend Option
|
@@ -166,41 +188,91 @@ doorkeeper.
|
|
166
188
|
option :resource_owner_authenticator,
|
167
189
|
as: :authenticate_resource_owner,
|
168
190
|
default: (lambda do |_routes|
|
169
|
-
logger.warn(I18n.
|
191
|
+
::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
|
170
192
|
nil
|
171
193
|
end)
|
194
|
+
|
172
195
|
option :admin_authenticator,
|
173
196
|
as: :authenticate_admin,
|
174
197
|
default: ->(_routes) {}
|
198
|
+
|
175
199
|
option :resource_owner_from_credentials,
|
176
200
|
default: (lambda do |_routes|
|
177
|
-
warn(I18n.
|
201
|
+
::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.credential_flow_not_configured'))
|
178
202
|
nil
|
179
203
|
end)
|
180
|
-
|
204
|
+
option :before_successful_strategy_response, default: ->(_request) {}
|
205
|
+
option :after_successful_strategy_response,
|
206
|
+
default: ->(_request, _response) {}
|
181
207
|
option :skip_authorization, default: ->(_routes) {}
|
182
208
|
option :access_token_expires_in, default: 7200
|
183
|
-
option :custom_access_token_expires_in, default:
|
209
|
+
option :custom_access_token_expires_in, default: ->(_app) { nil }
|
184
210
|
option :authorization_code_expires_in, default: 600
|
185
211
|
option :orm, default: :active_record
|
186
212
|
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
|
187
213
|
option :active_record_options, default: {}
|
214
|
+
option :grant_flows, default: %w[authorization_code client_credentials]
|
215
|
+
|
216
|
+
# Allows to forbid specific Application redirect URI's by custom rules.
|
217
|
+
# Doesn't forbid any URI by default.
|
218
|
+
#
|
219
|
+
# @param forbid_redirect_uri [Proc] Block or any object respond to #call
|
220
|
+
#
|
221
|
+
option :forbid_redirect_uri, default: ->(_uri) { false }
|
222
|
+
|
223
|
+
# WWW-Authenticate Realm (default "Doorkeeper").
|
224
|
+
#
|
225
|
+
# @param realm [String] ("Doorkeeper") Authentication realm
|
226
|
+
#
|
188
227
|
option :realm, default: 'Doorkeeper'
|
228
|
+
|
229
|
+
# Forces the usage of the HTTPS protocol in non-native redirect uris
|
230
|
+
# (enabled by default in non-development environments). OAuth2
|
231
|
+
# delegates security in communication to the HTTPS protocol so it is
|
232
|
+
# wise to keep this enabled.
|
233
|
+
#
|
234
|
+
# @param [Boolean] boolean_or_block value for the parameter, true by default in
|
235
|
+
# non-development environment
|
236
|
+
#
|
237
|
+
# @yield [uri] Conditional usage of SSL redirect uris.
|
238
|
+
# @yieldparam [URI] Redirect URI
|
239
|
+
# @yieldreturn [Boolean] Indicates necessity of usage of the HTTPS protocol
|
240
|
+
# in non-native redirect uris
|
241
|
+
#
|
189
242
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
190
|
-
|
191
|
-
|
243
|
+
|
244
|
+
|
245
|
+
# Use a custom class for generating the access token.
|
246
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
247
|
+
#
|
248
|
+
# @param access_token_generator [String]
|
249
|
+
# the name of the access token generator class
|
250
|
+
#
|
251
|
+
option :access_token_generator,
|
252
|
+
default: 'Doorkeeper::OAuth::Helpers::UniqueToken'
|
253
|
+
|
254
|
+
# The controller Doorkeeper::ApplicationController inherits from.
|
255
|
+
# Defaults to ActionController::Base.
|
256
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
257
|
+
#
|
258
|
+
# @param base_controller [String] the name of the base controller
|
259
|
+
option :base_controller,
|
260
|
+
default: 'ActionController::Base'
|
192
261
|
|
193
262
|
attr_reader :reuse_access_token
|
194
263
|
|
195
264
|
def refresh_token_enabled?
|
265
|
+
@refresh_token_enabled ||= false
|
196
266
|
!!@refresh_token_enabled
|
197
267
|
end
|
198
268
|
|
199
269
|
def enable_application_owner?
|
270
|
+
@enable_application_owner ||= false
|
200
271
|
!!@enable_application_owner
|
201
272
|
end
|
202
273
|
|
203
274
|
def confirm_application_owner?
|
275
|
+
@confirm_application_owner ||= false
|
204
276
|
!!@confirm_application_owner
|
205
277
|
end
|
206
278
|
|
@@ -217,15 +289,11 @@ doorkeeper.
|
|
217
289
|
end
|
218
290
|
|
219
291
|
def client_credentials_methods
|
220
|
-
@client_credentials ||= [
|
292
|
+
@client_credentials ||= %i[from_basic from_params]
|
221
293
|
end
|
222
294
|
|
223
295
|
def access_token_methods
|
224
|
-
@access_token_methods ||= [
|
225
|
-
end
|
226
|
-
|
227
|
-
def realm
|
228
|
-
@realm ||= 'Doorkeeper'
|
296
|
+
@access_token_methods ||= %i[from_bearer_authorization from_access_token_param from_bearer_param]
|
229
297
|
end
|
230
298
|
|
231
299
|
def authorization_response_types
|
@@ -236,6 +304,11 @@ doorkeeper.
|
|
236
304
|
@token_grant_types ||= calculate_token_grant_types
|
237
305
|
end
|
238
306
|
|
307
|
+
def native_authorization_code_route
|
308
|
+
@opt_out_native_route_change ||= false
|
309
|
+
@opt_out_native_route_change ? '/:code' : '/native'
|
310
|
+
end
|
311
|
+
|
239
312
|
private
|
240
313
|
|
241
314
|
# Determines what values are acceptable for 'response_type' param in
|