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,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class PreAuthorization
6
+ include Validations
7
+
8
+ validate :client_id, error: Errors::InvalidRequest
9
+ validate :client, error: Errors::InvalidClient
10
+ validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
11
+ validate :resource_owner_authorize_for_client, error: Errors::InvalidClient
12
+ validate :redirect_uri, error: Errors::InvalidRedirectUri
13
+ validate :params, error: Errors::InvalidRequest
14
+ validate :response_type, error: Errors::UnsupportedResponseType
15
+ validate :response_mode, error: Errors::UnsupportedResponseMode
16
+ validate :scopes, error: Errors::InvalidScope
17
+ validate :code_challenge, error: Errors::InvalidRequest
18
+ validate :code_challenge_method, error: Errors::InvalidCodeChallengeMethod
19
+
20
+ attr_reader :client, :code_challenge, :code_challenge_method, :missing_param,
21
+ :redirect_uri, :resource_owner, :response_type, :state,
22
+ :authorization_response_flow, :response_mode, :custom_access_token_attributes,
23
+ :invalid_request_reason
24
+
25
+ def initialize(server, parameters = {}, resource_owner = nil)
26
+ @server = server
27
+ @client_id = parameters[:client_id]
28
+ @response_type = parameters[:response_type]
29
+ @response_mode = parameters[:response_mode]
30
+ @redirect_uri = parameters[:redirect_uri]
31
+ @scope = parameters[:scope]
32
+ @state = parameters[:state]
33
+ @code_challenge = parameters[:code_challenge]
34
+ @code_challenge_method = parameters[:code_challenge_method]
35
+ @resource_owner = resource_owner
36
+ @custom_access_token_attributes = parameters.slice(*Doorkeeper.config.custom_access_token_attributes).to_h
37
+ end
38
+
39
+ def authorizable?
40
+ valid?
41
+ end
42
+
43
+ def scopes
44
+ Scopes.from_string(scope)
45
+ end
46
+
47
+ def scope
48
+ @scope.presence || (server.default_scopes.presence && build_scopes)
49
+ end
50
+
51
+ def error_response
52
+ if error == Errors::InvalidRequest
53
+ OAuth::InvalidRequestResponse.from_request(
54
+ self,
55
+ response_on_fragment: response_on_fragment?,
56
+ )
57
+ else
58
+ OAuth::ErrorResponse.from_request(self, response_on_fragment: response_on_fragment?)
59
+ end
60
+ end
61
+
62
+ def as_json(_options = nil)
63
+ pre_auth_hash
64
+ end
65
+
66
+ def form_post_response?
67
+ response_mode == "form_post"
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :client_id, :server
73
+
74
+ def build_scopes
75
+ client_scopes = client.scopes
76
+ if client_scopes.blank?
77
+ server.default_scopes.to_s
78
+ else
79
+ server.default_scopes.allowed(client_scopes).to_s
80
+ end
81
+ end
82
+
83
+ def validate_client_id
84
+ @missing_param = :client_id if client_id.blank?
85
+ @missing_param.nil?
86
+ end
87
+
88
+ def validate_client
89
+ @client = OAuth::Client.find(client_id)
90
+ @client.present?
91
+ end
92
+
93
+ def validate_client_supports_grant_flow
94
+ Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
95
+ end
96
+
97
+ def validate_resource_owner_authorize_for_client
98
+ # The `authorize_resource_owner_for_client` config option is used for this validation
99
+ client.application.authorized_for_resource_owner?(@resource_owner)
100
+ end
101
+
102
+ def validate_redirect_uri
103
+ return false if redirect_uri.blank?
104
+
105
+ Helpers::URIChecker.valid_for_authorization?(
106
+ redirect_uri,
107
+ client.redirect_uri,
108
+ )
109
+ end
110
+
111
+ def validate_params
112
+ @missing_param = if response_type.blank?
113
+ :response_type
114
+ elsif @scope.blank? && server.default_scopes.blank?
115
+ :scope
116
+ end
117
+
118
+ @missing_param.nil?
119
+ end
120
+
121
+ def validate_response_type
122
+ server.authorization_response_flows.any? do |flow|
123
+ if flow.matches_response_type?(response_type)
124
+ @authorization_response_flow = flow
125
+ true
126
+ end
127
+ end
128
+ end
129
+
130
+ def validate_response_mode
131
+ if response_mode.blank?
132
+ @response_mode = authorization_response_flow.default_response_mode
133
+ return true
134
+ end
135
+
136
+ authorization_response_flow.matches_response_mode?(response_mode)
137
+ end
138
+
139
+ def validate_scopes
140
+ Helpers::ScopeChecker.valid?(
141
+ scope_str: scope,
142
+ server_scopes: server.scopes,
143
+ app_scopes: client.scopes,
144
+ grant_type: grant_type,
145
+ )
146
+ end
147
+
148
+ def validate_code_challenge
149
+ return true unless Doorkeeper.config.force_pkce?
150
+ return true if client.confidential
151
+ return true if code_challenge.present?
152
+
153
+ @invalid_request_reason = :invalid_code_challenge
154
+ false
155
+ end
156
+
157
+ def validate_code_challenge_method
158
+ return true unless Doorkeeper.config.access_grant_model.pkce_supported?
159
+
160
+ code_challenge.blank? ||
161
+ (code_challenge_method.present? && Doorkeeper.config.pkce_code_challenge_methods_supported.include?(code_challenge_method))
162
+ end
163
+
164
+ def response_on_fragment?
165
+ return response_type == "token" if response_mode.nil?
166
+
167
+ response_mode == "fragment"
168
+ end
169
+
170
+ def grant_type
171
+ response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
172
+ end
173
+
174
+ def pre_auth_hash
175
+ {
176
+ client_id: client.uid,
177
+ redirect_uri: redirect_uri,
178
+ state: state,
179
+ response_type: response_type,
180
+ scope: scope,
181
+ client_name: client.name,
182
+ status: I18n.t("doorkeeper.pre_authorization.status"),
183
+ }
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class RefreshTokenRequest < BaseRequest
6
+ include OAuth::Helpers
7
+
8
+ validate :token_presence, error: Errors::InvalidRequest
9
+ validate :token, error: Errors::InvalidGrant
10
+ validate :client, error: Errors::InvalidClient
11
+ validate :client_match, error: Errors::InvalidGrant
12
+ validate :scope, error: Errors::InvalidScope
13
+
14
+ attr_reader :access_token, :client, :credentials, :refresh_token
15
+ attr_reader :missing_param
16
+
17
+ def initialize(server, refresh_token, credentials, parameters = {})
18
+ @server = server
19
+ @refresh_token = refresh_token
20
+ @credentials = credentials
21
+ @grant_type = Doorkeeper::OAuth::REFRESH_TOKEN
22
+ @original_scopes = parameters[:scope] || parameters[:scopes]
23
+ @refresh_token_parameter = parameters[:refresh_token]
24
+ @client = load_client(credentials) if credentials
25
+ end
26
+
27
+ private
28
+
29
+ def load_client(credentials)
30
+ Doorkeeper.config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
31
+ end
32
+
33
+ def before_successful_response
34
+ if refresh_token_revoked_on_use?
35
+ # No locking needed when refresh tokens are revoked on use
36
+ # because the old token is revoked later when the new token is used.
37
+ # This allows multiple concurrent refresh requests to succeed during the
38
+ # transition period, after which the old refresh token will be revoked.
39
+ raise Errors::InvalidGrantReuse if refresh_token.revoked?
40
+
41
+ create_access_token
42
+ else
43
+ # Use locking when refresh tokens are revoked immediately
44
+ # to prevent race conditions where multiple tokens could be created
45
+ refresh_token.with_lock do
46
+ raise Errors::InvalidGrantReuse if refresh_token.revoked?
47
+
48
+ refresh_token.revoke
49
+ create_access_token
50
+ end
51
+ end
52
+ super
53
+ end
54
+
55
+ def refresh_token_revoked_on_use?
56
+ Doorkeeper.config.access_token_model.refresh_token_revoked_on_use?
57
+ end
58
+
59
+ def default_scopes
60
+ refresh_token.scopes
61
+ end
62
+
63
+ def create_access_token
64
+ attributes = {}.merge(custom_token_attributes_with_data)
65
+
66
+ resource_owner =
67
+ if Doorkeeper.config.polymorphic_resource_owner?
68
+ refresh_token.resource_owner
69
+ else
70
+ refresh_token.resource_owner_id
71
+ end
72
+
73
+ if refresh_token_revoked_on_use?
74
+ attributes[:previous_refresh_token] = refresh_token.refresh_token
75
+ end
76
+
77
+ # RFC6749
78
+ # 1.5. Refresh Token
79
+ #
80
+ # Refresh tokens are issued to the client by the authorization server and are
81
+ # used to obtain a new access token when the current access token
82
+ # becomes invalid or expires, or to obtain additional access tokens
83
+ # with identical or narrower scope (access tokens may have a shorter
84
+ # lifetime and fewer permissions than authorized by the resource
85
+ # owner).
86
+ #
87
+ # Here we assume that TTL of the token received after refreshing should be
88
+ # the same as that of the original token.
89
+ #
90
+ @access_token = Doorkeeper.config.access_token_model.create_for(
91
+ application: refresh_token.application,
92
+ resource_owner: resource_owner,
93
+ scopes: scopes,
94
+ expires_in: refresh_token.expires_in,
95
+ use_refresh_token: true,
96
+ **attributes,
97
+ )
98
+ end
99
+
100
+ def validate_token_presence
101
+ @missing_param = :refresh_token if refresh_token.blank? && @refresh_token_parameter.blank?
102
+
103
+ @missing_param.nil?
104
+ end
105
+
106
+ def validate_token
107
+ refresh_token.present? && !refresh_token.revoked?
108
+ end
109
+
110
+ def validate_client
111
+ return true if credentials.blank?
112
+
113
+ client.present?
114
+ end
115
+
116
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-1.5
117
+ #
118
+ def validate_client_match
119
+ return true if refresh_token.application_id.blank?
120
+
121
+ client && refresh_token.application_id == client.id
122
+ end
123
+
124
+ def validate_scope
125
+ if @original_scopes.present?
126
+ ScopeChecker.valid?(
127
+ scope_str: @original_scopes,
128
+ server_scopes: refresh_token.scopes,
129
+ )
130
+ else
131
+ true
132
+ end
133
+ end
134
+
135
+ def custom_token_attributes_with_data
136
+ refresh_token
137
+ .attributes
138
+ .with_indifferent_access
139
+ .slice(*Doorkeeper.config.custom_access_token_attributes)
140
+ .symbolize_keys
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class Scopes
6
+ include Enumerable
7
+ include Comparable
8
+
9
+ DYNAMIC_SCOPE_WILDCARD = "*"
10
+
11
+ def self.from_string(string)
12
+ string ||= ""
13
+ new.tap do |scope|
14
+ scope.add(*string.split)
15
+ end
16
+ end
17
+
18
+ def self.from_array(array)
19
+ new.tap do |scope|
20
+ scope.add(*array)
21
+ end
22
+ end
23
+
24
+ delegate :each, :empty?, to: :@scopes
25
+
26
+ def initialize
27
+ @scopes = []
28
+ end
29
+
30
+ def exists?(scope)
31
+ scope = scope.to_s
32
+
33
+ @scopes.any? do |allowed_scope|
34
+ if dynamic_scopes_enabled? && dynamic_scopes_present?(allowed_scope, scope)
35
+ dynamic_scope_match?(allowed_scope, scope)
36
+ else
37
+ allowed_scope == scope
38
+ end
39
+ end
40
+ end
41
+
42
+ def add(*scopes)
43
+ @scopes.push(*scopes.map(&:to_s))
44
+ @scopes.uniq!
45
+ end
46
+
47
+ def all
48
+ @scopes
49
+ end
50
+
51
+ def to_s
52
+ @scopes.join(" ")
53
+ end
54
+
55
+ def scopes?(scopes)
56
+ scopes.all? { |scope| exists?(scope) }
57
+ end
58
+
59
+ alias has_scopes? scopes?
60
+
61
+ def +(other)
62
+ self.class.from_array(all + to_array(other))
63
+ end
64
+
65
+ def <=>(other)
66
+ if other.respond_to?(:map)
67
+ map(&:to_s).sort <=> other.map(&:to_s).sort
68
+ else
69
+ super
70
+ end
71
+ end
72
+
73
+ # DEPRECATED: With dynamic scopes, #allowed should be called because
74
+ # A & B doesn't really make sense with dynamic scopes.
75
+ #
76
+ # For example, if A = user:* and B is user:1, A & B = [].
77
+ # If we modified this method to take dynamic scopes into an account, then order
78
+ # becomes important, and this would violate the principle that A & B = B & A.
79
+ def &(other)
80
+ return allowed(other) if dynamic_scopes_enabled?
81
+
82
+ self.class.from_array(all & to_array(other))
83
+ end
84
+
85
+ # Returns a set of scopes that are allowed, taking dynamic
86
+ # scopes into account. This instance's scopes is taken as the allowed set,
87
+ # and the passed value is the set to filter.
88
+ #
89
+ # @param other The set of scopes to filter
90
+ def allowed(other)
91
+ filtered_scopes = other.select { |scope| exists?(scope) }
92
+ self.class.from_array(filtered_scopes)
93
+ end
94
+
95
+ private
96
+
97
+ def dynamic_scopes_enabled?
98
+ Doorkeeper.config.enable_dynamic_scopes?
99
+ end
100
+
101
+ def dynamic_scope_delimiter
102
+ return unless dynamic_scopes_enabled?
103
+
104
+ @dynamic_scope_delimiter ||= Doorkeeper.config.dynamic_scopes_delimiter
105
+ end
106
+
107
+ def dynamic_scopes_present?(allowed, requested)
108
+ allowed.include?(dynamic_scope_delimiter) && requested.include?(dynamic_scope_delimiter)
109
+ end
110
+
111
+ def dynamic_scope_match?(allowed, requested)
112
+ allowed_pattern = allowed.split(dynamic_scope_delimiter, 2)
113
+ request_pattern = requested.split(dynamic_scope_delimiter, 2)
114
+
115
+ return false if allowed_pattern[0] != request_pattern[0]
116
+ return false if allowed_pattern[1].blank?
117
+ return false if request_pattern[1].blank?
118
+
119
+ return true if allowed_pattern[1] == DYNAMIC_SCOPE_WILDCARD
120
+
121
+ allowed_pattern[1] == request_pattern[1]
122
+ end
123
+
124
+ def to_array(other)
125
+ case other
126
+ when Scopes
127
+ other.all
128
+ else
129
+ other.to_a
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class Token
6
+ class << self
7
+ def from_request(request, *methods)
8
+ methods.inject(nil) do |_, method|
9
+ method = self.method(method) if method.is_a?(Symbol)
10
+ credentials = method.call(request)
11
+ break credentials if credentials.present?
12
+ end
13
+ end
14
+
15
+ def authenticate(request, *methods)
16
+ if (token = from_request(request, *methods))
17
+ access_token = Doorkeeper.config.access_token_model.by_token(token)
18
+ if access_token.present? && Doorkeeper.config.refresh_token_enabled?
19
+ access_token.revoke_previous_refresh_token!
20
+ end
21
+ access_token
22
+ end
23
+ end
24
+
25
+ def from_access_token_param(request)
26
+ request.parameters[:access_token]
27
+ end
28
+
29
+ def from_bearer_param(request)
30
+ request.parameters[:bearer_token]
31
+ end
32
+
33
+ def from_bearer_authorization(request)
34
+ pattern = /^Bearer /i
35
+ header = request.authorization
36
+ token_from_header(header, pattern) if match?(header, pattern)
37
+ end
38
+
39
+ def from_basic_authorization(request)
40
+ pattern = /^Basic /i
41
+ header = request.authorization
42
+ token_from_basic_header(header, pattern) if match?(header, pattern)
43
+ end
44
+
45
+ private
46
+
47
+ def token_from_basic_header(header, pattern)
48
+ encoded_header = token_from_header(header, pattern)
49
+ decode_basic_credentials_token(encoded_header)
50
+ end
51
+
52
+ def decode_basic_credentials_token(encoded_header)
53
+ Base64.decode64(encoded_header).split(/:/, 2).first
54
+ end
55
+
56
+ def token_from_header(header, pattern)
57
+ header.gsub(pattern, "")
58
+ end
59
+
60
+ def match?(header, pattern)
61
+ header&.match(pattern)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end