doorkeeper 4.2.6 → 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/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +2 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +19 -5
- data/Appraisals +8 -4
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +77 -0
- data/README.md +169 -34
- data/Rakefile +6 -0
- data/SECURITY.md +15 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -5
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +47 -13
- 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 +15 -7
- data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
- data/app/validators/redirect_uri_validator.rb +13 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +31 -19
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +8 -5
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +18 -6
- data/doorkeeper.gemspec +6 -5
- data/gemfiles/rails_4_2.gemfile +6 -4
- data/gemfiles/rails_5_0.gemfile +4 -4
- data/gemfiles/rails_5_1.gemfile +6 -7
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +107 -68
- data/lib/doorkeeper/engine.rb +7 -3
- data/lib/doorkeeper/errors.rb +2 -5
- data/lib/doorkeeper/grape/helpers.rb +14 -9
- data/lib/doorkeeper/helpers/controller.rb +15 -6
- data/lib/doorkeeper/models/access_grant_mixin.rb +52 -23
- data/lib/doorkeeper/models/access_token_mixin.rb +51 -52
- data/lib/doorkeeper/models/application_mixin.rb +16 -30
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- 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 +41 -20
- data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
- data/lib/doorkeeper/oauth/base_request.rb +22 -7
- data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +2 -2
- 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.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -4
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
- data/lib/doorkeeper/oauth/scopes.rb +19 -9
- data/lib/doorkeeper/oauth/token.rb +6 -3
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
- data/lib/doorkeeper/orm/active_record/application.rb +34 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +21 -8
- data/lib/doorkeeper/rails/helpers.rb +7 -10
- data/lib/doorkeeper/rails/routes.rb +21 -7
- 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/password.rb +1 -11
- data/lib/doorkeeper/request.rb +29 -23
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +14 -1
- data/lib/doorkeeper.rb +6 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
- 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 +26 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +88 -10
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
- 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 +141 -17
- data/spec/controllers/authorizations_controller_spec.rb +255 -20
- data/spec/controllers/protected_resources_controller_spec.rb +44 -35
- data/spec/controllers/token_info_controller_spec.rb +17 -21
- data/spec/controllers/tokens_controller_spec.rb +142 -10
- 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 +18 -1
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/config/routes.rb +3 -42
- 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/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
- data/spec/dummy/db/schema.rb +38 -37
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +25 -6
- 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 +25 -4
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
- data/spec/lib/config_spec.rb +170 -22
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +2 -4
- 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 +63 -13
- data/spec/lib/oauth/base_request_spec.rb +19 -10
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
- 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 +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -5
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +1 -3
- 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 +115 -3
- data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
- data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
- data/spec/lib/oauth/scopes_spec.rb +28 -4
- data/spec/lib/oauth/token_request_spec.rb +10 -13
- 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 +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +2 -2
- data/spec/models/doorkeeper/access_token_spec.rb +118 -60
- data/spec/models/doorkeeper/application_spec.rb +101 -23
- data/spec/requests/applications/applications_request_spec.rb +94 -6
- 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 +15 -6
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_spec.rb +198 -1
- data/spec/requests/flows/client_credentials_spec.rb +73 -5
- data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +160 -24
- data/spec/requests/flows/refresh_token_spec.rb +6 -6
- data/spec/requests/flows/revoke_token_spec.rb +26 -26
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +2 -2
- data/spec/requests/protected_resources/private_api_spec.rb +2 -2
- data/spec/routing/custom_controller_routes_spec.rb +63 -7
- data/spec/routing/default_routes_spec.rb +6 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -63
- data/spec/support/dependencies/factory_bot.rb +2 -0
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -6
- data/spec/support/helpers/url_helper.rb +15 -10
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +2 -6
- data/spec/support/shared/models_shared_examples.rb +4 -4
- data/spec/validators/redirect_uri_validator_spec.rb +58 -7
- data/spec/version/version_spec.rb +15 -0
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +73 -19
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/support/dependencies/factory_girl.rb +0 -2
data/README.md
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
# Doorkeeper - awesome
|
|
1
|
+
# Doorkeeper - awesome OAuth 2 provider for your Rails app.
|
|
2
2
|
|
|
3
|
+
[](https://rubygems.org/gems/doorkeeper)
|
|
3
4
|
[](https://travis-ci.org/doorkeeper-gem/doorkeeper)
|
|
4
5
|
[](https://gemnasium.com/doorkeeper-gem/doorkeeper)
|
|
5
6
|
[](https://codeclimate.com/github/doorkeeper-gem/doorkeeper)
|
|
6
|
-
[](https://coveralls.io/github/doorkeeper-gem/doorkeeper?branch=master)
|
|
7
8
|
[](https://hakiri.io/github/doorkeeper-gem/doorkeeper/master)
|
|
8
9
|
|
|
9
10
|
Doorkeeper is a gem that makes it easy to introduce OAuth 2 provider
|
|
10
11
|
functionality to your Rails or Grape application.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Supported features:
|
|
13
14
|
|
|
15
|
+
- [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
|
|
16
|
+
- [Authorization Code Flow](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.1)
|
|
17
|
+
- [Access Token Scopes](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.3)
|
|
18
|
+
- [Refresh token](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-1.5)
|
|
19
|
+
- [Implicit grant](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.2)
|
|
20
|
+
- [Resource Owner Password Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.3)
|
|
21
|
+
- [Client Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.4)
|
|
22
|
+
- [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636)
|
|
23
|
+
- [OAuth 2.0 Token Revocation](http://tools.ietf.org/html/rfc7009)
|
|
24
|
+
- [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662)
|
|
14
25
|
|
|
15
26
|
## Documentation valid for `master` branch
|
|
16
27
|
|
|
@@ -18,7 +29,10 @@ Please check the documentation for the version of doorkeeper you are using in:
|
|
|
18
29
|
https://github.com/doorkeeper-gem/doorkeeper/releases
|
|
19
30
|
|
|
20
31
|
- See the [wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki)
|
|
32
|
+
- See [upgrade guides](https://github.com/doorkeeper-gem/doorkeeper/wiki/Migration-from-old-versions)
|
|
21
33
|
- For general questions, please post in [Stack Overflow](http://stackoverflow.com/questions/tagged/doorkeeper)
|
|
34
|
+
- See [SECURITY.md](SECURITY.md) for this project's security disclose
|
|
35
|
+
policy
|
|
22
36
|
|
|
23
37
|
## Table of Contents
|
|
24
38
|
|
|
@@ -27,19 +41,26 @@ https://github.com/doorkeeper-gem/doorkeeper/releases
|
|
|
27
41
|
|
|
28
42
|
- [Installation](#installation)
|
|
29
43
|
- [Configuration](#configuration)
|
|
30
|
-
- [
|
|
31
|
-
|
|
44
|
+
- [ORM](#orm)
|
|
45
|
+
- [Active Record](#active-record)
|
|
46
|
+
- [MongoDB](#mongodb)
|
|
47
|
+
- [Sequel](#sequel)
|
|
48
|
+
- [Couchbase](#couchbase)
|
|
49
|
+
- [API mode](#api-mode)
|
|
32
50
|
- [Routes](#routes)
|
|
33
51
|
- [Authenticating](#authenticating)
|
|
34
52
|
- [Internationalization (I18n)](#internationalization-i18n)
|
|
53
|
+
- [Rake Tasks](#rake-tasks)
|
|
35
54
|
- [Protecting resources with OAuth (a.k.a your API endpoint)](#protecting-resources-with-oauth-aka-your-api-endpoint)
|
|
36
|
-
- [
|
|
55
|
+
- [Ruby on Rails controllers](#ruby-on-rails-controllers)
|
|
56
|
+
- [Grape endpoints](#grape-endpoints)
|
|
37
57
|
- [Route Constraints and other integrations](#route-constraints-and-other-integrations)
|
|
38
58
|
- [Access Token Scopes](#access-token-scopes)
|
|
39
59
|
- [Custom Access Token Generator](#custom-access-token-generator)
|
|
40
60
|
- [Authenticated resource owner](#authenticated-resource-owner)
|
|
41
61
|
- [Applications list](#applications-list)
|
|
42
62
|
- [Other customizations](#other-customizations)
|
|
63
|
+
- [Testing](#testing)
|
|
43
64
|
- [Upgrading](#upgrading)
|
|
44
65
|
- [Development](#development)
|
|
45
66
|
- [Contributing](#contributing)
|
|
@@ -69,10 +90,12 @@ This will install the doorkeeper initializer into `config/initializers/doorkeepe
|
|
|
69
90
|
|
|
70
91
|
## Configuration
|
|
71
92
|
|
|
72
|
-
###
|
|
93
|
+
### ORM
|
|
73
94
|
|
|
74
|
-
|
|
75
|
-
|
|
95
|
+
#### Active Record
|
|
96
|
+
|
|
97
|
+
By default doorkeeper is configured to use Active Record, so to start you have
|
|
98
|
+
to generate the migration tables (supports Rails >= 5 migrations versioning):
|
|
76
99
|
|
|
77
100
|
rails generate doorkeeper:migration
|
|
78
101
|
|
|
@@ -84,25 +107,82 @@ for each table that includes a `resource_owner_id` column:
|
|
|
84
107
|
add_foreign_key :table_name, :users, column: :resource_owner_id
|
|
85
108
|
```
|
|
86
109
|
|
|
110
|
+
If you want to enable [PKCE flow] for mobile apps, you need to generate another
|
|
111
|
+
migration:
|
|
112
|
+
|
|
113
|
+
[PKCE flow]: https://tools.ietf.org/html/rfc7636
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
rails generate doorkeeper:pkce
|
|
117
|
+
```
|
|
118
|
+
|
|
87
119
|
Then run migrations:
|
|
88
120
|
|
|
89
121
|
```sh
|
|
90
122
|
rake db:migrate
|
|
91
123
|
```
|
|
92
124
|
|
|
93
|
-
|
|
125
|
+
Ensure to use non-confidential apps for pkce. PKCE is created, because
|
|
126
|
+
you cannot trust its apps' secret. So whatever app needs pkce: it means, it cannot
|
|
127
|
+
be a confidential app by design.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
Remember to add associations to your model so the related records are deleted.
|
|
131
|
+
If you don't do this an `ActiveRecord::InvalidForeignKey`-error will be raised
|
|
132
|
+
when you try to destroy a model with related access grants or access tokens.
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
class User < ApplicationRecord
|
|
136
|
+
has_many :access_grants, class_name: "Doorkeeper::AccessGrant",
|
|
137
|
+
foreign_key: :resource_owner_id,
|
|
138
|
+
dependent: :delete_all # or :destroy if you need callbacks
|
|
139
|
+
|
|
140
|
+
has_many :access_tokens, class_name: "Doorkeeper::AccessToken",
|
|
141
|
+
foreign_key: :resource_owner_id,
|
|
142
|
+
dependent: :delete_all # or :destroy if you need callbacks
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### MongoDB
|
|
94
147
|
|
|
95
148
|
See [doorkeeper-mongodb project] for Mongoid and MongoMapper support. Follow along
|
|
96
149
|
the implementation in that repository to extend doorkeeper with other ORMs.
|
|
97
150
|
|
|
98
151
|
[doorkeeper-mongodb project]: https://github.com/doorkeeper-gem/doorkeeper-mongodb
|
|
99
152
|
|
|
153
|
+
#### Sequel
|
|
154
|
+
|
|
100
155
|
If you are using [Sequel gem] then you can add [doorkeeper-sequel extension] to your project.
|
|
101
156
|
Follow configuration instructions for setting up the necessary Doorkeeper ORM.
|
|
102
157
|
|
|
103
158
|
[Sequel gem]: https://github.com/jeremyevans/sequel/
|
|
104
159
|
[doorkeeper-sequel extension]: https://github.com/nbulaj/doorkeeper-sequel
|
|
105
160
|
|
|
161
|
+
#### Couchbase
|
|
162
|
+
|
|
163
|
+
Use [doorkeeper-couchbase] extension if you are using Couchbase database.
|
|
164
|
+
|
|
165
|
+
[doorkeeper-couchbase]: https://github.com/acaprojects/doorkeeper-couchbase
|
|
166
|
+
|
|
167
|
+
### API mode
|
|
168
|
+
|
|
169
|
+
By default Doorkeeper uses full Rails stack to provide all the OAuth 2 functionality
|
|
170
|
+
with additional features like administration area for managing applications. By the
|
|
171
|
+
way, starting from Doorkeeper 5 you can use API mode for your [API only Rails 5 applications](http://edgeguides.rubyonrails.org/api_app.html).
|
|
172
|
+
All you need is just to configure the gem to work in desired mode:
|
|
173
|
+
|
|
174
|
+
``` ruby
|
|
175
|
+
Doorkeeper.configure do
|
|
176
|
+
# ...
|
|
177
|
+
|
|
178
|
+
api_only
|
|
179
|
+
end
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Keep in mind, that in this mode you will not be able to access `Applications` or
|
|
183
|
+
`Authorized Applications` controllers because they will be skipped. Also all the
|
|
184
|
+
redirects will be returned as JSON response with corresponding locations.
|
|
185
|
+
|
|
106
186
|
### Routes
|
|
107
187
|
|
|
108
188
|
The installation script will also automatically add the Doorkeeper routes into
|
|
@@ -117,12 +197,13 @@ end
|
|
|
117
197
|
|
|
118
198
|
This will mount following routes:
|
|
119
199
|
|
|
120
|
-
GET /oauth/authorize
|
|
200
|
+
GET /oauth/authorize/native?code
|
|
121
201
|
GET /oauth/authorize
|
|
122
202
|
POST /oauth/authorize
|
|
123
203
|
DELETE /oauth/authorize
|
|
124
204
|
POST /oauth/token
|
|
125
205
|
POST /oauth/revoke
|
|
206
|
+
POST /oauth/introspect
|
|
126
207
|
resources /oauth/applications
|
|
127
208
|
GET /oauth/authorized_applications
|
|
128
209
|
DELETE /oauth/authorized_applications/:id
|
|
@@ -139,7 +220,7 @@ and authentication block in `config/initializers/doorkeeper.rb`:
|
|
|
139
220
|
``` ruby
|
|
140
221
|
Doorkeeper.configure do
|
|
141
222
|
resource_owner_authenticator do
|
|
142
|
-
User.
|
|
223
|
+
User.find_by(id: session[:current_user_id]) || redirect_to(login_url)
|
|
143
224
|
end
|
|
144
225
|
end
|
|
145
226
|
```
|
|
@@ -152,16 +233,46 @@ the methods defined over there.
|
|
|
152
233
|
You may want to check other ways of authentication
|
|
153
234
|
[here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Authenticating-using-Clearance-or-DIY).
|
|
154
235
|
|
|
155
|
-
|
|
156
236
|
### Internationalization (I18n)
|
|
157
237
|
|
|
158
|
-
See language files in
|
|
238
|
+
Doorkeeper support multiple languages. See language files in
|
|
239
|
+
[the I18n repository](https://github.com/doorkeeper-gem/doorkeeper-i18n).
|
|
240
|
+
|
|
241
|
+
### Rake Tasks
|
|
242
|
+
|
|
243
|
+
If you are using `rake`, you can load rake tasks provided by this gem, by adding
|
|
244
|
+
the following line to your `Rakefile`:
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
Doorkeeper::Rake.load_tasks
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Cleaning up
|
|
159
251
|
|
|
252
|
+
By default Doorkeeper is retaining expired and revoked access tokens and grants.
|
|
253
|
+
This allows to keep an audit log of those records, but it also leads to the
|
|
254
|
+
corresponding tables to grow large over the lifetime of your application.
|
|
255
|
+
|
|
256
|
+
If you are concerned about those tables growing too large,
|
|
257
|
+
you can regularly run the following rake task to remove stale entries
|
|
258
|
+
from the database:
|
|
259
|
+
|
|
260
|
+
```rake
|
|
261
|
+
rake doorkeeper:db:cleanup
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Note that this will remove tokens that are expired according to the configured TTL
|
|
265
|
+
in `Doorkeeper.configuration.access_token_expires_in`. The specific `expires_in`
|
|
266
|
+
value of each access token **is not considered**. The same is true for access
|
|
267
|
+
grants.
|
|
160
268
|
|
|
161
269
|
## Protecting resources with OAuth (a.k.a your API endpoint)
|
|
162
270
|
|
|
163
|
-
|
|
164
|
-
|
|
271
|
+
### Ruby on Rails controllers
|
|
272
|
+
|
|
273
|
+
To protect your controllers (usual one or `ActionController::API`) with OAuth,
|
|
274
|
+
you just need to setup `before_action`s specifying the actions you want to
|
|
275
|
+
protect. For example:
|
|
165
276
|
|
|
166
277
|
``` ruby
|
|
167
278
|
class Api::V1::ProductsController < Api::V1::ApiController
|
|
@@ -174,16 +285,17 @@ end
|
|
|
174
285
|
You can pass any option `before_action` accepts, such as `if`, `only`,
|
|
175
286
|
`except`, and others.
|
|
176
287
|
|
|
177
|
-
###
|
|
288
|
+
### Grape endpoints
|
|
178
289
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
`helpers
|
|
290
|
+
Starting from version 2.2 Doorkeeper provides helpers for the
|
|
291
|
+
[Grape framework] >= 0.10. One of them is `doorkeeper_authorize!` that
|
|
292
|
+
can be used in a similar way as an example above to protect your API
|
|
293
|
+
with OAuth. Note that you have to use `require 'doorkeeper/grape/helpers'`
|
|
294
|
+
and `helpers Doorkeeper::Grape::Helpers` in your Grape API class.
|
|
183
295
|
|
|
184
296
|
For more information about integration with Grape see the [Wiki].
|
|
185
297
|
|
|
186
|
-
[
|
|
298
|
+
[Grape framework]: https://github.com/ruby-grape/grape
|
|
187
299
|
[Wiki]: https://github.com/doorkeeper-gem/doorkeeper/wiki/Grape-Integration
|
|
188
300
|
|
|
189
301
|
``` ruby
|
|
@@ -198,8 +310,8 @@ module API
|
|
|
198
310
|
doorkeeper_authorize!
|
|
199
311
|
end
|
|
200
312
|
|
|
201
|
-
route_setting :scopes, ['user:email']
|
|
202
|
-
get :emails do
|
|
313
|
+
# route_setting :scopes, ['user:email'] - for old versions of Grape
|
|
314
|
+
get :emails, scopes: [:user, :write] do
|
|
203
315
|
[{'email' => current_user.email}]
|
|
204
316
|
end
|
|
205
317
|
|
|
@@ -209,7 +321,6 @@ module API
|
|
|
209
321
|
end
|
|
210
322
|
```
|
|
211
323
|
|
|
212
|
-
|
|
213
324
|
### Route Constraints and other integrations
|
|
214
325
|
|
|
215
326
|
You can leverage the `Doorkeeper.authenticate` facade to easily extract a
|
|
@@ -224,7 +335,6 @@ module Constraint
|
|
|
224
335
|
token = Doorkeeper.authenticate(request)
|
|
225
336
|
token && token.accessible?
|
|
226
337
|
end
|
|
227
|
-
|
|
228
338
|
end
|
|
229
339
|
end
|
|
230
340
|
```
|
|
@@ -296,8 +406,10 @@ JWT token support is available with
|
|
|
296
406
|
|
|
297
407
|
### Custom Base Controller
|
|
298
408
|
|
|
299
|
-
By default Doorkeeper's main controller `Doorkeeper::ApplicationController`
|
|
300
|
-
You may want to use your own
|
|
409
|
+
By default Doorkeeper's main controller `Doorkeeper::ApplicationController`
|
|
410
|
+
inherits from `ActionController::Base`. You may want to use your own
|
|
411
|
+
controller to inherit from, to keep Doorkeeper controllers in the same
|
|
412
|
+
context than the rest your app:
|
|
301
413
|
|
|
302
414
|
```ruby
|
|
303
415
|
Doorkeeper.configure do
|
|
@@ -342,7 +454,7 @@ To protect the endpoint you should uncomment these lines:
|
|
|
342
454
|
# config/initializers/doorkeeper.rb
|
|
343
455
|
Doorkeeper.configure do
|
|
344
456
|
admin_authenticator do |routes|
|
|
345
|
-
Admin.
|
|
457
|
+
Admin.find_by(id: session[:admin_id]) || redirect_to(routes.new_admin_session_url)
|
|
346
458
|
end
|
|
347
459
|
end
|
|
348
460
|
```
|
|
@@ -353,10 +465,36 @@ customize the controller used by the list or skip the controller all together.
|
|
|
353
465
|
For more information see the page
|
|
354
466
|
[in the wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
|
|
355
467
|
|
|
468
|
+
By default, everybody can create application with any scopes. However,
|
|
469
|
+
you can enforce users to create applications only with configured scopes
|
|
470
|
+
(`default_scopes` and `optional_scopes` from the Doorkeeper initializer):
|
|
471
|
+
|
|
472
|
+
```ruby
|
|
473
|
+
# config/initializers/doorkeeper.rb
|
|
474
|
+
Doorkeeper.configure do
|
|
475
|
+
# ...
|
|
476
|
+
|
|
477
|
+
default_scopes :read, :write
|
|
478
|
+
optional_scopes :create, :update
|
|
479
|
+
|
|
480
|
+
enforce_configured_scopes
|
|
481
|
+
end
|
|
482
|
+
```
|
|
483
|
+
|
|
356
484
|
## Other customizations
|
|
357
485
|
|
|
358
486
|
- [Associate users to OAuth applications (ownership)](https://github.com/doorkeeper-gem/doorkeeper/wiki/Associate-users-to-OAuth-applications-%28ownership%29)
|
|
359
487
|
- [CORS - Cross Origin Resource Sharing](https://github.com/doorkeeper-gem/doorkeeper/wiki/%5BCORS%5D-Cross-Origin-Resource-Sharing)
|
|
488
|
+
- see more on [Wiki page](https://github.com/doorkeeper-gem/doorkeeper/wiki)
|
|
489
|
+
|
|
490
|
+
## Testing
|
|
491
|
+
|
|
492
|
+
You can use Doorkeeper models in your application test suite. Note that starting from
|
|
493
|
+
Doorkeeper 4.3.0 it uses [ActiveSupport lazy loading hooks](http://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html)
|
|
494
|
+
to load models. There are [known issue](https://github.com/doorkeeper-gem/doorkeeper/issues/1043)
|
|
495
|
+
with the `factory_bot_rails` gem (it executes factories building before `ActiveRecord::Base`
|
|
496
|
+
is initialized using hooks in gem railtie, so you can catch a `uninitialized constant` error).
|
|
497
|
+
It is recommended to use pure `factory_bot` gem to solve this problem.
|
|
360
498
|
|
|
361
499
|
## Upgrading
|
|
362
500
|
|
|
@@ -373,7 +511,7 @@ To run the local engine server:
|
|
|
373
511
|
|
|
374
512
|
```
|
|
375
513
|
bundle install
|
|
376
|
-
bundle exec
|
|
514
|
+
bundle exec rake doorkeeper:server
|
|
377
515
|
````
|
|
378
516
|
|
|
379
517
|
By default, it uses the latest Rails version with ActiveRecord. To run the
|
|
@@ -383,8 +521,6 @@ tests with a specific ORM and Rails version:
|
|
|
383
521
|
rails=4.2.0 orm=active_record bundle exec rake
|
|
384
522
|
```
|
|
385
523
|
|
|
386
|
-
Or you might prefer to run `script/run_all` to integrate against all ORMs.
|
|
387
|
-
|
|
388
524
|
## Contributing
|
|
389
525
|
|
|
390
526
|
Want to contribute and don't know where to start? Check out [features we're
|
|
@@ -400,7 +536,7 @@ page](https://github.com/doorkeeper-gem/doorkeeper/wiki/Contributing).
|
|
|
400
536
|
|
|
401
537
|
### Wiki
|
|
402
538
|
|
|
403
|
-
You can find everything about
|
|
539
|
+
You can find everything about Doorkeeper in our [wiki
|
|
404
540
|
here](https://github.com/doorkeeper-gem/doorkeeper/wiki).
|
|
405
541
|
|
|
406
542
|
### Screencast
|
|
@@ -422,7 +558,6 @@ here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-your-provider-wi
|
|
|
422
558
|
Thanks to all our [awesome
|
|
423
559
|
contributors](https://github.com/doorkeeper-gem/doorkeeper/graphs/contributors)!
|
|
424
560
|
|
|
425
|
-
|
|
426
561
|
### IETF Standards
|
|
427
562
|
|
|
428
563
|
* [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749)
|
data/Rakefile
CHANGED
|
@@ -15,6 +15,12 @@ namespace :doorkeeper do
|
|
|
15
15
|
cd 'spec/dummy'
|
|
16
16
|
system 'bundle exec rails g doorkeeper:install --force'
|
|
17
17
|
end
|
|
18
|
+
|
|
19
|
+
desc 'Runs local test server'
|
|
20
|
+
task :server do
|
|
21
|
+
cd 'spec/dummy'
|
|
22
|
+
system 'bundle exec rails server'
|
|
23
|
+
end
|
|
18
24
|
end
|
|
19
25
|
|
|
20
26
|
Bundler::GemHelper.install_tasks
|
data/SECURITY.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Reporting security issues in Doorkeeper
|
|
2
|
+
|
|
3
|
+
Hello! Thank you for wanting to disclose a possible security
|
|
4
|
+
vulnerability within the Doorkeeper gem! Please follow our disclosure
|
|
5
|
+
policy as outlined below:
|
|
6
|
+
|
|
7
|
+
1. Do NOT open up a GitHub issue with your report. Security reports
|
|
8
|
+
should be kept private until a possible fix is determined.
|
|
9
|
+
2. Send an email to Nikita Bulai at bulaj.nikita AT gmail.com or one of
|
|
10
|
+
the others Doorkeeper maintainers listed in gemspec. You should receive
|
|
11
|
+
a prompt response.
|
|
12
|
+
3. Be patient. Since Doorkeeper is in a stable maintenance phase, we want to
|
|
13
|
+
do as little as possible to rock the boat of the project.
|
|
14
|
+
|
|
15
|
+
Thank you very much for adhering for these policies!
|
|
@@ -4,12 +4,9 @@ module Doorkeeper
|
|
|
4
4
|
|
|
5
5
|
include Helpers::Controller
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
protect_from_forgery
|
|
9
|
-
else
|
|
7
|
+
unless Doorkeeper.configuration.api_only
|
|
10
8
|
protect_from_forgery with: :exception
|
|
9
|
+
helper 'doorkeeper/dashboard'
|
|
11
10
|
end
|
|
12
|
-
|
|
13
|
-
helper 'doorkeeper/dashboard'
|
|
14
11
|
end
|
|
15
12
|
end
|
|
@@ -5,6 +5,7 @@ module Doorkeeper
|
|
|
5
5
|
AbstractController::Rendering,
|
|
6
6
|
ActionController::Rendering,
|
|
7
7
|
ActionController::Renderers::All,
|
|
8
|
+
AbstractController::Callbacks,
|
|
8
9
|
Helpers::Controller
|
|
9
10
|
].freeze
|
|
10
11
|
|
|
@@ -12,6 +13,9 @@ module Doorkeeper
|
|
|
12
13
|
include mod
|
|
13
14
|
end
|
|
14
15
|
|
|
16
|
+
before_action :enforce_content_type,
|
|
17
|
+
if: -> { Doorkeeper.configuration.enforce_content_type }
|
|
18
|
+
|
|
15
19
|
ActiveSupport.run_load_hooks(:doorkeeper_metal_controller, self)
|
|
16
20
|
end
|
|
17
21
|
end
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
module Doorkeeper
|
|
2
2
|
class ApplicationsController < Doorkeeper::ApplicationController
|
|
3
|
-
layout 'doorkeeper/admin'
|
|
3
|
+
layout 'doorkeeper/admin' unless Doorkeeper.configuration.api_only
|
|
4
4
|
|
|
5
5
|
before_action :authenticate_admin!
|
|
6
|
-
before_action :set_application, only: [
|
|
6
|
+
before_action :set_application, only: %i[show edit update destroy]
|
|
7
7
|
|
|
8
8
|
def index
|
|
9
|
-
@applications = Application.
|
|
9
|
+
@applications = Application.ordered_by(:created_at)
|
|
10
|
+
|
|
11
|
+
respond_to do |format|
|
|
12
|
+
format.html
|
|
13
|
+
format.json { head :no_content }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def show
|
|
18
|
+
respond_to do |format|
|
|
19
|
+
format.html
|
|
20
|
+
format.json { render json: @application }
|
|
21
|
+
end
|
|
10
22
|
end
|
|
11
23
|
|
|
12
24
|
def new
|
|
@@ -15,26 +27,47 @@ module Doorkeeper
|
|
|
15
27
|
|
|
16
28
|
def create
|
|
17
29
|
@application = Application.new(application_params)
|
|
30
|
+
|
|
18
31
|
if @application.save
|
|
19
|
-
flash[:notice] = I18n.t(:notice, scope: [
|
|
20
|
-
|
|
32
|
+
flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
|
|
33
|
+
|
|
34
|
+
respond_to do |format|
|
|
35
|
+
format.html { redirect_to oauth_application_url(@application) }
|
|
36
|
+
format.json { render json: @application }
|
|
37
|
+
end
|
|
21
38
|
else
|
|
22
|
-
|
|
39
|
+
respond_to do |format|
|
|
40
|
+
format.html { render :new }
|
|
41
|
+
format.json { render json: { errors: @application.errors.full_messages }, status: :unprocessable_entity }
|
|
42
|
+
end
|
|
23
43
|
end
|
|
24
44
|
end
|
|
25
45
|
|
|
46
|
+
def edit; end
|
|
47
|
+
|
|
26
48
|
def update
|
|
27
|
-
if @application.
|
|
28
|
-
flash[:notice] = I18n.t(:notice, scope: [
|
|
29
|
-
|
|
49
|
+
if @application.update(application_params)
|
|
50
|
+
flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications update])
|
|
51
|
+
|
|
52
|
+
respond_to do |format|
|
|
53
|
+
format.html { redirect_to oauth_application_url(@application) }
|
|
54
|
+
format.json { render json: @application }
|
|
55
|
+
end
|
|
30
56
|
else
|
|
31
|
-
|
|
57
|
+
respond_to do |format|
|
|
58
|
+
format.html { render :edit }
|
|
59
|
+
format.json { render json: { errors: @application.errors.full_messages }, status: :unprocessable_entity }
|
|
60
|
+
end
|
|
32
61
|
end
|
|
33
62
|
end
|
|
34
63
|
|
|
35
64
|
def destroy
|
|
36
|
-
flash[:notice] = I18n.t(:notice, scope: [
|
|
37
|
-
|
|
65
|
+
flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications destroy]) if @application.destroy
|
|
66
|
+
|
|
67
|
+
respond_to do |format|
|
|
68
|
+
format.html { redirect_to oauth_applications_url }
|
|
69
|
+
format.json { head :no_content }
|
|
70
|
+
end
|
|
38
71
|
end
|
|
39
72
|
|
|
40
73
|
private
|
|
@@ -44,7 +77,8 @@ module Doorkeeper
|
|
|
44
77
|
end
|
|
45
78
|
|
|
46
79
|
def application_params
|
|
47
|
-
params.require(:doorkeeper_application).
|
|
80
|
+
params.require(:doorkeeper_application).
|
|
81
|
+
permit(:name, :redirect_uri, :scopes, :confidential)
|
|
48
82
|
end
|
|
49
83
|
end
|
|
50
84
|
end
|
|
@@ -4,20 +4,15 @@ module Doorkeeper
|
|
|
4
4
|
|
|
5
5
|
def new
|
|
6
6
|
if pre_auth.authorizable?
|
|
7
|
-
|
|
8
|
-
auth = authorization.authorize
|
|
9
|
-
redirect_to auth.redirect_uri
|
|
10
|
-
else
|
|
11
|
-
render :new
|
|
12
|
-
end
|
|
7
|
+
render_success
|
|
13
8
|
else
|
|
14
|
-
|
|
9
|
+
render_error
|
|
15
10
|
end
|
|
16
11
|
end
|
|
17
12
|
|
|
18
13
|
# TODO: Handle raise invalid authorization
|
|
19
14
|
def create
|
|
20
|
-
redirect_or_render
|
|
15
|
+
redirect_or_render authorize_response
|
|
21
16
|
end
|
|
22
17
|
|
|
23
18
|
def destroy
|
|
@@ -26,15 +21,45 @@ module Doorkeeper
|
|
|
26
21
|
|
|
27
22
|
private
|
|
28
23
|
|
|
24
|
+
def render_success
|
|
25
|
+
if skip_authorization? || matching_token?
|
|
26
|
+
redirect_or_render authorize_response
|
|
27
|
+
elsif Doorkeeper.configuration.api_only
|
|
28
|
+
render json: pre_auth
|
|
29
|
+
else
|
|
30
|
+
render :new
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render_error
|
|
35
|
+
if Doorkeeper.configuration.api_only
|
|
36
|
+
render json: pre_auth.error_response.body[:error_description],
|
|
37
|
+
status: :bad_request
|
|
38
|
+
else
|
|
39
|
+
render :error
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
29
43
|
def matching_token?
|
|
30
|
-
AccessToken.matching_token_for
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
token = AccessToken.matching_token_for(
|
|
45
|
+
pre_auth.client,
|
|
46
|
+
current_resource_owner.id,
|
|
47
|
+
pre_auth.scopes
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
token && token.accessible?
|
|
33
51
|
end
|
|
34
52
|
|
|
35
53
|
def redirect_or_render(auth)
|
|
36
54
|
if auth.redirectable?
|
|
37
|
-
|
|
55
|
+
if Doorkeeper.configuration.api_only
|
|
56
|
+
render(
|
|
57
|
+
json: { status: :redirect, redirect_uri: auth.redirect_uri },
|
|
58
|
+
status: auth.status
|
|
59
|
+
)
|
|
60
|
+
else
|
|
61
|
+
redirect_to auth.redirect_uri
|
|
62
|
+
end
|
|
38
63
|
else
|
|
39
64
|
render json: auth.body, status: auth.status
|
|
40
65
|
end
|
|
@@ -53,5 +78,23 @@ module Doorkeeper
|
|
|
53
78
|
def strategy
|
|
54
79
|
@strategy ||= server.authorization_request pre_auth.response_type
|
|
55
80
|
end
|
|
81
|
+
|
|
82
|
+
def authorize_response
|
|
83
|
+
@authorize_response ||= begin
|
|
84
|
+
authorizable = pre_auth.authorizable?
|
|
85
|
+
before_successful_authorization if authorizable
|
|
86
|
+
auth = strategy.authorize
|
|
87
|
+
after_successful_authorization if authorizable
|
|
88
|
+
auth
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def after_successful_authorization
|
|
93
|
+
Doorkeeper.configuration.after_successful_authorization.call(self)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def before_successful_authorization
|
|
97
|
+
Doorkeeper.configuration.before_successful_authorization.call(self)
|
|
98
|
+
end
|
|
56
99
|
end
|
|
57
100
|
end
|
|
@@ -4,11 +4,25 @@ module Doorkeeper
|
|
|
4
4
|
|
|
5
5
|
def index
|
|
6
6
|
@applications = Application.authorized_for(current_resource_owner)
|
|
7
|
+
|
|
8
|
+
respond_to do |format|
|
|
9
|
+
format.html
|
|
10
|
+
format.json { render json: @applications }
|
|
11
|
+
end
|
|
7
12
|
end
|
|
8
13
|
|
|
9
14
|
def destroy
|
|
10
15
|
AccessToken.revoke_all_for params[:id], current_resource_owner
|
|
11
|
-
|
|
16
|
+
|
|
17
|
+
respond_to do |format|
|
|
18
|
+
format.html do
|
|
19
|
+
redirect_to oauth_authorized_applications_url, notice: I18n.t(
|
|
20
|
+
:notice, scope: %i[doorkeeper flash authorized_applications destroy]
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
format.json { render :no_content }
|
|
25
|
+
end
|
|
12
26
|
end
|
|
13
27
|
end
|
|
14
28
|
end
|