doorkeeper 4.2.0 → 5.5.2

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 (271) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1038 -0
  3. data/README.md +110 -348
  4. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  5. data/app/controllers/doorkeeper/application_controller.rb +6 -7
  6. data/app/controllers/doorkeeper/application_metal_controller.rb +7 -11
  7. data/app/controllers/doorkeeper/applications_controller.rb +65 -20
  8. data/app/controllers/doorkeeper/authorizations_controller.rb +97 -17
  9. data/app/controllers/doorkeeper/authorized_applications_controller.rb +22 -3
  10. data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
  11. data/app/controllers/doorkeeper/tokens_controller.rb +112 -35
  12. data/app/helpers/doorkeeper/dashboard_helper.rb +10 -6
  13. data/app/views/doorkeeper/applications/_delete_form.html.erb +4 -3
  14. data/app/views/doorkeeper/applications/_form.html.erb +33 -21
  15. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  16. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  17. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  18. data/app/views/doorkeeper/applications/show.html.erb +40 -16
  19. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  20. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  21. data/app/views/doorkeeper/authorizations/new.html.erb +7 -1
  22. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  23. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  24. data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
  25. data/config/locales/en.yml +33 -9
  26. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  27. data/lib/doorkeeper/config/option.rb +82 -0
  28. data/lib/doorkeeper/config/validations.rb +53 -0
  29. data/lib/doorkeeper/config.rb +545 -143
  30. data/lib/doorkeeper/engine.rb +11 -5
  31. data/lib/doorkeeper/errors.rb +37 -10
  32. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  33. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  34. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  35. data/lib/doorkeeper/grant_flow.rb +45 -0
  36. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  37. data/lib/doorkeeper/grape/helpers.rb +24 -12
  38. data/lib/doorkeeper/helpers/controller.rb +49 -27
  39. data/lib/doorkeeper/models/access_grant_mixin.rb +100 -21
  40. data/lib/doorkeeper/models/access_token_mixin.rb +379 -75
  41. data/lib/doorkeeper/models/application_mixin.rb +72 -25
  42. data/lib/doorkeeper/models/concerns/accessible.rb +6 -0
  43. data/lib/doorkeeper/models/concerns/expirable.rb +20 -6
  44. data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
  45. data/lib/doorkeeper/models/concerns/ownership.rb +4 -7
  46. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  47. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  48. data/lib/doorkeeper/models/concerns/revocable.rb +12 -18
  49. data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
  50. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  51. data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
  52. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  53. data/lib/doorkeeper/oauth/authorization/token.rb +66 -28
  54. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization_code_request.rb +64 -14
  56. data/lib/doorkeeper/oauth/base_request.rb +66 -0
  57. data/lib/doorkeeper/oauth/base_response.rb +31 -0
  58. data/lib/doorkeeper/oauth/client/credentials.rb +23 -10
  59. data/lib/doorkeeper/oauth/client.rb +10 -12
  60. data/lib/doorkeeper/oauth/client_credentials/creator.rb +47 -4
  61. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +16 -9
  62. data/lib/doorkeeper/oauth/client_credentials/validator.rb +56 -0
  63. data/lib/doorkeeper/oauth/client_credentials_request.rb +11 -15
  64. data/lib/doorkeeper/oauth/code_request.rb +8 -12
  65. data/lib/doorkeeper/oauth/code_response.rb +28 -15
  66. data/lib/doorkeeper/oauth/error.rb +5 -3
  67. data/lib/doorkeeper/oauth/error_response.rb +41 -20
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -18
  70. data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
  71. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +53 -3
  72. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  73. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  74. data/lib/doorkeeper/oauth/invalid_token_response.rb +31 -5
  75. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  76. data/lib/doorkeeper/oauth/password_access_token_request.rb +45 -13
  77. data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
  78. data/lib/doorkeeper/oauth/refresh_token_request.rb +61 -36
  79. data/lib/doorkeeper/oauth/scopes.rb +26 -12
  80. data/lib/doorkeeper/oauth/token.rb +25 -23
  81. data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
  82. data/lib/doorkeeper/oauth/token_request.rb +8 -21
  83. data/lib/doorkeeper/oauth/token_response.rb +14 -10
  84. data/lib/doorkeeper/oauth.rb +13 -0
  85. data/lib/doorkeeper/orm/active_record/access_grant.rb +6 -4
  86. data/lib/doorkeeper/orm/active_record/access_token.rb +5 -25
  87. data/lib/doorkeeper/orm/active_record/application.rb +6 -15
  88. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
  89. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
  90. data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
  91. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  92. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
  93. data/lib/doorkeeper/orm/active_record.rb +37 -8
  94. data/lib/doorkeeper/rails/helpers.rb +14 -15
  95. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  96. data/lib/doorkeeper/rails/routes/mapper.rb +3 -1
  97. data/lib/doorkeeper/rails/routes/mapping.rb +10 -8
  98. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  99. data/lib/doorkeeper/rails/routes.rb +42 -30
  100. data/lib/doorkeeper/rake/db.rake +40 -0
  101. data/lib/doorkeeper/rake/setup.rake +11 -0
  102. data/lib/doorkeeper/rake.rb +14 -0
  103. data/lib/doorkeeper/request/authorization_code.rb +12 -4
  104. data/lib/doorkeeper/request/client_credentials.rb +3 -3
  105. data/lib/doorkeeper/request/code.rb +1 -1
  106. data/lib/doorkeeper/request/password.rb +5 -14
  107. data/lib/doorkeeper/request/refresh_token.rb +6 -5
  108. data/lib/doorkeeper/request/strategy.rb +4 -2
  109. data/lib/doorkeeper/request/token.rb +1 -1
  110. data/lib/doorkeeper/request.rb +62 -29
  111. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  112. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  113. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  114. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  115. data/lib/doorkeeper/server.rb +9 -19
  116. data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  117. data/lib/doorkeeper/validations.rb +5 -2
  118. data/lib/doorkeeper/version.rb +12 -1
  119. data/lib/doorkeeper.rb +111 -56
  120. data/lib/generators/doorkeeper/application_owner_generator.rb +28 -13
  121. data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  122. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  123. data/lib/generators/doorkeeper/install_generator.rb +19 -9
  124. data/lib/generators/doorkeeper/migration_generator.rb +27 -10
  125. data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  126. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -19
  127. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  128. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
  129. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +3 -1
  130. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  131. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  132. data/lib/generators/doorkeeper/templates/initializer.rb +410 -31
  133. data/lib/generators/doorkeeper/templates/migration.rb.erb +88 -0
  134. data/lib/generators/doorkeeper/views_generator.rb +8 -4
  135. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  136. metadata +132 -286
  137. data/.gitignore +0 -14
  138. data/.hound.yml +0 -13
  139. data/.rspec +0 -1
  140. data/.travis.yml +0 -20
  141. data/CONTRIBUTING.md +0 -47
  142. data/Gemfile +0 -14
  143. data/NEWS.md +0 -593
  144. data/RELEASING.md +0 -17
  145. data/Rakefile +0 -20
  146. data/app/validators/redirect_uri_validator.rb +0 -34
  147. data/doorkeeper.gemspec +0 -28
  148. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  149. data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
  150. data/lib/doorkeeper/oauth/request_concern.rb +0 -48
  151. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
  152. data/lib/generators/doorkeeper/templates/migration.rb +0 -68
  153. data/spec/controllers/application_metal_controller.rb +0 -10
  154. data/spec/controllers/applications_controller_spec.rb +0 -58
  155. data/spec/controllers/authorizations_controller_spec.rb +0 -189
  156. data/spec/controllers/protected_resources_controller_spec.rb +0 -300
  157. data/spec/controllers/token_info_controller_spec.rb +0 -52
  158. data/spec/controllers/tokens_controller_spec.rb +0 -88
  159. data/spec/dummy/Rakefile +0 -7
  160. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  161. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
  162. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
  163. data/spec/dummy/app/controllers/home_controller.rb +0 -17
  164. data/spec/dummy/app/controllers/metal_controller.rb +0 -11
  165. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
  166. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  167. data/spec/dummy/app/models/user.rb +0 -5
  168. data/spec/dummy/app/views/home/index.html.erb +0 -0
  169. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  170. data/spec/dummy/config/application.rb +0 -23
  171. data/spec/dummy/config/boot.rb +0 -9
  172. data/spec/dummy/config/database.yml +0 -15
  173. data/spec/dummy/config/environment.rb +0 -5
  174. data/spec/dummy/config/environments/development.rb +0 -29
  175. data/spec/dummy/config/environments/production.rb +0 -62
  176. data/spec/dummy/config/environments/test.rb +0 -44
  177. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +0 -6
  178. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  179. data/spec/dummy/config/initializers/doorkeeper.rb +0 -96
  180. data/spec/dummy/config/initializers/secret_token.rb +0 -9
  181. data/spec/dummy/config/initializers/session_store.rb +0 -8
  182. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  183. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  184. data/spec/dummy/config/routes.rb +0 -52
  185. data/spec/dummy/config.ru +0 -4
  186. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -9
  187. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -5
  188. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -60
  189. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -7
  190. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -11
  191. data/spec/dummy/db/schema.rb +0 -67
  192. data/spec/dummy/public/404.html +0 -26
  193. data/spec/dummy/public/422.html +0 -26
  194. data/spec/dummy/public/500.html +0 -26
  195. data/spec/dummy/public/favicon.ico +0 -0
  196. data/spec/dummy/script/rails +0 -6
  197. data/spec/factories.rb +0 -28
  198. data/spec/generators/application_owner_generator_spec.rb +0 -22
  199. data/spec/generators/install_generator_spec.rb +0 -31
  200. data/spec/generators/migration_generator_spec.rb +0 -20
  201. data/spec/generators/templates/routes.rb +0 -3
  202. data/spec/generators/views_generator_spec.rb +0 -27
  203. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
  204. data/spec/lib/config_spec.rb +0 -334
  205. data/spec/lib/doorkeeper_spec.rb +0 -28
  206. data/spec/lib/models/expirable_spec.rb +0 -51
  207. data/spec/lib/models/revocable_spec.rb +0 -59
  208. data/spec/lib/models/scopes_spec.rb +0 -43
  209. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -42
  210. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
  211. data/spec/lib/oauth/client/credentials_spec.rb +0 -47
  212. data/spec/lib/oauth/client/methods_spec.rb +0 -54
  213. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
  214. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
  215. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
  216. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  217. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -104
  218. data/spec/lib/oauth/client_spec.rb +0 -39
  219. data/spec/lib/oauth/code_request_spec.rb +0 -45
  220. data/spec/lib/oauth/code_response_spec.rb +0 -34
  221. data/spec/lib/oauth/error_response_spec.rb +0 -61
  222. data/spec/lib/oauth/error_spec.rb +0 -23
  223. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
  224. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
  225. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
  226. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -104
  227. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -28
  228. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -90
  229. data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
  230. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -154
  231. data/spec/lib/oauth/scopes_spec.rb +0 -122
  232. data/spec/lib/oauth/token_request_spec.rb +0 -98
  233. data/spec/lib/oauth/token_response_spec.rb +0 -85
  234. data/spec/lib/oauth/token_spec.rb +0 -116
  235. data/spec/lib/request/strategy_spec.rb +0 -53
  236. data/spec/lib/server_spec.rb +0 -52
  237. data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
  238. data/spec/models/doorkeeper/access_token_spec.rb +0 -394
  239. data/spec/models/doorkeeper/application_spec.rb +0 -179
  240. data/spec/requests/applications/applications_request_spec.rb +0 -94
  241. data/spec/requests/applications/authorized_applications_spec.rb +0 -30
  242. data/spec/requests/endpoints/authorization_spec.rb +0 -72
  243. data/spec/requests/endpoints/token_spec.rb +0 -64
  244. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -66
  245. data/spec/requests/flows/authorization_code_spec.rb +0 -156
  246. data/spec/requests/flows/client_credentials_spec.rb +0 -58
  247. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
  248. data/spec/requests/flows/implicit_grant_spec.rb +0 -61
  249. data/spec/requests/flows/password_spec.rb +0 -115
  250. data/spec/requests/flows/refresh_token_spec.rb +0 -174
  251. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  252. data/spec/requests/flows/skip_authorization_spec.rb +0 -59
  253. data/spec/requests/protected_resources/metal_spec.rb +0 -14
  254. data/spec/requests/protected_resources/private_api_spec.rb +0 -81
  255. data/spec/routing/custom_controller_routes_spec.rb +0 -71
  256. data/spec/routing/default_routes_spec.rb +0 -35
  257. data/spec/routing/scoped_routes_spec.rb +0 -31
  258. data/spec/spec_helper.rb +0 -2
  259. data/spec/spec_helper_integration.rb +0 -59
  260. data/spec/support/dependencies/factory_girl.rb +0 -2
  261. data/spec/support/helpers/access_token_request_helper.rb +0 -11
  262. data/spec/support/helpers/authorization_request_helper.rb +0 -41
  263. data/spec/support/helpers/config_helper.rb +0 -9
  264. data/spec/support/helpers/model_helper.rb +0 -67
  265. data/spec/support/helpers/request_spec_helper.rb +0 -76
  266. data/spec/support/helpers/url_helper.rb +0 -55
  267. data/spec/support/http_method_shim.rb +0 -24
  268. data/spec/support/orm/active_record.rb +0 -3
  269. data/spec/support/shared/controllers_shared_context.rb +0 -69
  270. data/spec/support/shared/models_shared_examples.rb +0 -52
  271. data/spec/validators/redirect_uri_validator_spec.rb +0 -78
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ # RFC7662 OAuth 2.0 Token Introspection
6
+ #
7
+ # @see https://tools.ietf.org/html/rfc7662
8
+ class TokenIntrospection
9
+ def initialize(server, token)
10
+ @server = server
11
+ @token = token
12
+
13
+ authorize!
14
+ end
15
+
16
+ def authorized?
17
+ @error.blank?
18
+ end
19
+
20
+ def error_response
21
+ return if @error.blank?
22
+
23
+ if @error == :invalid_token
24
+ OAuth::InvalidTokenResponse.from_access_token(authorized_token)
25
+ elsif @error == :invalid_request
26
+ OAuth::InvalidRequestResponse.from_request(self)
27
+ else
28
+ OAuth::ErrorResponse.new(name: @error)
29
+ end
30
+ end
31
+
32
+ def to_json(*)
33
+ active? ? success_response : failure_response
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :server, :token
39
+ attr_reader :error, :invalid_request_reason
40
+
41
+ # If the protected resource uses OAuth 2.0 client credentials to
42
+ # authenticate to the introspection endpoint and its credentials are
43
+ # invalid, the authorization server responds with an HTTP 401
44
+ # (Unauthorized) as described in Section 5.2 of OAuth 2.0 [RFC6749].
45
+ #
46
+ # Endpoint must first validate the authentication.
47
+ # If the authentication is invalid, the endpoint should respond with
48
+ # an HTTP 401 status code and an invalid_client response.
49
+ #
50
+ # @see https://www.oauth.com/oauth2-servers/token-introspection-endpoint/
51
+ #
52
+ # To prevent token scanning attacks, the endpoint MUST also require
53
+ # some form of authorization to access this endpoint, such as client
54
+ # authentication as described in OAuth 2.0 [RFC6749] or a separate
55
+ # OAuth 2.0 access token such as the bearer token described in OAuth
56
+ # 2.0 Bearer Token Usage [RFC6750].
57
+ #
58
+ def authorize!
59
+ # Requested client authorization
60
+ if server.credentials
61
+ @error = :invalid_client unless authorized_client
62
+ elsif authorized_token
63
+ # Requested bearer token authorization
64
+ #
65
+ # If the protected resource uses an OAuth 2.0 bearer token to authorize
66
+ # its call to the introspection endpoint and the token used for
67
+ # authorization does not contain sufficient privileges or is otherwise
68
+ # invalid for this request, the authorization server responds with an
69
+ # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
70
+ # Usage [RFC6750].
71
+ #
72
+ @error = :invalid_token unless valid_authorized_token?
73
+ else
74
+ @error = :invalid_request
75
+ @invalid_request_reason = :request_not_authorized
76
+ end
77
+ end
78
+
79
+ # Client Authentication
80
+ def authorized_client
81
+ @authorized_client ||= server.credentials && server.client
82
+ end
83
+
84
+ # Bearer Token Authentication
85
+ def authorized_token
86
+ @authorized_token ||= Doorkeeper.authenticate(server.context.request)
87
+ end
88
+
89
+ # 2.2. Introspection Response
90
+ def success_response
91
+ customize_response(
92
+ active: true,
93
+ scope: @token.scopes_string,
94
+ client_id: @token.try(:application).try(:uid),
95
+ token_type: @token.token_type,
96
+ exp: @token.expires_at.to_i,
97
+ iat: @token.created_at.to_i,
98
+ )
99
+ end
100
+
101
+ # If the introspection call is properly authorized but the token is not
102
+ # active, does not exist on this server, or the protected resource is
103
+ # not allowed to introspect this particular token, then the
104
+ # authorization server MUST return an introspection response with the
105
+ # "active" field set to "false". Note that to avoid disclosing too
106
+ # much of the authorization server's state to a third party, the
107
+ # authorization server SHOULD NOT include any additional information
108
+ # about an inactive token, including why the token is inactive.
109
+ #
110
+ # @see https://tools.ietf.org/html/rfc7662 2.2. Introspection Response
111
+ #
112
+ def failure_response
113
+ {
114
+ active: false,
115
+ }
116
+ end
117
+
118
+ # Boolean indicator of whether or not the presented token
119
+ # is currently active. The specifics of a token's "active" state
120
+ # will vary depending on the implementation of the authorization
121
+ # server and the information it keeps about its tokens, but a "true"
122
+ # value return for the "active" property will generally indicate
123
+ # that a given token has been issued by this authorization server,
124
+ # has not been revoked by the resource owner, and is within its
125
+ # given time window of validity (e.g., after its issuance time and
126
+ # before its expiration time).
127
+ #
128
+ # Any other error is considered an "inactive" token.
129
+ #
130
+ # * The token requested does not exist or is invalid
131
+ # * The token expired
132
+ # * The token was issued to a different client than is making this request
133
+ #
134
+ # Since resource servers using token introspection rely on the
135
+ # authorization server to determine the state of a token, the
136
+ # authorization server MUST perform all applicable checks against a
137
+ # token's state. For instance, these tests include the following:
138
+ #
139
+ # o If the token can expire, the authorization server MUST determine
140
+ # whether or not the token has expired.
141
+ # o If the token can be issued before it is able to be used, the
142
+ # authorization server MUST determine whether or not a token's valid
143
+ # period has started yet.
144
+ # o If the token can be revoked after it was issued, the authorization
145
+ # server MUST determine whether or not such a revocation has taken
146
+ # place.
147
+ # o If the token has been signed, the authorization server MUST
148
+ # validate the signature.
149
+ # o If the token can be used only at certain resource servers, the
150
+ # authorization server MUST determine whether or not the token can
151
+ # be used at the resource server making the introspection call.
152
+ #
153
+ def active?
154
+ if authorized_client
155
+ valid_token? && token_introspection_allowed?(auth_client: authorized_client.application)
156
+ else
157
+ valid_token?
158
+ end
159
+ end
160
+
161
+ # Token can be valid only if it is not expired or revoked.
162
+ def valid_token?
163
+ @token&.accessible?
164
+ end
165
+
166
+ def valid_authorized_token?
167
+ !authorized_token_matches_introspected? &&
168
+ authorized_token.accessible? &&
169
+ token_introspection_allowed?(auth_token: authorized_token)
170
+ end
171
+
172
+ # RFC7662 Section 2.1
173
+ def authorized_token_matches_introspected?
174
+ authorized_token.token == @token&.token
175
+ end
176
+
177
+ # Config constraints for introspection in Doorkeeper.config.allow_token_introspection
178
+ def token_introspection_allowed?(auth_client: nil, auth_token: nil)
179
+ allow_introspection = Doorkeeper.config.allow_token_introspection
180
+ return allow_introspection unless allow_introspection.respond_to?(:call)
181
+
182
+ allow_introspection.call(@token, auth_client, auth_token)
183
+ end
184
+
185
+ # Allows to customize introspection response.
186
+ # Provides context (controller) and token for generating developer-specific
187
+ # response.
188
+ #
189
+ # @see https://tools.ietf.org/html/rfc7662#section-2.2
190
+ #
191
+ def customize_response(response)
192
+ customized_response = Doorkeeper.config.custom_introspection_response.call(
193
+ token,
194
+ server.context,
195
+ )
196
+ return response if customized_response.blank?
197
+
198
+ response.merge(customized_response)
199
+ end
200
+ end
201
+ end
202
+ end
@@ -1,37 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class TokenRequest
4
- attr_accessor :pre_auth, :resource_owner, :client
6
+ attr_reader :pre_auth, :resource_owner
5
7
 
6
8
  def initialize(pre_auth, resource_owner)
7
- @pre_auth = pre_auth
8
- @client = pre_auth.client
9
+ @pre_auth = pre_auth
9
10
  @resource_owner = resource_owner
10
11
  end
11
12
 
12
13
  def authorize
13
- if pre_auth.authorizable?
14
- auth = Authorization::Token.new(pre_auth, resource_owner)
15
- auth.issue_token
16
- @response = CodeResponse.new pre_auth,
17
- auth,
18
- response_on_fragment: true
19
- else
20
- @response = error_response
21
- end
14
+ auth = Authorization::Token.new(pre_auth, resource_owner)
15
+ auth.issue_token!
16
+ CodeResponse.new(pre_auth, auth, response_on_fragment: true)
22
17
  end
23
18
 
24
19
  def deny
25
20
  pre_auth.error = :access_denied
26
- error_response
27
- end
28
-
29
- private
30
-
31
- def error_response
32
- ErrorResponse.from_request pre_auth,
33
- redirect_uri: pre_auth.redirect_uri,
34
- response_on_fragment: true
21
+ pre_auth.error_response
35
22
  end
36
23
  end
37
24
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class TokenResponse
4
- attr_accessor :token
6
+ attr_reader :token
5
7
 
6
8
  def initialize(token)
7
9
  @token = token
@@ -9,12 +11,12 @@ module Doorkeeper
9
11
 
10
12
  def body
11
13
  {
12
- 'access_token' => token.token,
13
- 'token_type' => token.token_type,
14
- 'expires_in' => token.expires_in_seconds,
15
- 'refresh_token' => token.refresh_token,
16
- 'scope' => token.scopes_string,
17
- 'created_at' => token.created_at.to_i
14
+ "access_token" => token.plaintext_token,
15
+ "token_type" => token.token_type,
16
+ "expires_in" => token.expires_in_seconds,
17
+ "refresh_token" => token.plaintext_refresh_token,
18
+ "scope" => token.scopes_string,
19
+ "created_at" => token.created_at.to_i,
18
20
  }.reject { |_, value| value.blank? }
19
21
  end
20
22
 
@@ -23,9 +25,11 @@ module Doorkeeper
23
25
  end
24
26
 
25
27
  def headers
26
- { 'Cache-Control' => 'no-store',
27
- 'Pragma' => 'no-cache',
28
- 'Content-Type' => 'application/json; charset=utf-8' }
28
+ {
29
+ "Cache-Control" => "no-store",
30
+ "Pragma" => "no-cache",
31
+ "Content-Type" => "application/json; charset=utf-8",
32
+ }
29
33
  end
30
34
  end
31
35
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ GRANT_TYPES = [
6
+ AUTHORIZATION_CODE = "authorization_code",
7
+ IMPLICIT = "implicit",
8
+ PASSWORD = "password",
9
+ CLIENT_CREDENTIALS = "client_credentials",
10
+ REFRESH_TOKEN = "refresh_token",
11
+ ].freeze
12
+ end
13
+ end
@@ -1,7 +1,9 @@
1
- module Doorkeeper
2
- class AccessGrant < ActiveRecord::Base
3
- self.table_name = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}".to_sym
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/orm/active_record/mixins/access_grant"
4
4
 
5
- include AccessGrantMixin
5
+ module Doorkeeper
6
+ class AccessGrant < ::ActiveRecord::Base
7
+ include Doorkeeper::Orm::ActiveRecord::Mixins::AccessGrant
6
8
  end
7
9
  end
@@ -1,29 +1,9 @@
1
- module Doorkeeper
2
- class AccessToken < ActiveRecord::Base
3
- self.table_name = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}".to_sym
4
-
5
- include AccessTokenMixin
6
-
7
- def self.delete_all_for(application_id, resource_owner)
8
- where(application_id: application_id,
9
- resource_owner_id: resource_owner.id).delete_all
10
- end
11
- private_class_method :delete_all_for
1
+ # frozen_string_literal: true
12
2
 
13
- def self.active_for(resource_owner)
14
- where(resource_owner_id: resource_owner.id, revoked_at: nil)
15
- end
3
+ require "doorkeeper/orm/active_record/mixins/access_token"
16
4
 
17
- def self.order_method
18
- :order
19
- end
20
-
21
- def self.refresh_token_revoked_on_use?
22
- column_names.include?('previous_refresh_token')
23
- end
24
-
25
- def self.created_at_desc
26
- 'created_at desc'
27
- end
5
+ module Doorkeeper
6
+ class AccessToken < ::ActiveRecord::Base
7
+ include Doorkeeper::Orm::ActiveRecord::Mixins::AccessToken
28
8
  end
29
9
  end
@@ -1,19 +1,10 @@
1
- module Doorkeeper
2
- class Application < ActiveRecord::Base
3
- self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}".to_sym
4
-
5
- include ApplicationMixin
1
+ # frozen_string_literal: true
6
2
 
7
- if ActiveRecord::VERSION::MAJOR >= 4
8
- has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: 'AccessToken'
9
- else
10
- has_many :authorized_tokens, class_name: 'AccessToken', conditions: { revoked_at: nil }
11
- end
12
- has_many :authorized_applications, through: :authorized_tokens, source: :application
3
+ require "doorkeeper/orm/active_record/redirect_uri_validator"
4
+ require "doorkeeper/orm/active_record/mixins/application"
13
5
 
14
- def self.authorized_for(resource_owner)
15
- resource_access_tokens = AccessToken.active_for(resource_owner)
16
- where(id: resource_access_tokens.select(:application_id).distinct)
17
- end
6
+ module Doorkeeper
7
+ class Application < ::ActiveRecord::Base
8
+ include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
18
9
  end
19
10
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module AccessGrant
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+
10
+ include ::Doorkeeper::AccessGrantMixin
11
+
12
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
13
+ optional: true,
14
+ inverse_of: :access_grants
15
+
16
+ if Doorkeeper.config.polymorphic_resource_owner?
17
+ belongs_to :resource_owner, polymorphic: true, optional: false
18
+ else
19
+ validates :resource_owner_id, presence: true
20
+ end
21
+
22
+ validates :application_id,
23
+ :token,
24
+ :expires_in,
25
+ :redirect_uri,
26
+ presence: true
27
+
28
+ validates :token, uniqueness: { case_sensitive: true }
29
+
30
+ before_validation :generate_token, on: :create
31
+
32
+ # We keep a volatile copy of the raw token for initial communication
33
+ # The stored refresh_token may be mapped and not available in cleartext.
34
+ #
35
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
36
+ # while hashing strategies do not, so you cannot rely on this value
37
+ # returning a present value for persisted tokens.
38
+ def plaintext_token
39
+ if secret_strategy.allows_restoring_secrets?
40
+ secret_strategy.restore_secret(self, :token)
41
+ else
42
+ @raw_token
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ # Generates token value with UniqueToken class.
49
+ #
50
+ # @return [String] token value
51
+ #
52
+ def generate_token
53
+ @raw_token = Doorkeeper::OAuth::Helpers::UniqueToken.generate
54
+ secret_strategy.store_secret(self, :token, @raw_token)
55
+ end
56
+ end
57
+
58
+ module ClassMethods
59
+ private
60
+
61
+ def compute_doorkeeper_table_name
62
+ table_name = "oauth_access_grant"
63
+ table_name = table_name.pluralize if pluralize_table_names
64
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module AccessToken
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+
10
+ include ::Doorkeeper::AccessTokenMixin
11
+
12
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
13
+ inverse_of: :access_tokens,
14
+ optional: true
15
+
16
+ if Doorkeeper.config.polymorphic_resource_owner?
17
+ belongs_to :resource_owner, polymorphic: true, optional: true
18
+ end
19
+
20
+ validates :token, presence: true, uniqueness: { case_sensitive: true }
21
+ validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
22
+
23
+ # @attr_writer [Boolean, nil] use_refresh_token
24
+ # indicates the possibility of using refresh token
25
+ attr_writer :use_refresh_token
26
+
27
+ before_validation :generate_token, on: :create
28
+ before_validation :generate_refresh_token,
29
+ on: :create, if: :use_refresh_token?
30
+ end
31
+
32
+ module ClassMethods
33
+ # Searches for not revoked Access Tokens associated with the
34
+ # specific Resource Owner.
35
+ #
36
+ # @param resource_owner [ActiveRecord::Base]
37
+ # Resource Owner model instance
38
+ #
39
+ # @return [ActiveRecord::Relation]
40
+ # active Access Tokens for Resource Owner
41
+ #
42
+ def active_for(resource_owner)
43
+ by_resource_owner(resource_owner).where(revoked_at: nil)
44
+ end
45
+
46
+ def refresh_token_revoked_on_use?
47
+ column_names.include?("previous_refresh_token")
48
+ end
49
+
50
+ private
51
+
52
+ def compute_doorkeeper_table_name
53
+ table_name = "oauth_access_token"
54
+ table_name = table_name.pluralize if pluralize_table_names
55
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
56
+ end
57
+ end
58
+ end
59
+ end