doorkeeper 4.4.3 → 5.0.0.rc1
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/.gitignore +1 -0
- data/.travis.yml +2 -0
- data/Appraisals +2 -2
- data/Gemfile +1 -1
- data/NEWS.md +36 -17
- 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 +58 -35
- 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/password_access_token_request.rb +7 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +41 -11
- 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 +14 -6
- 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 -49
- 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 +5 -4
- 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 +51 -31
- 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 +9 -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 -7
- 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 +33 -4
- 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 -47
- 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/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
- 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
@@ -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.
|
@@ -115,13 +115,23 @@ doorkeeper.
|
|
115
115
|
@config.instance_variable_set(:@reuse_access_token, true)
|
116
116
|
end
|
117
117
|
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
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)
|
125
135
|
end
|
126
136
|
end
|
127
137
|
|
@@ -188,7 +198,10 @@ doorkeeper.
|
|
188
198
|
option :resource_owner_authenticator,
|
189
199
|
as: :authenticate_resource_owner,
|
190
200
|
default: (lambda do |_routes|
|
191
|
-
::Rails.logger.warn(
|
201
|
+
::Rails.logger.warn(
|
202
|
+
I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured')
|
203
|
+
)
|
204
|
+
|
192
205
|
nil
|
193
206
|
end)
|
194
207
|
|
@@ -198,15 +211,20 @@ doorkeeper.
|
|
198
211
|
|
199
212
|
option :resource_owner_from_credentials,
|
200
213
|
default: (lambda do |_routes|
|
201
|
-
::Rails.logger.warn(
|
214
|
+
::Rails.logger.warn(
|
215
|
+
I18n.t('doorkeeper.errors.messages.credential_flow_not_configured')
|
216
|
+
)
|
217
|
+
|
202
218
|
nil
|
203
219
|
end)
|
220
|
+
option :before_successful_authorization, default: ->(_context) {}
|
221
|
+
option :after_successful_authorization, default: ->(_context) {}
|
204
222
|
option :before_successful_strategy_response, default: ->(_request) {}
|
205
223
|
option :after_successful_strategy_response,
|
206
224
|
default: ->(_request, _response) {}
|
207
225
|
option :skip_authorization, default: ->(_routes) {}
|
208
226
|
option :access_token_expires_in, default: 7200
|
209
|
-
option :custom_access_token_expires_in, default: ->(
|
227
|
+
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
210
228
|
option :authorization_code_expires_in, default: 600
|
211
229
|
option :orm, default: :active_record
|
212
230
|
option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
|
@@ -241,7 +259,6 @@ doorkeeper.
|
|
241
259
|
#
|
242
260
|
option :force_ssl_in_redirect_uri, default: !Rails.env.development?
|
243
261
|
|
244
|
-
|
245
262
|
# Use a custom class for generating the access token.
|
246
263
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
247
264
|
#
|
@@ -260,20 +277,31 @@ doorkeeper.
|
|
260
277
|
default: 'ActionController::Base'
|
261
278
|
|
262
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
|
263
290
|
|
264
291
|
def refresh_token_enabled?
|
265
|
-
@refresh_token_enabled
|
266
|
-
|
292
|
+
!!(defined?(@refresh_token_enabled) && @refresh_token_enabled)
|
293
|
+
end
|
294
|
+
|
295
|
+
def enforce_configured_scopes?
|
296
|
+
!!(defined?(@enforce_configured_scopes) && @enforce_configured_scopes)
|
267
297
|
end
|
268
298
|
|
269
299
|
def enable_application_owner?
|
270
|
-
@enable_application_owner
|
271
|
-
!!@enable_application_owner
|
300
|
+
!!(defined?(@enable_application_owner) && @enable_application_owner)
|
272
301
|
end
|
273
302
|
|
274
303
|
def confirm_application_owner?
|
275
|
-
@confirm_application_owner
|
276
|
-
!!@confirm_application_owner
|
304
|
+
!!(defined?(@confirm_application_owner) && @confirm_application_owner)
|
277
305
|
end
|
278
306
|
|
279
307
|
def default_scopes
|
@@ -289,7 +317,7 @@ doorkeeper.
|
|
289
317
|
end
|
290
318
|
|
291
319
|
def client_credentials_methods
|
292
|
-
@
|
320
|
+
@client_credentials_methods ||= %i[from_basic from_params]
|
293
321
|
end
|
294
322
|
|
295
323
|
def access_token_methods
|
@@ -297,16 +325,11 @@ doorkeeper.
|
|
297
325
|
end
|
298
326
|
|
299
327
|
def authorization_response_types
|
300
|
-
@authorization_response_types ||= calculate_authorization_response_types
|
328
|
+
@authorization_response_types ||= calculate_authorization_response_types.freeze
|
301
329
|
end
|
302
330
|
|
303
331
|
def token_grant_types
|
304
|
-
@token_grant_types ||= calculate_token_grant_types
|
305
|
-
end
|
306
|
-
|
307
|
-
def native_authorization_code_route
|
308
|
-
@opt_out_native_route_change ||= false
|
309
|
-
@opt_out_native_route_change ? '/:code' : '/native'
|
332
|
+
@token_grant_types ||= calculate_token_grant_types.freeze
|
310
333
|
end
|
311
334
|
|
312
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
|