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.

Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +25 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  5. data/.gitignore +6 -1
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +26 -10
  9. data/Appraisals +18 -0
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/CONTRIBUTING.md +2 -0
  12. data/Gemfile +5 -5
  13. data/NEWS.md +141 -2
  14. data/README.md +149 -66
  15. data/RELEASING.md +5 -12
  16. data/Rakefile +1 -1
  17. data/SECURITY.md +15 -0
  18. data/app/controllers/doorkeeper/application_controller.rb +4 -6
  19. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  20. data/app/controllers/doorkeeper/applications_controller.rb +18 -8
  21. data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
  22. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  23. data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
  24. data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
  25. data/app/validators/redirect_uri_validator.rb +12 -2
  26. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  27. data/app/views/doorkeeper/applications/_form.html.erb +13 -2
  28. data/app/views/doorkeeper/applications/index.html.erb +2 -0
  29. data/app/views/doorkeeper/applications/show.html.erb +4 -1
  30. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  31. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
  34. data/config/locales/en.yml +12 -7
  35. data/doorkeeper.gemspec +16 -11
  36. data/gemfiles/rails_4_2.gemfile +13 -0
  37. data/gemfiles/rails_5_0.gemfile +12 -0
  38. data/gemfiles/rails_5_1.gemfile +12 -0
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +119 -46
  42. data/lib/doorkeeper/engine.rb +11 -7
  43. data/lib/doorkeeper/errors.rb +18 -0
  44. data/lib/doorkeeper/grape/helpers.rb +14 -8
  45. data/lib/doorkeeper/helpers/controller.rb +8 -19
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
  47. data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
  48. data/lib/doorkeeper/models/application_mixin.rb +33 -35
  49. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  50. data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
  51. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  52. data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
  53. data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
  54. data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
  57. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
  58. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  59. data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
  60. data/lib/doorkeeper/oauth/client.rb +2 -3
  61. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  62. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  63. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  64. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
  65. data/lib/doorkeeper/oauth/code_response.rb +16 -16
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +10 -10
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
  75. data/lib/doorkeeper/oauth/scopes.rb +18 -8
  76. data/lib/doorkeeper/oauth/token.rb +20 -21
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  79. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
  82. data/lib/doorkeeper/orm/active_record/application.rb +48 -11
  83. data/lib/doorkeeper/orm/active_record.rb +17 -22
  84. data/lib/doorkeeper/rails/helpers.rb +6 -9
  85. data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
  86. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  87. data/lib/doorkeeper/rails/routes.rb +17 -11
  88. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  89. data/lib/doorkeeper/request/password.rb +2 -2
  90. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  91. data/lib/doorkeeper/request.rb +7 -1
  92. data/lib/doorkeeper/server.rb +0 -8
  93. data/lib/doorkeeper/validations.rb +3 -2
  94. data/lib/doorkeeper/version.rb +34 -1
  95. data/lib/doorkeeper.rb +10 -2
  96. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
  97. data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
  98. data/lib/generators/doorkeeper/migration_generator.rb +13 -1
  99. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
  100. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
  101. data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
  102. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
  105. data/spec/controllers/application_metal_controller.rb +10 -0
  106. data/spec/controllers/applications_controller_spec.rb +15 -4
  107. data/spec/controllers/authorizations_controller_spec.rb +74 -27
  108. data/spec/controllers/protected_resources_controller_spec.rb +70 -32
  109. data/spec/controllers/token_info_controller_spec.rb +17 -13
  110. data/spec/controllers/tokens_controller_spec.rb +198 -12
  111. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
  112. data/spec/dummy/app/controllers/home_controller.rb +1 -1
  113. data/spec/dummy/app/controllers/metal_controller.rb +1 -1
  114. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
  115. data/spec/dummy/app/models/user.rb +0 -4
  116. data/spec/dummy/config/application.rb +2 -36
  117. data/spec/dummy/config/environment.rb +1 -1
  118. data/spec/dummy/config/environments/test.rb +4 -15
  119. data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
  120. data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
  121. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  122. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  123. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  124. data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
  125. data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
  126. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
  127. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
  128. data/spec/dummy/db/schema.rb +24 -22
  129. data/spec/factories.rb +4 -2
  130. data/spec/generators/application_owner_generator_spec.rb +24 -5
  131. data/spec/generators/migration_generator_spec.rb +24 -3
  132. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  133. data/spec/grape/grape_integration_spec.rb +135 -0
  134. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  135. data/spec/lib/config_spec.rb +159 -14
  136. data/spec/lib/doorkeeper_spec.rb +135 -13
  137. data/spec/lib/models/expirable_spec.rb +0 -1
  138. data/spec/lib/models/revocable_spec.rb +27 -4
  139. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  140. data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
  141. data/spec/lib/oauth/base_request_spec.rb +155 -0
  142. data/spec/lib/oauth/base_response_spec.rb +45 -0
  143. data/spec/lib/oauth/client/credentials_spec.rb +45 -2
  144. data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
  145. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  146. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
  147. data/spec/lib/oauth/code_request_spec.rb +1 -3
  148. data/spec/lib/oauth/code_response_spec.rb +34 -0
  149. data/spec/lib/oauth/error_response_spec.rb +9 -9
  150. data/spec/lib/oauth/error_spec.rb +1 -1
  151. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
  152. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  153. data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
  154. data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
  155. data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
  156. data/spec/lib/oauth/scopes_spec.rb +28 -2
  157. data/spec/lib/oauth/token_request_spec.rb +6 -8
  158. data/spec/lib/oauth/token_spec.rb +12 -5
  159. data/spec/lib/server_spec.rb +10 -3
  160. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  161. data/spec/models/doorkeeper/access_token_spec.rb +116 -48
  162. data/spec/models/doorkeeper/application_spec.rb +145 -29
  163. data/spec/requests/applications/applications_request_spec.rb +5 -5
  164. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  165. data/spec/requests/endpoints/token_spec.rb +8 -1
  166. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  167. data/spec/requests/flows/authorization_code_spec.rb +6 -13
  168. data/spec/requests/flows/client_credentials_spec.rb +29 -1
  169. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  170. data/spec/requests/flows/password_spec.rb +118 -15
  171. data/spec/requests/flows/refresh_token_spec.rb +89 -19
  172. data/spec/requests/flows/revoke_token_spec.rb +105 -91
  173. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  174. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  175. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  176. data/spec/routing/default_routes_spec.rb +5 -1
  177. data/spec/spec_helper.rb +2 -0
  178. data/spec/spec_helper_integration.rb +22 -4
  179. data/spec/support/dependencies/factory_girl.rb +2 -2
  180. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  181. data/spec/support/helpers/model_helper.rb +34 -7
  182. data/spec/support/helpers/request_spec_helper.rb +17 -5
  183. data/spec/support/helpers/url_helper.rb +9 -8
  184. data/spec/support/http_method_shim.rb +38 -0
  185. data/spec/support/shared/controllers_shared_context.rb +15 -10
  186. data/spec/support/shared/models_shared_examples.rb +5 -5
  187. data/spec/validators/redirect_uri_validator_spec.rb +51 -6
  188. data/spec/version/version_spec.rb +15 -0
  189. metadata +128 -46
  190. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  191. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  192. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  193. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
  194. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  195. data/spec/lib/oauth/client/methods_spec.rb +0 -54
data/README.md CHANGED
@@ -1,58 +1,74 @@
1
- # Doorkeeper - awesome oauth provider for your Rails app.
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
- [PR 567]: https://github.com/doorkeeper-gem/doorkeeper/pull/567
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
- - [Useful links](#useful-links)
39
+
24
40
  - [Installation](#installation)
25
41
  - [Configuration](#configuration)
42
+ - [ORM](#orm)
26
43
  - [Active Record](#active-record)
27
- - [Other ORMs](#other-orms)
28
- - [Routes](#routes)
29
- - [Authenticating](#authenticating)
30
- - [Internationalization (I18n)](#internationalization-i18n)
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
- - [Protect your API with OAuth when using Grape](#protect-your-api-with-oauth-when-using-grape)
33
- - [Route Constraints and other integrations](#route-constraints-and-other-integrations)
34
- - [Access Token Scopes](#access-token-scopes)
35
- - [Custom Access Token Generator](#custom-access-token-generator)
36
- - [Authenticated resource owner](#authenticated-resource-owner)
37
- - [Applications list](#applications-list)
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
- - [Wiki](#wiki)
44
- - [Screencast](#screencast)
45
- - [Client applications](#client-applications)
46
- - [Contributors](#contributors)
47
- - [IETF Standards](#ietf-standards)
48
- - [License](#license)
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
- ## Useful links
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
- ### Active Record
89
+ ### ORM
90
+
91
+ #### Active Record
74
92
 
75
- By default doorkeeper is configured to use active record, so to start you have
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
- Don't forget to run the migration with:
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
- rake db:migrate
108
+ ```sh
109
+ rake db:migrate
110
+ ```
83
111
 
84
- ### Other ORMs
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
- See [doorkeeper-mongodb project] for mongoid and mongomapper support. Follow along
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/:code
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.find_by_id(session[:current_user_id]) || redirect_to(login_url)
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
- To protect your API with OAuth, you just need to setup `before_action`s
149
- specifying the actions you want to protect. For example:
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
- ### Protect your API with OAuth when using Grape
222
+ ### Grape endpoints
163
223
 
164
- As of [PR 567] doorkeeper has helpers for Grape. One of them is
165
- `doorkeeper_authorize!` and can be used in a similar way as an example above.
166
- Note that you have to use `require 'doorkeeper/grape/helpers'` and
167
- `helpers Doorkeeper::Grape::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
- [PR 567]: https://github.com/doorkeeper-gem/doorkeeper/pull/567
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 need
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 time,
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
- have both `:admin` and `:write` scopes.
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 public available.
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.find_by_id(session[:admin_id]) || redirect_to(routes.new_admin_session_url)
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 at all. For
323
- more information see the page [in the
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 doorkeeper in our [wiki
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. There shouldn’t be code changes, and thus CI doesn’t need to
6
- run, you can then add “[ci skip]” to the commit message.
7
- 4. Tag the release: `git tag vVERSION -m "Release vVERSION"`
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
@@ -2,7 +2,7 @@ require 'bundler/setup'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  desc 'Default: run specs.'
5
- task :default => :spec
5
+ task default: :spec
6
6
 
7
7
  desc "Run all specs"
8
8
  RSpec::Core::RakeTask.new(:spec) do |config|
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 < ActionController::Base
2
+ class ApplicationController <
3
+ Doorkeeper.configuration.base_controller.constantize
4
+
3
5
  include Helpers::Controller
4
6
 
5
- if ::Rails.version.to_i < 4
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
- before_filter :authenticate_admin!
6
- before_filter :set_application, only: [:show, :edit, :update, :destroy]
5
+ before_action :authenticate_admin!
6
+ before_action :set_application, only: [:show, :edit, :update, :destroy]
7
7
 
8
8
  def index
9
- @applications = Application.all
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
- if params.respond_to?(:permit)
48
- params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes)
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 AuthorizationsController < Doorkeeper::ApplicationController
3
- before_filter :authenticate_resource_owner!
3
+ before_action :authenticate_resource_owner!
4
4
 
5
5
  def new
6
6
  if pre_auth.authorizable?
@@ -1,6 +1,6 @@
1
1
  module Doorkeeper
2
2
  class AuthorizedApplicationsController < Doorkeeper::ApplicationController
3
- before_filter :authenticate_resource_owner!
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
- self.headers.merge! response.headers
5
+ headers.merge! response.headers
6
6
  self.response_body = response.body.to_json
7
- self.status = response.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 validates the client credentials
15
- if doorkeeper_token && doorkeeper_token.accessible?
16
- # Doorkeeper does not use the token_type_hint logic described in the RFC 7009
17
- # due to the refresh token implementation that is a field in the access token model.
18
- revoke_token(request.POST['token']) if request.POST['token']
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
- # The authorization server responds with HTTP status code 200 if the
21
- # token has been revoked successfully or if the client submitted an invalid token
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
- def revoke_token(token)
28
- token = AccessToken.by_token(token) || AccessToken.by_refresh_token(token)
29
- if token && doorkeeper_token.same_credential?(token)
30
- token.revoke
31
- true
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
- false
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