super-smart-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/doorkeeper-5.9.3/CHANGELOG.md +1208 -0
  3. data/doorkeeper-5.9.3/MIT-LICENSE +20 -0
  4. data/doorkeeper-5.9.3/README.md +186 -0
  5. data/doorkeeper-5.9.3/app/assets/stylesheets/doorkeeper/admin/application.css +10 -0
  6. data/doorkeeper-5.9.3/app/assets/stylesheets/doorkeeper/application.css +64 -0
  7. data/doorkeeper-5.9.3/app/controllers/doorkeeper/application_controller.rb +14 -0
  8. data/doorkeeper-5.9.3/app/controllers/doorkeeper/application_metal_controller.rb +13 -0
  9. data/doorkeeper-5.9.3/app/controllers/doorkeeper/applications_controller.rb +99 -0
  10. data/doorkeeper-5.9.3/app/controllers/doorkeeper/authorizations_controller.rb +164 -0
  11. data/doorkeeper-5.9.3/app/controllers/doorkeeper/authorized_applications_controller.rb +33 -0
  12. data/doorkeeper-5.9.3/app/controllers/doorkeeper/token_info_controller.rb +25 -0
  13. data/doorkeeper-5.9.3/app/controllers/doorkeeper/tokens_controller.rb +180 -0
  14. data/doorkeeper-5.9.3/app/helpers/doorkeeper/dashboard_helper.rb +21 -0
  15. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/_delete_form.html.erb +6 -0
  16. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/_form.html.erb +59 -0
  17. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/edit.html.erb +5 -0
  18. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/index.html.erb +38 -0
  19. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/new.html.erb +5 -0
  20. data/doorkeeper-5.9.3/app/views/doorkeeper/applications/show.html.erb +63 -0
  21. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/error.html.erb +9 -0
  22. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  23. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/new.html.erb +46 -0
  24. data/doorkeeper-5.9.3/app/views/doorkeeper/authorizations/show.html.erb +7 -0
  25. data/doorkeeper-5.9.3/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +4 -0
  26. data/doorkeeper-5.9.3/app/views/doorkeeper/authorized_applications/index.html.erb +24 -0
  27. data/doorkeeper-5.9.3/app/views/layouts/doorkeeper/admin.html.erb +39 -0
  28. data/doorkeeper-5.9.3/app/views/layouts/doorkeeper/application.html.erb +23 -0
  29. data/doorkeeper-5.9.3/config/locales/en.yml +155 -0
  30. data/doorkeeper-5.9.3/lib/doorkeeper/config/abstract_builder.rb +28 -0
  31. data/doorkeeper-5.9.3/lib/doorkeeper/config/option.rb +82 -0
  32. data/doorkeeper-5.9.3/lib/doorkeeper/config/validations.rb +65 -0
  33. data/doorkeeper-5.9.3/lib/doorkeeper/config.rb +721 -0
  34. data/doorkeeper-5.9.3/lib/doorkeeper/engine.rb +38 -0
  35. data/doorkeeper-5.9.3/lib/doorkeeper/errors.rb +85 -0
  36. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  37. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/flow.rb +44 -0
  38. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow/registry.rb +50 -0
  39. data/doorkeeper-5.9.3/lib/doorkeeper/grant_flow.rb +45 -0
  40. data/doorkeeper-5.9.3/lib/doorkeeper/grape/authorization_decorator.rb +19 -0
  41. data/doorkeeper-5.9.3/lib/doorkeeper/grape/helpers.rb +58 -0
  42. data/doorkeeper-5.9.3/lib/doorkeeper/helpers/controller.rb +91 -0
  43. data/doorkeeper-5.9.3/lib/doorkeeper/models/access_grant_mixin.rb +124 -0
  44. data/doorkeeper-5.9.3/lib/doorkeeper/models/access_token_mixin.rb +526 -0
  45. data/doorkeeper-5.9.3/lib/doorkeeper/models/application_mixin.rb +96 -0
  46. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/accessible.rb +15 -0
  47. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/expirable.rb +36 -0
  48. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +96 -0
  49. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/orderable.rb +15 -0
  50. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/ownership.rb +18 -0
  51. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +29 -0
  52. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  53. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  54. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/revocable.rb +31 -0
  55. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/scopes.rb +27 -0
  56. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  57. data/doorkeeper-5.9.3/lib/doorkeeper/models/concerns/write_to_primary.rb +57 -0
  58. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/code.rb +76 -0
  59. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  60. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/token.rb +100 -0
  61. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization/uri_builder.rb +33 -0
  62. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/authorization_code_request.rb +125 -0
  63. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/base_request.rb +68 -0
  64. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/base_response.rb +31 -0
  65. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client/credentials.rb +34 -0
  66. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client.rb +28 -0
  67. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/creator.rb +57 -0
  68. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/issuer.rb +48 -0
  69. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
  70. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
  71. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/code_request.rb +25 -0
  72. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/code_response.rb +51 -0
  73. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/error.rb +16 -0
  74. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/error_response.rb +121 -0
  75. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/forbidden_token_response.rb +31 -0
  76. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/scope_checker.rb +50 -0
  77. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/unique_token.rb +30 -0
  78. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/helpers/uri_checker.rb +83 -0
  79. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  80. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/invalid_request_response.rb +47 -0
  81. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/invalid_token_response.rb +54 -0
  82. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  83. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/password_access_token_request.rb +75 -0
  84. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/pre_authorization.rb +187 -0
  85. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/refresh_token_request.rb +144 -0
  86. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/scopes.rb +134 -0
  87. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token.rb +66 -0
  88. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_introspection.rb +220 -0
  89. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_request.rb +25 -0
  90. data/doorkeeper-5.9.3/lib/doorkeeper/oauth/token_response.rb +38 -0
  91. data/doorkeeper-5.9.3/lib/doorkeeper/oauth.rb +13 -0
  92. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/access_grant.rb +9 -0
  93. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/access_token.rb +9 -0
  94. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/application.rb +10 -0
  95. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +64 -0
  96. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/access_token.rb +95 -0
  97. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/mixins/application.rb +223 -0
  98. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  99. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +44 -0
  100. data/doorkeeper-5.9.3/lib/doorkeeper/orm/active_record.rb +41 -0
  101. data/doorkeeper-5.9.3/lib/doorkeeper/rails/helpers.rb +82 -0
  102. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  103. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/mapper.rb +30 -0
  104. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/mapping.rb +40 -0
  105. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes/registry.rb +45 -0
  106. data/doorkeeper-5.9.3/lib/doorkeeper/rails/routes.rb +110 -0
  107. data/doorkeeper-5.9.3/lib/doorkeeper/rake/db.rake +40 -0
  108. data/doorkeeper-5.9.3/lib/doorkeeper/rake/setup.rake +6 -0
  109. data/doorkeeper-5.9.3/lib/doorkeeper/rake.rb +14 -0
  110. data/doorkeeper-5.9.3/lib/doorkeeper/request/authorization_code.rb +26 -0
  111. data/doorkeeper-5.9.3/lib/doorkeeper/request/client_credentials.rb +17 -0
  112. data/doorkeeper-5.9.3/lib/doorkeeper/request/code.rb +17 -0
  113. data/doorkeeper-5.9.3/lib/doorkeeper/request/password.rb +19 -0
  114. data/doorkeeper-5.9.3/lib/doorkeeper/request/refresh_token.rb +22 -0
  115. data/doorkeeper-5.9.3/lib/doorkeeper/request/strategy.rb +19 -0
  116. data/doorkeeper-5.9.3/lib/doorkeeper/request/token.rb +17 -0
  117. data/doorkeeper-5.9.3/lib/doorkeeper/request.rb +73 -0
  118. data/doorkeeper-5.9.3/lib/doorkeeper/revocable_tokens/revocable_access_token.rb +21 -0
  119. data/doorkeeper-5.9.3/lib/doorkeeper/revocable_tokens/revocable_refresh_token.rb +21 -0
  120. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/base.rb +64 -0
  121. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  122. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/plain.rb +33 -0
  123. data/doorkeeper-5.9.3/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  124. data/doorkeeper-5.9.3/lib/doorkeeper/server.rb +44 -0
  125. data/doorkeeper-5.9.3/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  126. data/doorkeeper-5.9.3/lib/doorkeeper/validations.rb +33 -0
  127. data/doorkeeper-5.9.3/lib/doorkeeper/version.rb +14 -0
  128. data/doorkeeper-5.9.3/lib/doorkeeper.rb +209 -0
  129. data/doorkeeper-5.9.3/lib/generators/doorkeeper/application_owner_generator.rb +33 -0
  130. data/doorkeeper-5.9.3/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  131. data/doorkeeper-5.9.3/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  132. data/doorkeeper-5.9.3/lib/generators/doorkeeper/install_generator.rb +22 -0
  133. data/doorkeeper-5.9.3/lib/generators/doorkeeper/migration_generator.rb +32 -0
  134. data/doorkeeper-5.9.3/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  135. data/doorkeeper-5.9.3/lib/generators/doorkeeper/previous_refresh_token_generator.rb +41 -0
  136. data/doorkeeper-5.9.3/lib/generators/doorkeeper/remove_applications_secret_not_null_constraint_generator.rb +33 -0
  137. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/README +24 -0
  138. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  139. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
  140. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +13 -0
  141. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  142. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  143. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/initializer.rb +544 -0
  144. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/migration.rb.erb +99 -0
  145. data/doorkeeper-5.9.3/lib/generators/doorkeeper/templates/remove_applications_secret_not_null_constraint.rb.erb +7 -0
  146. data/doorkeeper-5.9.3/lib/generators/doorkeeper/views_generator.rb +18 -0
  147. data/doorkeeper-5.9.3/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +6 -0
  148. data/super-smart-kit.gemspec +12 -0
  149. metadata +188 -0
@@ -0,0 +1,220 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ # RFC7662 OAuth 2.0 Token Introspection
6
+ #
7
+ # @see https://datatracker.ietf.org/doc/html/rfc7662
8
+ class TokenIntrospection
9
+ attr_reader :token, :error, :invalid_request_reason
10
+
11
+ def initialize(server, token)
12
+ @server = server
13
+ @token = token
14
+ end
15
+
16
+ def authorized?
17
+ authorize!
18
+ @error.blank?
19
+ end
20
+
21
+ def error_response
22
+ return if @error.blank?
23
+
24
+ if @error == Errors::InvalidToken
25
+ OAuth::InvalidTokenResponse.from_access_token(authorized_token)
26
+ elsif @error == Errors::InvalidRequest
27
+ OAuth::InvalidRequestResponse.from_request(self)
28
+ else
29
+ OAuth::ErrorResponse.from_request(self)
30
+ end
31
+ end
32
+
33
+ def to_json(*)
34
+ active? ? success_response : failure_response
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :server
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
+ authorize_using_basic_auth!
62
+ elsif authorized_token
63
+ authorize_using_bearer_token!
64
+ else
65
+ @error = Errors::InvalidRequest
66
+ @invalid_request_reason = :request_not_authorized
67
+ end
68
+ end
69
+
70
+ def authorize_using_basic_auth!
71
+ # Note that a properly formed and authorized query for an inactive or
72
+ # otherwise invalid token (or a token the protected resource is not
73
+ # allowed to know about) is not considered an error response by this
74
+ # specification. In these cases, the authorization server MUST instead
75
+ # respond with an introspection response with the "active" field set to
76
+ # "false" as described in Section 2.2.
77
+ @error = Errors::InvalidClient unless authorized_client
78
+ end
79
+
80
+ def authorize_using_bearer_token!
81
+ # Requested bearer token authorization
82
+ #
83
+ # If the protected resource uses an OAuth 2.0 bearer token to authorize
84
+ # its call to the introspection endpoint and the token used for
85
+ # authorization does not contain sufficient privileges or is otherwise
86
+ # invalid for this request, the authorization server responds with an
87
+ # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
88
+ # Usage [RFC6750].
89
+ #
90
+ @error = Errors::InvalidToken unless valid_authorized_token?
91
+ end
92
+
93
+ # Client Authentication
94
+ def authorized_client
95
+ @authorized_client ||= server.credentials && server.client
96
+ end
97
+
98
+ # Bearer Token Authentication
99
+ def authorized_token
100
+ @authorized_token ||= Doorkeeper.authenticate(server.context.request)
101
+ end
102
+
103
+ # 2.2. Introspection Response
104
+ def success_response
105
+ response = {
106
+ active: true,
107
+ scope: @token.scopes_string,
108
+ client_id: @token.try(:application).try(:uid),
109
+ token_type: @token.token_type,
110
+ iat: @token.created_at.to_i,
111
+ }
112
+ # `exp` is OPTIONAL per RFC 7662 §2.2; omit it for non-expiring tokens
113
+ # so clients don't interpret `0` as "expired at 1970-01-01".
114
+ response[:exp] = @token.expires_at.to_i if @token.expires_at
115
+
116
+ customize_response(response)
117
+ end
118
+
119
+ # If the introspection call is properly authorized but the token is not
120
+ # active, does not exist on this server, or the protected resource is
121
+ # not allowed to introspect this particular token, then the
122
+ # authorization server MUST return an introspection response with the
123
+ # "active" field set to "false". Note that to avoid disclosing too
124
+ # much of the authorization server's state to a third party, the
125
+ # authorization server SHOULD NOT include any additional information
126
+ # about an inactive token, including why the token is inactive.
127
+ #
128
+ # @see https://datatracker.ietf.org/doc/html/rfc7662 2.2. Introspection Response
129
+ #
130
+ def failure_response
131
+ {
132
+ active: false,
133
+ }
134
+ end
135
+
136
+ # Boolean indicator of whether or not the presented token
137
+ # is currently active. The specifics of a token's "active" state
138
+ # will vary depending on the implementation of the authorization
139
+ # server and the information it keeps about its tokens, but a "true"
140
+ # value return for the "active" property will generally indicate
141
+ # that a given token has been issued by this authorization server,
142
+ # has not been revoked by the resource owner, and is within its
143
+ # given time window of validity (e.g., after its issuance time and
144
+ # before its expiration time).
145
+ #
146
+ # Any other error is considered an "inactive" token.
147
+ #
148
+ # * The token requested does not exist or is invalid
149
+ # * The token expired
150
+ # * The token was issued to a different client than is making this request
151
+ #
152
+ # Since resource servers using token introspection rely on the
153
+ # authorization server to determine the state of a token, the
154
+ # authorization server MUST perform all applicable checks against a
155
+ # token's state. For instance, these tests include the following:
156
+ #
157
+ # o If the token can expire, the authorization server MUST determine
158
+ # whether or not the token has expired.
159
+ # o If the token can be issued before it is able to be used, the
160
+ # authorization server MUST determine whether or not a token's valid
161
+ # period has started yet.
162
+ # o If the token can be revoked after it was issued, the authorization
163
+ # server MUST determine whether or not such a revocation has taken
164
+ # place.
165
+ # o If the token has been signed, the authorization server MUST
166
+ # validate the signature.
167
+ # o If the token can be used only at certain resource servers, the
168
+ # authorization server MUST determine whether or not the token can
169
+ # be used at the resource server making the introspection call.
170
+ #
171
+ def active?
172
+ if authorized_client
173
+ valid_token? && token_introspection_allowed?(auth_client: authorized_client.application)
174
+ else
175
+ valid_token?
176
+ end
177
+ end
178
+
179
+ # Token can be valid only if it is not expired or revoked.
180
+ def valid_token?
181
+ @token&.accessible?
182
+ end
183
+
184
+ def valid_authorized_token?
185
+ !authorized_token_matches_introspected? &&
186
+ authorized_token.accessible? &&
187
+ token_introspection_allowed?(auth_token: authorized_token)
188
+ end
189
+
190
+ # RFC7662 Section 2.1
191
+ def authorized_token_matches_introspected?
192
+ authorized_token.token == @token&.token
193
+ end
194
+
195
+ # Config constraints for introspection in Doorkeeper.config.allow_token_introspection
196
+ def token_introspection_allowed?(auth_client: nil, auth_token: nil)
197
+ allow_introspection = Doorkeeper.config.allow_token_introspection
198
+ return allow_introspection unless allow_introspection.respond_to?(:call)
199
+
200
+ allow_introspection.call(@token, auth_client, auth_token)
201
+ end
202
+
203
+ # Allows to customize introspection response.
204
+ # Provides context (controller) and token for generating developer-specific
205
+ # response.
206
+ #
207
+ # @see https://datatracker.ietf.org/doc/html/rfc7662#section-2.2
208
+ #
209
+ def customize_response(response)
210
+ customized_response = Doorkeeper.config.custom_introspection_response.call(
211
+ token,
212
+ server.context,
213
+ )
214
+ return response if customized_response.blank?
215
+
216
+ response.merge(customized_response)
217
+ end
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class TokenRequest
6
+ attr_reader :pre_auth, :resource_owner
7
+
8
+ def initialize(pre_auth, resource_owner)
9
+ @pre_auth = pre_auth
10
+ @resource_owner = resource_owner
11
+ end
12
+
13
+ def authorize
14
+ auth = Authorization::Token.new(pre_auth, resource_owner)
15
+ auth.issue_token!
16
+ CodeResponse.new(pre_auth, auth, response_on_fragment: true)
17
+ end
18
+
19
+ def deny
20
+ pre_auth.error = Errors::AccessDenied
21
+ pre_auth.error_response
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class TokenResponse
6
+ attr_reader :token
7
+
8
+ alias issued_token token
9
+
10
+ def initialize(token)
11
+ @token = token
12
+ end
13
+
14
+ def body
15
+ @body ||= {
16
+ "access_token" => token.plaintext_token,
17
+ "token_type" => token.token_type,
18
+ "expires_in" => token.expires_in_seconds,
19
+ "refresh_token" => token.plaintext_refresh_token,
20
+ "scope" => token.scopes_string,
21
+ "created_at" => token.created_at.to_i,
22
+ }.reject { |_, value| value.blank? }
23
+ end
24
+
25
+ def status
26
+ :ok
27
+ end
28
+
29
+ def headers
30
+ {
31
+ "Cache-Control" => "no-store, no-cache",
32
+ "Content-Type" => "application/json; charset=utf-8",
33
+ "Pragma" => "no-cache",
34
+ }
35
+ end
36
+ end
37
+ end
38
+ 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
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/orm/active_record/mixins/access_grant"
4
+
5
+ module Doorkeeper
6
+ class AccessGrant < ::ActiveRecord::Base
7
+ include Doorkeeper::Orm::ActiveRecord::Mixins::AccessGrant
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/orm/active_record/mixins/access_token"
4
+
5
+ module Doorkeeper
6
+ class AccessToken < ::ActiveRecord::Base
7
+ include Doorkeeper::Orm::ActiveRecord::Mixins::AccessToken
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/orm/active_record/redirect_uri_validator"
4
+ require "doorkeeper/orm/active_record/mixins/application"
5
+
6
+ module Doorkeeper
7
+ class Application < ::ActiveRecord::Base
8
+ include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
9
+ end
10
+ end
@@ -0,0 +1,64 @@
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
+ self.strict_loading_by_default = false if respond_to?(:strict_loading_by_default)
10
+
11
+ include ::Doorkeeper::AccessGrantMixin
12
+ include ::Doorkeeper::Models::PolymorphicResourceOwner::ForAccessGrant
13
+
14
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
15
+ optional: true,
16
+ inverse_of: :access_grants
17
+
18
+ validates :application_id,
19
+ :token,
20
+ :expires_in,
21
+ :redirect_uri,
22
+ presence: true
23
+
24
+ validates :token, uniqueness: { case_sensitive: true }
25
+
26
+ before_validation :generate_token, on: :create
27
+
28
+ # We keep a volatile copy of the raw token for initial communication
29
+ # The stored refresh_token may be mapped and not available in cleartext.
30
+ #
31
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
32
+ # while hashing strategies do not, so you cannot rely on this value
33
+ # returning a present value for persisted tokens.
34
+ def plaintext_token
35
+ if secret_strategy.allows_restoring_secrets?
36
+ secret_strategy.restore_secret(self, :token)
37
+ else
38
+ @raw_token
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ # Generates token value with UniqueToken class.
45
+ #
46
+ # @return [String] token value
47
+ #
48
+ def generate_token
49
+ @raw_token = Doorkeeper::OAuth::Helpers::UniqueToken.generate
50
+ secret_strategy.store_secret(self, :token, @raw_token)
51
+ end
52
+ end
53
+
54
+ module ClassMethods
55
+ private
56
+
57
+ def compute_doorkeeper_table_name
58
+ table_name = "oauth_access_grant"
59
+ table_name = table_name.pluralize if pluralize_table_names
60
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,95 @@
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
+ self.strict_loading_by_default = false if respond_to?(:strict_loading_by_default)
10
+
11
+ include ::Doorkeeper::AccessTokenMixin
12
+ include ::Doorkeeper::Models::PolymorphicResourceOwner::ForAccessToken
13
+
14
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
15
+ inverse_of: :access_tokens,
16
+ optional: true
17
+
18
+ validates :token, presence: true, uniqueness: { case_sensitive: true }
19
+ validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
20
+
21
+ # @attr_writer [Boolean, nil] use_refresh_token
22
+ # indicates the possibility of using refresh token
23
+ attr_writer :use_refresh_token
24
+
25
+ before_validation :generate_token, on: :create
26
+ before_validation :generate_refresh_token,
27
+ on: :create, if: :use_refresh_token?
28
+ end
29
+
30
+ module ClassMethods
31
+ # Searches for not revoked Access Tokens associated with the
32
+ # specific Resource Owner.
33
+ #
34
+ # @param resource_owner [ActiveRecord::Base]
35
+ # Resource Owner model instance
36
+ #
37
+ # @return [ActiveRecord::Relation]
38
+ # active Access Tokens for Resource Owner
39
+ #
40
+ def active_for(resource_owner)
41
+ by_resource_owner(resource_owner).where(revoked_at: nil)
42
+ end
43
+
44
+ # Determines if refresh tokens should be revoked only when the new access token is used,
45
+ # rather than immediately upon refresh. This is based on the presence of the
46
+ # `previous_refresh_token` column in the database.
47
+ #
48
+ # When true (column exists):
49
+ # - Refresh tokens are NOT immediately revoked
50
+ # - New access token stores the old refresh token value in `previous_refresh_token`
51
+ # - Old refresh token is revoked later when the new access token is first used
52
+ # - Multiple concurrent refresh requests can succeed (no database locks)
53
+ # - Better database performance and lower latency
54
+ #
55
+ # When false (column does not exist):
56
+ # - Refresh tokens are immediately revoked using database locks
57
+ # - Only one concurrent refresh request can succeed
58
+ # - May experience database lock contention under high load
59
+ #
60
+ # To enable the revoke-on-use feature and improve performance:
61
+ # rails generate doorkeeper:previous_refresh_token
62
+ # rails db:migrate
63
+ #
64
+ # @return [Boolean] true if previous_refresh_token column exists
65
+ #
66
+ def refresh_token_revoked_on_use?
67
+ column_names.include?("previous_refresh_token")
68
+ end
69
+
70
+ # Returns non-expired and non-revoked access tokens
71
+ def not_expired
72
+ relation = where(revoked_at: nil)
73
+
74
+ if supports_expiration_time_math?
75
+ # have not reached the expiration time or it never expires
76
+ relation.where("#{expiration_time_sql} > ?", Time.now.utc).or(
77
+ relation.where(expires_in: nil),
78
+ )
79
+ else
80
+ ::Kernel.warn(::Doorkeeper::Models::ExpirationTimeSqlMath::WARNING_MESSAGE)
81
+
82
+ relation
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def compute_doorkeeper_table_name
89
+ table_name = "oauth_access_token"
90
+ table_name = table_name.pluralize if pluralize_table_names
91
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
92
+ end
93
+ end
94
+ end
95
+ end