doorkeeper 3.1.0 → 4.4.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +6 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +26 -10
- data/Appraisals +18 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -5
- data/NEWS.md +141 -2
- data/README.md +149 -66
- data/RELEASING.md +5 -12
- data/Rakefile +1 -1
- data/SECURITY.md +15 -0
- data/app/controllers/doorkeeper/application_controller.rb +4 -6
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +18 -8
- data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
- data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
- data/app/validators/redirect_uri_validator.rb +12 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/applications/_form.html.erb +13 -2
- data/app/views/doorkeeper/applications/index.html.erb +2 -0
- data/app/views/doorkeeper/applications/show.html.erb +4 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
- data/config/locales/en.yml +12 -7
- data/doorkeeper.gemspec +16 -11
- data/gemfiles/rails_4_2.gemfile +13 -0
- data/gemfiles/rails_5_0.gemfile +12 -0
- data/gemfiles/rails_5_1.gemfile +12 -0
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +119 -46
- data/lib/doorkeeper/engine.rb +11 -7
- data/lib/doorkeeper/errors.rb +18 -0
- data/lib/doorkeeper/grape/helpers.rb +14 -8
- data/lib/doorkeeper/helpers/controller.rb +8 -19
- data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
- data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
- data/lib/doorkeeper/models/application_mixin.rb +33 -35
- data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
- data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
- data/lib/doorkeeper/oauth/base_response.rb +29 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
- data/lib/doorkeeper/oauth/client.rb +2 -3
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
- data/lib/doorkeeper/oauth/code_response.rb +16 -16
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +10 -10
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
- data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
- data/lib/doorkeeper/oauth/scopes.rb +18 -8
- data/lib/doorkeeper/oauth/token.rb +20 -21
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_request.rb +1 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
- data/lib/doorkeeper/orm/active_record/application.rb +48 -11
- data/lib/doorkeeper/orm/active_record.rb +17 -22
- data/lib/doorkeeper/rails/helpers.rb +6 -9
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
- data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +17 -11
- data/lib/doorkeeper/request/authorization_code.rb +7 -1
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request.rb +7 -1
- data/lib/doorkeeper/server.rb +0 -8
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +34 -1
- data/lib/doorkeeper.rb +10 -2
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
- data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
- data/lib/generators/doorkeeper/migration_generator.rb +13 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
- data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
- data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
- data/spec/controllers/application_metal_controller.rb +10 -0
- data/spec/controllers/applications_controller_spec.rb +15 -4
- data/spec/controllers/authorizations_controller_spec.rb +74 -27
- data/spec/controllers/protected_resources_controller_spec.rb +70 -32
- data/spec/controllers/token_info_controller_spec.rb +17 -13
- data/spec/controllers/tokens_controller_spec.rb +198 -12
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
- data/spec/dummy/app/controllers/home_controller.rb +1 -1
- data/spec/dummy/app/controllers/metal_controller.rb +1 -1
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
- data/spec/dummy/app/models/user.rb +0 -4
- data/spec/dummy/config/application.rb +2 -36
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +4 -15
- data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
- data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
- data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
- data/spec/dummy/db/schema.rb +24 -22
- data/spec/factories.rb +4 -2
- data/spec/generators/application_owner_generator_spec.rb +24 -5
- data/spec/generators/migration_generator_spec.rb +24 -3
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +159 -14
- data/spec/lib/doorkeeper_spec.rb +135 -13
- data/spec/lib/models/expirable_spec.rb +0 -1
- data/spec/lib/models/revocable_spec.rb +27 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
- data/spec/lib/oauth/base_request_spec.rb +155 -0
- data/spec/lib/oauth/base_response_spec.rb +45 -0
- data/spec/lib/oauth/client/credentials_spec.rb +45 -2
- data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
- data/spec/lib/oauth/code_request_spec.rb +1 -3
- data/spec/lib/oauth/code_response_spec.rb +34 -0
- data/spec/lib/oauth/error_response_spec.rb +9 -9
- data/spec/lib/oauth/error_spec.rb +1 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
- data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
- data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
- data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
- data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
- data/spec/lib/oauth/scopes_spec.rb +28 -2
- data/spec/lib/oauth/token_request_spec.rb +6 -8
- data/spec/lib/oauth/token_spec.rb +12 -5
- data/spec/lib/server_spec.rb +10 -3
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +116 -48
- data/spec/models/doorkeeper/application_spec.rb +145 -29
- data/spec/requests/applications/applications_request_spec.rb +5 -5
- data/spec/requests/endpoints/authorization_spec.rb +5 -6
- data/spec/requests/endpoints/token_spec.rb +8 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
- data/spec/requests/flows/authorization_code_spec.rb +6 -13
- data/spec/requests/flows/client_credentials_spec.rb +29 -1
- data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
- data/spec/requests/flows/password_spec.rb +118 -15
- data/spec/requests/flows/refresh_token_spec.rb +89 -19
- data/spec/requests/flows/revoke_token_spec.rb +105 -91
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/routing/default_routes_spec.rb +5 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helper_integration.rb +22 -4
- data/spec/support/dependencies/factory_girl.rb +2 -2
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/model_helper.rb +34 -7
- data/spec/support/helpers/request_spec_helper.rb +17 -5
- data/spec/support/helpers/url_helper.rb +9 -8
- data/spec/support/http_method_shim.rb +38 -0
- data/spec/support/shared/controllers_shared_context.rb +15 -10
- data/spec/support/shared/models_shared_examples.rb +5 -5
- data/spec/validators/redirect_uri_validator_spec.rb +51 -6
- data/spec/version/version_spec.rb +15 -0
- metadata +128 -46
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
data/README.md
CHANGED
@@ -1,58 +1,74 @@
|
|
1
|
-
# Doorkeeper - awesome
|
1
|
+
# Doorkeeper - awesome OAuth 2 provider for your Rails app.
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/doorkeeper-gem/doorkeeper.svg?branch=master)](https://travis-ci.org/doorkeeper-gem/doorkeeper)
|
4
|
-
[![Dependency Status](https://gemnasium.com/applicake/doorkeeper.svg?travis)](https://gemnasium.com/applicake/doorkeeper)
|
5
|
-
[![Code Climate](https://codeclimate.com/github/applicake/doorkeeper.svg)](https://codeclimate.com/github/applicake/doorkeeper)
|
6
3
|
[![Gem Version](https://badge.fury.io/rb/doorkeeper.svg)](https://rubygems.org/gems/doorkeeper)
|
4
|
+
[![Build Status](https://travis-ci.org/doorkeeper-gem/doorkeeper.svg?branch=master)](https://travis-ci.org/doorkeeper-gem/doorkeeper)
|
5
|
+
[![Dependency Status](https://gemnasium.com/doorkeeper-gem/doorkeeper.svg?travis)](https://gemnasium.com/doorkeeper-gem/doorkeeper)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/doorkeeper-gem/doorkeeper.svg)](https://codeclimate.com/github/doorkeeper-gem/doorkeeper)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/github/doorkeeper-gem/doorkeeper/badge.svg?branch=master)](https://coveralls.io/github/doorkeeper-gem/doorkeeper?branch=master)
|
8
|
+
[![Security](https://hakiri.io/github/doorkeeper-gem/doorkeeper/master.svg)](https://hakiri.io/github/doorkeeper-gem/doorkeeper/master)
|
7
9
|
|
8
10
|
Doorkeeper is a gem that makes it easy to introduce OAuth 2 provider
|
9
11
|
functionality to your Rails or Grape application.
|
10
12
|
|
11
|
-
|
13
|
+
Supported features:
|
12
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
|
+
- [OAuth 2.0 Token Revocation](http://tools.ietf.org/html/rfc7009)
|
23
|
+
- [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662)
|
13
24
|
|
14
25
|
## Documentation valid for `master` branch
|
15
26
|
|
16
27
|
Please check the documentation for the version of doorkeeper you are using in:
|
17
28
|
https://github.com/doorkeeper-gem/doorkeeper/releases
|
18
29
|
|
30
|
+
- See the [wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki)
|
31
|
+
- For general questions, please post in [Stack Overflow](http://stackoverflow.com/questions/tagged/doorkeeper)
|
32
|
+
- See [SECURITY.md](SECURITY.md) for this project's security disclose
|
33
|
+
policy
|
34
|
+
|
19
35
|
## Table of Contents
|
20
36
|
|
21
37
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
22
38
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
23
|
-
|
39
|
+
|
24
40
|
- [Installation](#installation)
|
25
41
|
- [Configuration](#configuration)
|
42
|
+
- [ORM](#orm)
|
26
43
|
- [Active Record](#active-record)
|
27
|
-
- [
|
28
|
-
- [
|
29
|
-
- [
|
30
|
-
|
44
|
+
- [MongoDB](#mongodb)
|
45
|
+
- [Sequel](#sequel)
|
46
|
+
- [Couchbase](#couchbase)
|
47
|
+
- [Routes](#routes)
|
48
|
+
- [Authenticating](#authenticating)
|
49
|
+
- [Internationalization (I18n)](#internationalization-i18n)
|
31
50
|
- [Protecting resources with OAuth (a.k.a your API endpoint)](#protecting-resources-with-oauth-aka-your-api-endpoint)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
51
|
+
- [Ruby on Rails controllers](#ruby-on-rails-controllers)
|
52
|
+
- [Grape endpoints](#grape-endpoints)
|
53
|
+
- [Route Constraints and other integrations](#route-constraints-and-other-integrations)
|
54
|
+
- [Access Token Scopes](#access-token-scopes)
|
55
|
+
- [Custom Access Token Generator](#custom-access-token-generator)
|
56
|
+
- [Authenticated resource owner](#authenticated-resource-owner)
|
57
|
+
- [Applications list](#applications-list)
|
38
58
|
- [Other customizations](#other-customizations)
|
59
|
+
- [Testing](#testing)
|
39
60
|
- [Upgrading](#upgrading)
|
40
61
|
- [Development](#development)
|
41
62
|
- [Contributing](#contributing)
|
42
63
|
- [Other resources](#other-resources)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
50
|
-
|
64
|
+
- [Wiki](#wiki)
|
65
|
+
- [Screencast](#screencast)
|
66
|
+
- [Client applications](#client-applications)
|
67
|
+
- [Contributors](#contributors)
|
68
|
+
- [IETF Standards](#ietf-standards)
|
69
|
+
- [License](#license)
|
51
70
|
|
52
|
-
|
53
|
-
|
54
|
-
- For documentation, please check out our [wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki)
|
55
|
-
- For general questions, please post it in [stack overflow](http://stackoverflow.com/questions/tagged/doorkeeper)
|
71
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
56
72
|
|
57
73
|
## Installation
|
58
74
|
|
@@ -70,24 +86,66 @@ This will install the doorkeeper initializer into `config/initializers/doorkeepe
|
|
70
86
|
|
71
87
|
## Configuration
|
72
88
|
|
73
|
-
###
|
89
|
+
### ORM
|
90
|
+
|
91
|
+
#### Active Record
|
74
92
|
|
75
|
-
By default doorkeeper is configured to use
|
76
|
-
to generate the migration tables:
|
93
|
+
By default doorkeeper is configured to use Active Record, so to start you have
|
94
|
+
to generate the migration tables (supports Rails >= 5 migrations versioning):
|
77
95
|
|
78
96
|
rails generate doorkeeper:migration
|
79
97
|
|
80
|
-
|
98
|
+
You may want to add foreign keys to your migration. For example, if you plan on
|
99
|
+
using `User` as the resource owner, add the following line to the migration file
|
100
|
+
for each table that includes a `resource_owner_id` column:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
add_foreign_key :table_name, :users, column: :resource_owner_id
|
104
|
+
```
|
105
|
+
|
106
|
+
Then run migrations:
|
81
107
|
|
82
|
-
|
108
|
+
```sh
|
109
|
+
rake db:migrate
|
110
|
+
```
|
83
111
|
|
84
|
-
|
112
|
+
Remember to add associations to your model so the related records are deleted.
|
113
|
+
If you don't do this an `ActiveRecord::InvalidForeignKey`-error will be raised
|
114
|
+
when you try to destroy a model with related access grants or access tokens.
|
85
115
|
|
86
|
-
|
116
|
+
```ruby
|
117
|
+
class User < ApplicationRecord
|
118
|
+
has_many :access_grants, class_name: "Doorkeeper::AccessGrant",
|
119
|
+
foreign_key: :resource_owner_id,
|
120
|
+
dependent: :delete_all # or :destroy if you need callbacks
|
121
|
+
|
122
|
+
has_many :access_tokens, class_name: "Doorkeeper::AccessToken",
|
123
|
+
foreign_key: :resource_owner_id,
|
124
|
+
dependent: :delete_all # or :destroy if you need callbacks
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
#### MongoDB
|
129
|
+
|
130
|
+
See [doorkeeper-mongodb project] for Mongoid and MongoMapper support. Follow along
|
87
131
|
the implementation in that repository to extend doorkeeper with other ORMs.
|
88
132
|
|
89
133
|
[doorkeeper-mongodb project]: https://github.com/doorkeeper-gem/doorkeeper-mongodb
|
90
134
|
|
135
|
+
#### Sequel
|
136
|
+
|
137
|
+
If you are using [Sequel gem] then you can add [doorkeeper-sequel extension] to your project.
|
138
|
+
Follow configuration instructions for setting up the necessary Doorkeeper ORM.
|
139
|
+
|
140
|
+
[Sequel gem]: https://github.com/jeremyevans/sequel/
|
141
|
+
[doorkeeper-sequel extension]: https://github.com/nbulaj/doorkeeper-sequel
|
142
|
+
|
143
|
+
#### Couchbase
|
144
|
+
|
145
|
+
Use [doorkeeper-couchbase] extension if you are using Couchbase database.
|
146
|
+
|
147
|
+
[doorkeeper-couchbase]: https://github.com/acaprojects/doorkeeper-couchbase
|
148
|
+
|
91
149
|
### Routes
|
92
150
|
|
93
151
|
The installation script will also automatically add the Doorkeeper routes into
|
@@ -102,12 +160,13 @@ end
|
|
102
160
|
|
103
161
|
This will mount following routes:
|
104
162
|
|
105
|
-
GET /oauth/authorize
|
163
|
+
GET /oauth/authorize/native?code
|
106
164
|
GET /oauth/authorize
|
107
165
|
POST /oauth/authorize
|
108
166
|
DELETE /oauth/authorize
|
109
167
|
POST /oauth/token
|
110
168
|
POST /oauth/revoke
|
169
|
+
POST /oauth/introspect
|
111
170
|
resources /oauth/applications
|
112
171
|
GET /oauth/authorized_applications
|
113
172
|
DELETE /oauth/authorized_applications/:id
|
@@ -119,12 +178,12 @@ wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
|
|
119
178
|
### Authenticating
|
120
179
|
|
121
180
|
You need to configure Doorkeeper in order to provide `resource_owner` model
|
122
|
-
and authentication block `initializers/doorkeeper.rb
|
181
|
+
and authentication block in `config/initializers/doorkeeper.rb`:
|
123
182
|
|
124
183
|
``` ruby
|
125
184
|
Doorkeeper.configure do
|
126
185
|
resource_owner_authenticator do
|
127
|
-
User.
|
186
|
+
User.find_by(id: session[:current_user_id]) || redirect_to(login_url)
|
128
187
|
end
|
129
188
|
end
|
130
189
|
```
|
@@ -137,16 +196,17 @@ the methods defined over there.
|
|
137
196
|
You may want to check other ways of authentication
|
138
197
|
[here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Authenticating-using-Clearance-or-DIY).
|
139
198
|
|
140
|
-
|
141
199
|
### Internationalization (I18n)
|
142
200
|
|
143
201
|
See language files in [the I18n repository](https://github.com/doorkeeper-gem/doorkeeper-i18n).
|
144
202
|
|
145
|
-
|
146
203
|
## Protecting resources with OAuth (a.k.a your API endpoint)
|
147
204
|
|
148
|
-
|
149
|
-
|
205
|
+
### Ruby on Rails controllers
|
206
|
+
|
207
|
+
To protect your controllers (usual one or `ActionController::API`) with OAuth,
|
208
|
+
you just need to setup `before_action`s specifying the actions you want to
|
209
|
+
protect. For example:
|
150
210
|
|
151
211
|
``` ruby
|
152
212
|
class Api::V1::ProductsController < Api::V1::ApiController
|
@@ -159,16 +219,17 @@ end
|
|
159
219
|
You can pass any option `before_action` accepts, such as `if`, `only`,
|
160
220
|
`except`, and others.
|
161
221
|
|
162
|
-
###
|
222
|
+
### Grape endpoints
|
163
223
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
`helpers
|
224
|
+
Starting from version 2.2 Doorkeeper provides helpers for the
|
225
|
+
[Grape framework] >= 0.10. One of them is `doorkeeper_authorize!` that
|
226
|
+
can be used in a similar way as an example above to protect your API
|
227
|
+
with OAuth. Note that you have to use `require 'doorkeeper/grape/helpers'`
|
228
|
+
and `helpers Doorkeeper::Grape::Helpers` in your Grape API class.
|
168
229
|
|
169
230
|
For more information about integration with Grape see the [Wiki].
|
170
231
|
|
171
|
-
[
|
232
|
+
[Grape framework]: https://github.com/ruby-grape/grape
|
172
233
|
[Wiki]: https://github.com/doorkeeper-gem/doorkeeper/wiki/Grape-Integration
|
173
234
|
|
174
235
|
``` ruby
|
@@ -183,13 +244,17 @@ module API
|
|
183
244
|
doorkeeper_authorize!
|
184
245
|
end
|
185
246
|
|
247
|
+
# route_setting :scopes, ['user:email'] - for old versions of Grape
|
248
|
+
get :emails, scopes: [:user, :write] do
|
249
|
+
[{'email' => current_user.email}]
|
250
|
+
end
|
251
|
+
|
186
252
|
# ...
|
187
253
|
end
|
188
254
|
end
|
189
255
|
end
|
190
256
|
```
|
191
257
|
|
192
|
-
|
193
258
|
### Route Constraints and other integrations
|
194
259
|
|
195
260
|
You can leverage the `Doorkeeper.authenticate` facade to easily extract a
|
@@ -204,7 +269,6 @@ module Constraint
|
|
204
269
|
token = Doorkeeper.authenticate(request)
|
205
270
|
token && token.accessible?
|
206
271
|
end
|
207
|
-
|
208
272
|
end
|
209
273
|
end
|
210
274
|
```
|
@@ -238,13 +302,13 @@ class Api::V1::ProductsController < Api::V1::ApiController
|
|
238
302
|
end
|
239
303
|
```
|
240
304
|
|
241
|
-
Please note that there is a logical OR between multiple required scopes. In
|
305
|
+
Please note that there is a logical OR between multiple required scopes. In the
|
242
306
|
above example, `doorkeeper_authorize! :admin, :write` means that the access
|
243
|
-
token is required to have either `:admin` scope or `:write` scope, but not
|
244
|
-
have both of them.
|
307
|
+
token is required to have either `:admin` scope or `:write` scope, but does not
|
308
|
+
need have both of them.
|
245
309
|
|
246
|
-
If want to require the access token to have multiple scopes at the same
|
247
|
-
use multiple `doorkeeper_authorize!`, for example:
|
310
|
+
If you want to require the access token to have multiple scopes at the same
|
311
|
+
time, use multiple `doorkeeper_authorize!`, for example:
|
248
312
|
|
249
313
|
```ruby
|
250
314
|
class Api::V1::ProductsController < Api::V1::ApiController
|
@@ -256,8 +320,8 @@ class Api::V1::ProductsController < Api::V1::ApiController
|
|
256
320
|
end
|
257
321
|
```
|
258
322
|
|
259
|
-
In above example, a client can call `:create` action only if its access token
|
260
|
-
|
323
|
+
In the above example, a client can call `:create` action only if its access token
|
324
|
+
has both `:admin` and `:write` scopes.
|
261
325
|
|
262
326
|
### Custom Access Token Generator
|
263
327
|
|
@@ -274,6 +338,18 @@ end
|
|
274
338
|
JWT token support is available with
|
275
339
|
[Doorkeeper-JWT](https://github.com/chriswarren/doorkeeper-jwt).
|
276
340
|
|
341
|
+
### Custom Base Controller
|
342
|
+
|
343
|
+
By default Doorkeeper's main controller `Doorkeeper::ApplicationController`
|
344
|
+
inherits from `ActionController::Base`. You may want to use your own
|
345
|
+
controller to inherit from, to keep Doorkeeper controllers in the same
|
346
|
+
context than the rest your app:
|
347
|
+
|
348
|
+
```ruby
|
349
|
+
Doorkeeper.configure do
|
350
|
+
base_controller 'ApplicationController'
|
351
|
+
end
|
352
|
+
```
|
277
353
|
|
278
354
|
### Authenticated resource owner
|
279
355
|
|
@@ -305,28 +381,38 @@ token owner.
|
|
305
381
|
|
306
382
|
### Applications list
|
307
383
|
|
308
|
-
By default, the applications list (`/oauth/applications`) is
|
384
|
+
By default, the applications list (`/oauth/applications`) is publicly available.
|
309
385
|
To protect the endpoint you should uncomment these lines:
|
310
386
|
|
311
387
|
```ruby
|
312
388
|
# config/initializers/doorkeeper.rb
|
313
389
|
Doorkeeper.configure do
|
314
390
|
admin_authenticator do |routes|
|
315
|
-
Admin.
|
391
|
+
Admin.find_by(id: session[:admin_id]) || redirect_to(routes.new_admin_session_url)
|
316
392
|
end
|
317
393
|
end
|
318
394
|
```
|
319
395
|
|
320
396
|
The logic is the same as the `resource_owner_authenticator` block. **Note:**
|
321
397
|
since the application list is just a scaffold, it's recommended to either
|
322
|
-
customize the controller used by the list or skip the controller
|
323
|
-
more information see the page
|
324
|
-
wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
|
398
|
+
customize the controller used by the list or skip the controller all together.
|
399
|
+
For more information see the page
|
400
|
+
[in the wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
|
325
401
|
|
326
402
|
## Other customizations
|
327
403
|
|
328
404
|
- [Associate users to OAuth applications (ownership)](https://github.com/doorkeeper-gem/doorkeeper/wiki/Associate-users-to-OAuth-applications-%28ownership%29)
|
329
405
|
- [CORS - Cross Origin Resource Sharing](https://github.com/doorkeeper-gem/doorkeeper/wiki/%5BCORS%5D-Cross-Origin-Resource-Sharing)
|
406
|
+
- see more on [Wiki page](https://github.com/doorkeeper-gem/doorkeeper/wiki)
|
407
|
+
|
408
|
+
## Testing
|
409
|
+
|
410
|
+
You can use Doorkeeper models in your application test suite. Note that starting from
|
411
|
+
Doorkeeper 4.3.0 it uses [ActiveSupport lazy loading hooks](http://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html)
|
412
|
+
to load models. There are [known issue](https://github.com/doorkeeper-gem/doorkeeper/issues/1043)
|
413
|
+
with the `factory_bot_rails` gem (it executes factories building before `ActiveRecord::Base`
|
414
|
+
is initialized using hooks in gem railtie, so you can catch a `uninitialized constant` error).
|
415
|
+
It is recommended to use pure `factory_bot` gem to solve this problem.
|
330
416
|
|
331
417
|
## Upgrading
|
332
418
|
|
@@ -353,8 +439,6 @@ tests with a specific ORM and Rails version:
|
|
353
439
|
rails=4.2.0 orm=active_record bundle exec rake
|
354
440
|
```
|
355
441
|
|
356
|
-
Or you might prefer to run `script/run_all` to integrate against all ORMs.
|
357
|
-
|
358
442
|
## Contributing
|
359
443
|
|
360
444
|
Want to contribute and don't know where to start? Check out [features we're
|
@@ -370,7 +454,7 @@ page](https://github.com/doorkeeper-gem/doorkeeper/wiki/Contributing).
|
|
370
454
|
|
371
455
|
### Wiki
|
372
456
|
|
373
|
-
You can find everything about
|
457
|
+
You can find everything about Doorkeeper in our [wiki
|
374
458
|
here](https://github.com/doorkeeper-gem/doorkeeper/wiki).
|
375
459
|
|
376
460
|
### Screencast
|
@@ -392,7 +476,6 @@ here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-your-provider-wi
|
|
392
476
|
Thanks to all our [awesome
|
393
477
|
contributors](https://github.com/doorkeeper-gem/doorkeeper/graphs/contributors)!
|
394
478
|
|
395
|
-
|
396
479
|
### IETF Standards
|
397
480
|
|
398
481
|
* [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749)
|
data/RELEASING.md
CHANGED
@@ -1,17 +1,10 @@
|
|
1
1
|
# Releasing doorkeeper
|
2
2
|
|
3
|
+
How to release doorkeeper in five easy steps!
|
4
|
+
|
3
5
|
1. Update `lib/doorkeeper/version.rb` file accordingly.
|
4
6
|
2. Update `NEWS.md` to reflect the changes since last release.
|
5
|
-
3. Commit changes
|
6
|
-
|
7
|
-
|
8
|
-
5. Push changes: `git push && git push --tags`
|
9
|
-
6. Build and publish the gem:
|
10
|
-
|
11
|
-
```bash
|
12
|
-
gem build doorkeeper.gemspec
|
13
|
-
gem push doorkeeper-*.gem
|
14
|
-
```
|
15
|
-
|
16
|
-
7. Announce the new release, making sure to say “thank you” to the contributors
|
7
|
+
3. Commit changes: `git commit -am 'Bump to vVERSION'`
|
8
|
+
4. Run `rake release`
|
9
|
+
5. Announce the new release, making sure to say “thank you” to the contributors
|
17
10
|
who helped shape this version!
|
data/Rakefile
CHANGED
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!
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module Doorkeeper
|
2
|
-
class ApplicationController <
|
2
|
+
class ApplicationController <
|
3
|
+
Doorkeeper.configuration.base_controller.constantize
|
4
|
+
|
3
5
|
include Helpers::Controller
|
4
6
|
|
5
|
-
|
6
|
-
protect_from_forgery
|
7
|
-
else
|
8
|
-
protect_from_forgery with: :exception
|
9
|
-
end
|
7
|
+
protect_from_forgery with: :exception
|
10
8
|
|
11
9
|
helper 'doorkeeper/dashboard'
|
12
10
|
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
class ApplicationMetalController < ActionController::Metal
|
3
3
|
MODULES = [
|
4
|
-
ActionController::RackDelegation,
|
5
4
|
ActionController::Instrumentation,
|
6
5
|
AbstractController::Rendering,
|
7
6
|
ActionController::Rendering,
|
8
7
|
ActionController::Renderers::All,
|
9
8
|
Helpers::Controller
|
10
|
-
]
|
9
|
+
].freeze
|
11
10
|
|
12
11
|
MODULES.each do |mod|
|
13
12
|
include mod
|
14
13
|
end
|
14
|
+
|
15
|
+
ActiveSupport.run_load_hooks(:doorkeeper_metal_controller, self)
|
15
16
|
end
|
16
17
|
end
|
@@ -2,13 +2,24 @@ module Doorkeeper
|
|
2
2
|
class ApplicationsController < Doorkeeper::ApplicationController
|
3
3
|
layout 'doorkeeper/admin'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
before_action :authenticate_admin!
|
6
|
+
before_action :set_application, only: [:show, :edit, :update, :destroy]
|
7
7
|
|
8
8
|
def index
|
9
|
-
@applications = Application.
|
9
|
+
@applications = if Application.respond_to?(:ordered_by)
|
10
|
+
Application.ordered_by(:created_at)
|
11
|
+
else
|
12
|
+
ActiveSupport::Deprecation.warn <<-MSG.squish
|
13
|
+
Doorkeeper #{Doorkeeper.configuration.orm} extension must implement #ordered_by
|
14
|
+
method for it's models as it will be used by default in Doorkeeper 5.
|
15
|
+
MSG
|
16
|
+
|
17
|
+
Application.all
|
18
|
+
end
|
10
19
|
end
|
11
20
|
|
21
|
+
def show; end
|
22
|
+
|
12
23
|
def new
|
13
24
|
@application = Application.new
|
14
25
|
end
|
@@ -23,6 +34,8 @@ module Doorkeeper
|
|
23
34
|
end
|
24
35
|
end
|
25
36
|
|
37
|
+
def edit; end
|
38
|
+
|
26
39
|
def update
|
27
40
|
if @application.update_attributes(application_params)
|
28
41
|
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :update])
|
@@ -44,11 +57,8 @@ module Doorkeeper
|
|
44
57
|
end
|
45
58
|
|
46
59
|
def application_params
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
params[:doorkeeper_application].slice(:name, :redirect_uri, :scopes) rescue nil
|
51
|
-
end
|
60
|
+
params.require(:doorkeeper_application).
|
61
|
+
permit(:name, :redirect_uri, :scopes, :confidential)
|
52
62
|
end
|
53
63
|
end
|
54
64
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
class AuthorizedApplicationsController < Doorkeeper::ApplicationController
|
3
|
-
|
3
|
+
before_action :authenticate_resource_owner!
|
4
4
|
|
5
5
|
def index
|
6
6
|
@applications = Application.authorized_for(current_resource_owner)
|
@@ -2,38 +2,85 @@ module Doorkeeper
|
|
2
2
|
class TokensController < Doorkeeper::ApplicationMetalController
|
3
3
|
def create
|
4
4
|
response = authorize_response
|
5
|
-
|
5
|
+
headers.merge! response.headers
|
6
6
|
self.response_body = response.body.to_json
|
7
|
-
self.status
|
7
|
+
self.status = response.status
|
8
8
|
rescue Errors::DoorkeeperError => e
|
9
9
|
handle_token_exception e
|
10
10
|
end
|
11
11
|
|
12
12
|
# OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
|
13
13
|
def revoke
|
14
|
-
# The authorization server first
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
# The authorization server, if applicable, first authenticates the client
|
15
|
+
# and checks its ownership of the provided token.
|
16
|
+
#
|
17
|
+
# Doorkeeper does not use the token_type_hint logic described in the
|
18
|
+
# RFC 7009 due to the refresh token implementation that is a field in
|
19
|
+
# the access token model.
|
20
|
+
if authorized?
|
21
|
+
revoke_token
|
19
22
|
end
|
20
|
-
|
21
|
-
#
|
23
|
+
|
24
|
+
# The authorization server responds with HTTP status code 200 if the token
|
25
|
+
# has been revoked successfully or if the client submitted an invalid
|
26
|
+
# token
|
22
27
|
render json: {}, status: 200
|
23
28
|
end
|
24
29
|
|
30
|
+
def introspect
|
31
|
+
introspection = OAuth::TokenIntrospection.new(server, token)
|
32
|
+
|
33
|
+
if introspection.authorized?
|
34
|
+
render json: introspection.to_json, status: 200
|
35
|
+
else
|
36
|
+
error = OAuth::ErrorResponse.new(name: introspection.error)
|
37
|
+
response.headers.merge!(error.headers)
|
38
|
+
render json: error.body, status: error.status
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
25
42
|
private
|
26
43
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
44
|
+
# OAuth 2.0 Section 2.1 defines two client types, "public" & "confidential".
|
45
|
+
# Public clients (as per RFC 7009) do not require authentication whereas
|
46
|
+
# confidential clients must be authenticated for their token revocation.
|
47
|
+
#
|
48
|
+
# Once a confidential client is authenticated, it must be authorized to
|
49
|
+
# revoke the provided access or refresh token. This ensures one client
|
50
|
+
# cannot revoke another's tokens.
|
51
|
+
#
|
52
|
+
# Doorkeeper determines the client type implicitly via the presence of the
|
53
|
+
# OAuth client associated with a given access or refresh token. Since public
|
54
|
+
# clients authenticate the resource owner via "password" or "implicit" grant
|
55
|
+
# types, they set the application_id as null (since the claim cannot be
|
56
|
+
# verified).
|
57
|
+
#
|
58
|
+
# https://tools.ietf.org/html/rfc6749#section-2.1
|
59
|
+
# https://tools.ietf.org/html/rfc7009
|
60
|
+
def authorized?
|
61
|
+
return unless token.present?
|
62
|
+
# Client is confidential, therefore client authentication & authorization
|
63
|
+
# is required
|
64
|
+
if token.application_id? && token.application.confidential?
|
65
|
+
# We authorize client by checking token's application
|
66
|
+
server.client && server.client.application == token.application
|
32
67
|
else
|
33
|
-
|
68
|
+
# Client is public, authentication unnecessary
|
69
|
+
true
|
34
70
|
end
|
35
71
|
end
|
36
72
|
|
73
|
+
def revoke_token
|
74
|
+
if token.accessible?
|
75
|
+
token.revoke
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def token
|
80
|
+
@token ||= AccessToken.by_token(request.POST['token']) ||
|
81
|
+
AccessToken.by_refresh_token(request.POST['token'])
|
82
|
+
end
|
83
|
+
|
37
84
|
def strategy
|
38
85
|
@strategy ||= server.token_request params[:grant_type]
|
39
86
|
end
|