doorkeeper 4.4.1 → 5.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -0
- data/Appraisals +2 -2
- data/Gemfile +1 -1
- data/NEWS.md +36 -9
- data/README.md +85 -3
- data/Rakefile +6 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +4 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +42 -22
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +12 -15
- data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
- data/app/validators/redirect_uri_validator.rb +3 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +25 -24
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +17 -7
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +6 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +9 -1
- data/doorkeeper.gemspec +0 -2
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/lib/doorkeeper/config.rb +60 -23
- data/lib/doorkeeper/engine.rb +4 -0
- data/lib/doorkeeper/errors.rb +2 -5
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +7 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +56 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +38 -21
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +23 -6
- data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
- data/lib/doorkeeper/oauth/base_request.rb +18 -8
- data/lib/doorkeeper/oauth/client/credentials.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
- data/lib/doorkeeper/oauth/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/token.rb +5 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +13 -16
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +2 -0
- data/lib/doorkeeper/rails/helpers.rb +2 -4
- data/lib/doorkeeper/rails/routes.rb +13 -1
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request.rb +28 -28
- data/lib/doorkeeper/version.rb +5 -25
- data/lib/doorkeeper.rb +4 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +60 -9
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +126 -13
- data/spec/controllers/authorizations_controller_spec.rb +252 -17
- data/spec/controllers/protected_resources_controller_spec.rb +16 -16
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +19 -73
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +6 -0
- data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
- data/spec/dummy/db/schema.rb +36 -36
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +1 -1
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +59 -14
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +24 -2
- data/spec/lib/oauth/base_request_spec.rb +16 -2
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +1 -3
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +4 -2
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -2
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +4 -5
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +1 -1
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +50 -16
- data/spec/models/doorkeeper/application_spec.rb +1 -30
- data/spec/requests/applications/applications_request_spec.rb +89 -1
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_spec.rb +198 -2
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +56 -2
- data/spec/requests/flows/refresh_token_spec.rb +2 -2
- data/spec/requests/flows/revoke_token_spec.rb +11 -11
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- 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 +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/request_spec_helper.rb +2 -2
- data/spec/support/helpers/url_helper.rb +7 -3
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/validators/redirect_uri_validator_spec.rb +7 -1
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +33 -31
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
- data/spec/controllers/application_metal_controller.rb +0 -10
- /data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
|
@@ -1,58 +1,59 @@
|
|
|
1
|
-
<%= form_for application, url: doorkeeper_submit_path(application), html: {
|
|
1
|
+
<%= form_for application, url: doorkeeper_submit_path(application), html: { role: 'form' } do |f| %>
|
|
2
2
|
<% if application.errors.any? %>
|
|
3
3
|
<div class="alert alert-danger" data-alert><p><%= t('doorkeeper.applications.form.error') %></p></div>
|
|
4
4
|
<% end %>
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
<%= f.label :name, class: 'col-sm-2
|
|
6
|
+
<div class="form-group row">
|
|
7
|
+
<%= f.label :name, class: 'col-sm-2 col-form-label font-weight-bold' %>
|
|
8
8
|
<div class="col-sm-10">
|
|
9
|
-
<%= f.text_field :name, class:
|
|
9
|
+
<%= f.text_field :name, class: "form-control #{ 'is-invalid' if application.errors[:name].present? }", required: true %>
|
|
10
10
|
<%= doorkeeper_errors_for application, :name %>
|
|
11
11
|
</div>
|
|
12
|
-
|
|
12
|
+
</div>
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
<%= f.label :redirect_uri, class: 'col-sm-2
|
|
14
|
+
<div class="form-group row">
|
|
15
|
+
<%= f.label :redirect_uri, class: 'col-sm-2 col-form-label font-weight-bold' %>
|
|
16
16
|
<div class="col-sm-10">
|
|
17
|
-
<%= f.text_area :redirect_uri, class:
|
|
17
|
+
<%= f.text_area :redirect_uri, class: "form-control #{ 'is-invalid' if application.errors[:redirect_uri].present? }" %>
|
|
18
18
|
<%= doorkeeper_errors_for application, :redirect_uri %>
|
|
19
|
-
<span class="
|
|
19
|
+
<span class="form-text text-secondary">
|
|
20
20
|
<%= t('doorkeeper.applications.help.redirect_uri') %>
|
|
21
21
|
</span>
|
|
22
|
+
|
|
22
23
|
<% if Doorkeeper.configuration.native_redirect_uri %>
|
|
23
|
-
<span class="
|
|
24
|
-
<%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code) { 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 }) %>
|
|
25
26
|
</span>
|
|
26
27
|
<% end %>
|
|
27
28
|
</div>
|
|
28
|
-
|
|
29
|
+
</div>
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
<%= f.label :confidential, class: 'col-sm-2
|
|
31
|
+
<div class="form-group row">
|
|
32
|
+
<%= f.label :confidential, class: 'col-sm-2 form-check-label font-weight-bold' %>
|
|
32
33
|
<div class="col-sm-10">
|
|
33
|
-
<%= f.check_box :confidential, class: '
|
|
34
|
+
<%= f.check_box :confidential, class: "checkbox #{ 'is-invalid' if application.errors[:confidential].present? }" %>
|
|
34
35
|
<%= doorkeeper_errors_for application, :confidential %>
|
|
35
|
-
<span class="
|
|
36
|
+
<span class="form-text text-secondary">
|
|
36
37
|
<%= t('doorkeeper.applications.help.confidential') %>
|
|
37
38
|
</span>
|
|
38
39
|
</div>
|
|
39
|
-
|
|
40
|
+
</div>
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
<%= f.label :scopes, class: 'col-sm-2
|
|
42
|
+
<div class="form-group row">
|
|
43
|
+
<%= f.label :scopes, class: 'col-sm-2 col-form-label font-weight-bold' %>
|
|
43
44
|
<div class="col-sm-10">
|
|
44
|
-
<%= f.text_field :scopes, class:
|
|
45
|
+
<%= f.text_field :scopes, class: "form-control #{ 'has-error' if application.errors[:scopes].present? }" %>
|
|
45
46
|
<%= doorkeeper_errors_for application, :scopes %>
|
|
46
|
-
<span class="
|
|
47
|
+
<span class="form-text text-secondary">
|
|
47
48
|
<%= t('doorkeeper.applications.help.scopes') %>
|
|
48
49
|
</span>
|
|
49
50
|
</div>
|
|
50
|
-
|
|
51
|
+
</div>
|
|
51
52
|
|
|
52
53
|
<div class="form-group">
|
|
53
54
|
<div class="col-sm-offset-2 col-sm-10">
|
|
54
|
-
<%= f.submit t('doorkeeper.applications.buttons.submit'), class:
|
|
55
|
-
<%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, class:
|
|
55
|
+
<%= f.submit t('doorkeeper.applications.buttons.submit'), class: 'btn btn-primary' %>
|
|
56
|
+
<%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, class: 'btn btn-secondary' %>
|
|
56
57
|
</div>
|
|
57
58
|
</div>
|
|
58
59
|
<% end %>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div class="
|
|
1
|
+
<div class="border-bottom mb-4">
|
|
2
2
|
<h1><%= t('.title') %></h1>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
@@ -10,18 +10,28 @@
|
|
|
10
10
|
<th><%= t('.name') %></th>
|
|
11
11
|
<th><%= t('.callback_url') %></th>
|
|
12
12
|
<th><%= t('.confidential') %></th>
|
|
13
|
-
<th
|
|
13
|
+
<th><%= t('.actions') %></th>
|
|
14
14
|
<th></th>
|
|
15
15
|
</tr>
|
|
16
16
|
</thead>
|
|
17
17
|
<tbody>
|
|
18
18
|
<% @applications.each do |application| %>
|
|
19
19
|
<tr id="application_<%= application.id %>">
|
|
20
|
-
<td
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<td
|
|
24
|
-
|
|
20
|
+
<td class="align-middle">
|
|
21
|
+
<%= link_to application.name, oauth_application_path(application) %>
|
|
22
|
+
</td>
|
|
23
|
+
<td class="align-middle">
|
|
24
|
+
<%= application.redirect_uri %>
|
|
25
|
+
</td>
|
|
26
|
+
<td class="align-middle">
|
|
27
|
+
<%= application.confidential? ? t('doorkeeper.applications.index.confidentiality.yes') : t('doorkeeper.applications.index.confidentiality.no') %>
|
|
28
|
+
</td>
|
|
29
|
+
<td class="align-middle">
|
|
30
|
+
<%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %>
|
|
31
|
+
</td>
|
|
32
|
+
<td class="align-middle">
|
|
33
|
+
<%= render 'delete_form', application: application %>
|
|
34
|
+
</td>
|
|
25
35
|
</tr>
|
|
26
36
|
<% end %>
|
|
27
37
|
</tbody>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
<div class="
|
|
1
|
+
<div class="border-bottom mb-4">
|
|
2
2
|
<h1><%= t('.title', name: @application.name) %></h1>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
<div class="row">
|
|
6
6
|
<div class="col-md-8">
|
|
7
7
|
<h4><%= t('.application_id') %>:</h4>
|
|
8
|
-
<p><code id="application_id"><%= @application.uid %></code></p>
|
|
8
|
+
<p><code class="bg-light" id="application_id"><%= @application.uid %></code></p>
|
|
9
9
|
|
|
10
10
|
<h4><%= t('.secret') %>:</h4>
|
|
11
|
-
<p><code id="secret"><%= @application.secret %></code></p>
|
|
11
|
+
<p><code class="bg-light" id="secret"><%= @application.secret %></code></p>
|
|
12
12
|
|
|
13
13
|
<h4><%= t('.scopes') %>:</h4>
|
|
14
|
-
<p><code id="scopes"><%= @application.scopes %></code></p>
|
|
14
|
+
<p><code class="bg-light" id="scopes"><%= @application.scopes.presence || raw(' ') %></code></p>
|
|
15
15
|
|
|
16
16
|
<h4><%= t('.confidential') %>:</h4>
|
|
17
|
-
<p><code id="confidential"><%= @application.confidential? %></code></p>
|
|
17
|
+
<p><code class="bg-light" id="confidential"><%= @application.confidential? %></code></p>
|
|
18
18
|
|
|
19
19
|
<h4><%= t('.callback_urls') %>:</h4>
|
|
20
20
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
<% @application.redirect_uri.split.each do |uri| %>
|
|
23
23
|
<tr>
|
|
24
24
|
<td>
|
|
25
|
-
<code><%= uri %></code>
|
|
25
|
+
<code class="bg-light"><%= uri %></code>
|
|
26
26
|
</td>
|
|
27
27
|
<td>
|
|
28
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,6 +26,8 @@
|
|
|
26
26
|
<%= hidden_field_tag :state, @pre_auth.state %>
|
|
27
27
|
<%= hidden_field_tag :response_type, @pre_auth.response_type %>
|
|
28
28
|
<%= hidden_field_tag :scope, @pre_auth.scope %>
|
|
29
|
+
<%= hidden_field_tag :code_challenge, @pre_auth.code_challenge %>
|
|
30
|
+
<%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method %>
|
|
29
31
|
<%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %>
|
|
30
32
|
<% end %>
|
|
31
33
|
<%= form_tag oauth_authorization_path, method: :delete do %>
|
|
@@ -34,6 +36,8 @@
|
|
|
34
36
|
<%= hidden_field_tag :state, @pre_auth.state %>
|
|
35
37
|
<%= hidden_field_tag :response_type, @pre_auth.response_type %>
|
|
36
38
|
<%= hidden_field_tag :scope, @pre_auth.scope %>
|
|
39
|
+
<%= hidden_field_tag :code_challenge, @pre_auth.code_challenge %>
|
|
40
|
+
<%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method %>
|
|
37
41
|
<%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %>
|
|
38
42
|
<% end %>
|
|
39
43
|
</div>
|
|
@@ -4,27 +4,27 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title
|
|
7
|
+
<title><%= t('doorkeeper.layouts.admin.title') %></title>
|
|
8
8
|
<%= stylesheet_link_tag "doorkeeper/admin/application" %>
|
|
9
9
|
<%= csrf_meta_tags %>
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<% end %>
|
|
12
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-5">
|
|
13
|
+
<%= link_to t('doorkeeper.layouts.admin.nav.oauth2_provider'), oauth_applications_path, class: 'navbar-brand' %>
|
|
14
|
+
|
|
15
|
+
<div class="collapse navbar-collapse">
|
|
16
|
+
<ul class="navbar-nav mr-auto">
|
|
17
|
+
<li class="nav-item <%= 'active' if request.path == oauth_applications_path %>">
|
|
18
|
+
<%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path, class: 'nav-link' %>
|
|
19
|
+
</li>
|
|
20
|
+
<li class="nav-item">
|
|
21
|
+
<%= link_to t('doorkeeper.layouts.admin.nav.home'), root_path, class: 'nav-link' %>
|
|
22
|
+
</li>
|
|
24
23
|
</ul>
|
|
25
24
|
</div>
|
|
26
|
-
</
|
|
27
|
-
|
|
25
|
+
</nav>
|
|
26
|
+
|
|
27
|
+
<div class="doorkeeper-admin container">
|
|
28
28
|
<%- if flash[:notice].present? %>
|
|
29
29
|
<div class="alert alert-info">
|
|
30
30
|
<%= flash[:notice] %>
|
data/config/locales/en.yml
CHANGED
|
@@ -14,6 +14,8 @@ en:
|
|
|
14
14
|
relative_uri: 'must be an absolute URI.'
|
|
15
15
|
secured_uri: 'must be an HTTPS/SSL URI.'
|
|
16
16
|
forbidden_uri: 'is forbidden by the server.'
|
|
17
|
+
scopes:
|
|
18
|
+
not_match_configured: "doesn't match configured on the server."
|
|
17
19
|
|
|
18
20
|
doorkeeper:
|
|
19
21
|
applications:
|
|
@@ -40,6 +42,7 @@ en:
|
|
|
40
42
|
name: 'Name'
|
|
41
43
|
callback_url: 'Callback URL'
|
|
42
44
|
confidential: 'Confidential?'
|
|
45
|
+
actions: 'Actions'
|
|
43
46
|
confidentiality:
|
|
44
47
|
'yes': 'Yes'
|
|
45
48
|
'no': 'No'
|
|
@@ -47,7 +50,7 @@ en:
|
|
|
47
50
|
title: 'New Application'
|
|
48
51
|
show:
|
|
49
52
|
title: 'Application: %{name}'
|
|
50
|
-
application_id: 'Application
|
|
53
|
+
application_id: 'Application UID'
|
|
51
54
|
secret: 'Secret'
|
|
52
55
|
scopes: 'Scopes'
|
|
53
56
|
confidential: 'Confidential'
|
|
@@ -78,6 +81,9 @@ en:
|
|
|
78
81
|
created_at: 'Created At'
|
|
79
82
|
date_format: '%Y-%m-%d %H:%M:%S'
|
|
80
83
|
|
|
84
|
+
pre_authorization:
|
|
85
|
+
status: 'Pre-authorization'
|
|
86
|
+
|
|
81
87
|
errors:
|
|
82
88
|
messages:
|
|
83
89
|
# Common error messages
|
|
@@ -86,6 +92,7 @@ en:
|
|
|
86
92
|
unauthorized_client: 'The client is not authorized to perform this request using this method.'
|
|
87
93
|
access_denied: 'The resource owner or authorization server denied the request.'
|
|
88
94
|
invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
|
|
95
|
+
invalid_code_challenge_method: 'The code challenge method must be plain or S256.'
|
|
89
96
|
server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
|
|
90
97
|
temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
|
|
91
98
|
|
|
@@ -120,6 +127,7 @@ en:
|
|
|
120
127
|
|
|
121
128
|
layouts:
|
|
122
129
|
admin:
|
|
130
|
+
title: 'Doorkeeper'
|
|
123
131
|
nav:
|
|
124
132
|
oauth2_provider: 'OAuth2 Provider'
|
|
125
133
|
applications: 'Applications'
|
data/doorkeeper.gemspec
CHANGED
data/gemfiles/rails_5_2.gemfile
CHANGED
data/lib/doorkeeper/config.rb
CHANGED
|
@@ -15,19 +15,19 @@ module Doorkeeper
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def self.configuration
|
|
18
|
-
@config || (
|
|
18
|
+
@config || (raise MissingConfiguration)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def self.setup_orm_adapter
|
|
22
22
|
@orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
|
|
23
|
-
rescue NameError =>
|
|
24
|
-
|
|
25
|
-
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
|
|
26
|
-
trying to load it.
|
|
27
|
-
|
|
28
|
-
You probably need to add the related gem for this adapter to work with
|
|
29
|
-
doorkeeper.
|
|
30
|
-
|
|
23
|
+
rescue NameError => error
|
|
24
|
+
raise error, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
|
|
25
|
+
[doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
|
|
26
|
+
trying to load it.
|
|
27
|
+
|
|
28
|
+
You probably need to add the related gem for this adapter to work with
|
|
29
|
+
doorkeeper.
|
|
30
|
+
ERROR_MSG
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def self.setup_orm_models
|
|
@@ -90,7 +90,7 @@ doorkeeper.
|
|
|
90
90
|
#
|
|
91
91
|
# @param methods [Array] Define client credentials
|
|
92
92
|
def client_credentials(*methods)
|
|
93
|
-
@config.instance_variable_set(:@
|
|
93
|
+
@config.instance_variable_set(:@client_credentials_methods, methods)
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
# Change the way access token is authenticated from the request object.
|
|
@@ -114,6 +114,25 @@ doorkeeper.
|
|
|
114
114
|
def reuse_access_token
|
|
115
115
|
@config.instance_variable_set(:@reuse_access_token, true)
|
|
116
116
|
end
|
|
117
|
+
|
|
118
|
+
# Use an API mode for applications generated with --api argument
|
|
119
|
+
# It will skip applications controller, disable forgery protection
|
|
120
|
+
def api_only
|
|
121
|
+
@config.instance_variable_set(:@api_only, true)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Forbids creating/updating applications with arbitrary scopes that are
|
|
125
|
+
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
|
126
|
+
# (disabled by default)
|
|
127
|
+
def enforce_configured_scopes
|
|
128
|
+
@config.instance_variable_set(:@enforce_configured_scopes, true)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Enforce request content type as the spec requires:
|
|
132
|
+
# disabled by default for backward compatibility.
|
|
133
|
+
def enforce_content_type
|
|
134
|
+
@config.instance_variable_set(:@enforce_content_type, true)
|
|
135
|
+
end
|
|
117
136
|
end
|
|
118
137
|
|
|
119
138
|
module Option
|
|
@@ -179,7 +198,10 @@ doorkeeper.
|
|
|
179
198
|
option :resource_owner_authenticator,
|
|
180
199
|
as: :authenticate_resource_owner,
|
|
181
200
|
default: (lambda do |_routes|
|
|
182
|
-
::Rails.logger.warn(
|
|
201
|
+
::Rails.logger.warn(
|
|
202
|
+
I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured')
|
|
203
|
+
)
|
|
204
|
+
|
|
183
205
|
nil
|
|
184
206
|
end)
|
|
185
207
|
|
|
@@ -189,15 +211,20 @@ doorkeeper.
|
|
|
189
211
|
|
|
190
212
|
option :resource_owner_from_credentials,
|
|
191
213
|
default: (lambda do |_routes|
|
|
192
|
-
::Rails.logger.warn(
|
|
214
|
+
::Rails.logger.warn(
|
|
215
|
+
I18n.t('doorkeeper.errors.messages.credential_flow_not_configured')
|
|
216
|
+
)
|
|
217
|
+
|
|
193
218
|
nil
|
|
194
219
|
end)
|
|
220
|
+
option :before_successful_authorization, default: ->(_context) {}
|
|
221
|
+
option :after_successful_authorization, default: ->(_context) {}
|
|
195
222
|
option :before_successful_strategy_response, default: ->(_request) {}
|
|
196
223
|
option :after_successful_strategy_response,
|
|
197
224
|
default: ->(_request, _response) {}
|
|
198
225
|
option :skip_authorization, default: ->(_routes) {}
|
|
199
226
|
option :access_token_expires_in, default: 7200
|
|
200
|
-
option :custom_access_token_expires_in, default: ->(
|
|
227
|
+
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
|
201
228
|
option :authorization_code_expires_in, default: 600
|
|
202
229
|
option :orm, default: :active_record
|
|
203
230
|
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
|
|
@@ -232,7 +259,6 @@ doorkeeper.
|
|
|
232
259
|
#
|
|
233
260
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
|
234
261
|
|
|
235
|
-
|
|
236
262
|
# Use a custom class for generating the access token.
|
|
237
263
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
|
238
264
|
#
|
|
@@ -251,20 +277,31 @@ doorkeeper.
|
|
|
251
277
|
default: 'ActionController::Base'
|
|
252
278
|
|
|
253
279
|
attr_reader :reuse_access_token
|
|
280
|
+
attr_reader :api_only
|
|
281
|
+
attr_reader :enforce_content_type
|
|
282
|
+
|
|
283
|
+
def api_only
|
|
284
|
+
@api_only ||= false
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def enforce_content_type
|
|
288
|
+
@enforce_content_type ||= false
|
|
289
|
+
end
|
|
254
290
|
|
|
255
291
|
def refresh_token_enabled?
|
|
256
|
-
@refresh_token_enabled
|
|
257
|
-
|
|
292
|
+
!!(defined?(@refresh_token_enabled) && @refresh_token_enabled)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def enforce_configured_scopes?
|
|
296
|
+
!!(defined?(@enforce_configured_scopes) && @enforce_configured_scopes)
|
|
258
297
|
end
|
|
259
298
|
|
|
260
299
|
def enable_application_owner?
|
|
261
|
-
@enable_application_owner
|
|
262
|
-
!!@enable_application_owner
|
|
300
|
+
!!(defined?(@enable_application_owner) && @enable_application_owner)
|
|
263
301
|
end
|
|
264
302
|
|
|
265
303
|
def confirm_application_owner?
|
|
266
|
-
@confirm_application_owner
|
|
267
|
-
!!@confirm_application_owner
|
|
304
|
+
!!(defined?(@confirm_application_owner) && @confirm_application_owner)
|
|
268
305
|
end
|
|
269
306
|
|
|
270
307
|
def default_scopes
|
|
@@ -280,7 +317,7 @@ doorkeeper.
|
|
|
280
317
|
end
|
|
281
318
|
|
|
282
319
|
def client_credentials_methods
|
|
283
|
-
@
|
|
320
|
+
@client_credentials_methods ||= %i[from_basic from_params]
|
|
284
321
|
end
|
|
285
322
|
|
|
286
323
|
def access_token_methods
|
|
@@ -288,11 +325,11 @@ doorkeeper.
|
|
|
288
325
|
end
|
|
289
326
|
|
|
290
327
|
def authorization_response_types
|
|
291
|
-
@authorization_response_types ||= calculate_authorization_response_types
|
|
328
|
+
@authorization_response_types ||= calculate_authorization_response_types.freeze
|
|
292
329
|
end
|
|
293
330
|
|
|
294
331
|
def token_grant_types
|
|
295
|
-
@token_grant_types ||= calculate_token_grant_types
|
|
332
|
+
@token_grant_types ||= calculate_token_grant_types.freeze
|
|
296
333
|
end
|
|
297
334
|
|
|
298
335
|
private
|
data/lib/doorkeeper/engine.rb
CHANGED
|
@@ -17,6 +17,10 @@ module Doorkeeper
|
|
|
17
17
|
|
|
18
18
|
if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
|
|
19
19
|
initializer 'doorkeeper.assets.precompile' do |app|
|
|
20
|
+
# Force users to use:
|
|
21
|
+
# //= link doorkeeper/admin/application.css
|
|
22
|
+
# in Doorkeeper 5 for Sprockets 4 instead of precompile.
|
|
23
|
+
# Add note to official docs & Wiki
|
|
20
24
|
app.config.assets.precompile += %w[
|
|
21
25
|
doorkeeper/application.css
|
|
22
26
|
doorkeeper/admin/application.css
|
data/lib/doorkeeper/errors.rb
CHANGED
|
@@ -36,10 +36,7 @@ module Doorkeeper
|
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class TokenGeneratorNotFound < DoorkeeperError
|
|
43
|
-
end
|
|
39
|
+
UnableToGenerateToken = Class.new(DoorkeeperError)
|
|
40
|
+
TokenGeneratorNotFound = Class.new(DoorkeeperError)
|
|
44
41
|
end
|
|
45
42
|
end
|
|
@@ -30,11 +30,11 @@ module Doorkeeper
|
|
|
30
30
|
|
|
31
31
|
# :doc:
|
|
32
32
|
def doorkeeper_token
|
|
33
|
-
@
|
|
33
|
+
@doorkeeper_token ||= OAuth::Token.authenticate request, *config_methods
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def config_methods
|
|
37
|
-
@
|
|
37
|
+
@config_methods ||= Doorkeeper.configuration.access_token_methods
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def get_error_response_from_exception(exception)
|
|
@@ -51,6 +51,11 @@ module Doorkeeper
|
|
|
51
51
|
def skip_authorization?
|
|
52
52
|
!!instance_exec([@server.current_resource_owner, @pre_auth.client], &Doorkeeper.configuration.skip_authorization)
|
|
53
53
|
end
|
|
54
|
+
|
|
55
|
+
def enforce_content_type
|
|
56
|
+
return if request.content_type == 'application/x-www-form-urlencoded'
|
|
57
|
+
render json: {}, status: :unsupported_media_type
|
|
58
|
+
end
|
|
54
59
|
end
|
|
55
60
|
end
|
|
56
61
|
end
|
|
@@ -9,6 +9,15 @@ module Doorkeeper
|
|
|
9
9
|
include Models::Orderable
|
|
10
10
|
include Models::Scopes
|
|
11
11
|
|
|
12
|
+
# never uses pkce, if pkce migrations were not generated
|
|
13
|
+
def uses_pkce?
|
|
14
|
+
pkce_supported? && code_challenge.present?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def pkce_supported?
|
|
18
|
+
respond_to? :code_challenge
|
|
19
|
+
end
|
|
20
|
+
|
|
12
21
|
module ClassMethods
|
|
13
22
|
# Searches for Doorkeeper::AccessGrant record with the
|
|
14
23
|
# specific token value.
|
|
@@ -21,6 +30,53 @@ module Doorkeeper
|
|
|
21
30
|
def by_token(token)
|
|
22
31
|
find_by(token: token.to_s)
|
|
23
32
|
end
|
|
33
|
+
|
|
34
|
+
# Implements PKCE code_challenge encoding without base64 padding as described in the spec.
|
|
35
|
+
# https://tools.ietf.org/html/rfc7636#appendix-A
|
|
36
|
+
# Appendix A. Notes on Implementing Base64url Encoding without Padding
|
|
37
|
+
#
|
|
38
|
+
# This appendix describes how to implement a base64url-encoding
|
|
39
|
+
# function without padding, based upon the standard base64-encoding
|
|
40
|
+
# function that uses padding.
|
|
41
|
+
#
|
|
42
|
+
# To be concrete, example C# code implementing these functions is shown
|
|
43
|
+
# below. Similar code could be used in other languages.
|
|
44
|
+
#
|
|
45
|
+
# static string base64urlencode(byte [] arg)
|
|
46
|
+
# {
|
|
47
|
+
# string s = Convert.ToBase64String(arg); // Regular base64 encoder
|
|
48
|
+
# s = s.Split('=')[0]; // Remove any trailing '='s
|
|
49
|
+
# s = s.Replace('+', '-'); // 62nd char of encoding
|
|
50
|
+
# s = s.Replace('/', '_'); // 63rd char of encoding
|
|
51
|
+
# return s;
|
|
52
|
+
# }
|
|
53
|
+
#
|
|
54
|
+
# An example correspondence between unencoded and encoded values
|
|
55
|
+
# follows. The octet sequence below encodes into the string below,
|
|
56
|
+
# which when decoded, reproduces the octet sequence.
|
|
57
|
+
#
|
|
58
|
+
# 3 236 255 224 193
|
|
59
|
+
#
|
|
60
|
+
# A-z_4ME
|
|
61
|
+
#
|
|
62
|
+
# https://ruby-doc.org/stdlib-2.1.3/libdoc/base64/rdoc/Base64.html#method-i-urlsafe_encode64
|
|
63
|
+
#
|
|
64
|
+
# urlsafe_encode64(bin)
|
|
65
|
+
# Returns the Base64-encoded version of bin. This method complies with
|
|
66
|
+
# “Base 64 Encoding with URL and Filename Safe Alphabet” in RFC 4648.
|
|
67
|
+
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
|
68
|
+
|
|
69
|
+
# @param code_verifier [#to_s] a one time use value (any object that responds to `#to_s`)
|
|
70
|
+
#
|
|
71
|
+
# @return [#to_s] An encoded code challenge based on the provided verifier suitable for PKCE validation
|
|
72
|
+
def generate_code_challenge(code_verifier)
|
|
73
|
+
padded_result = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier))
|
|
74
|
+
padded_result.split('=')[0] # Remove any trailing '='
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def pkce_supported?
|
|
78
|
+
new.pkce_supported?
|
|
79
|
+
end
|
|
24
80
|
end
|
|
25
81
|
end
|
|
26
82
|
end
|