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,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class AuthorizationCodeRequest < BaseRequest
6
+ validate :params, error: Errors::InvalidRequest
7
+ validate :client, error: Errors::InvalidClient
8
+ validate :grant, error: Errors::InvalidGrant
9
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
10
+ validate :redirect_uri, error: Errors::InvalidGrant
11
+ validate :code_verifier, error: Errors::InvalidGrant
12
+
13
+ attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
14
+ :invalid_request_reason, :missing_param
15
+
16
+ def initialize(server, grant, client, parameters = {})
17
+ super()
18
+ @server = server
19
+ @client = client
20
+ @grant = grant
21
+ @grant_type = Doorkeeper::OAuth::AUTHORIZATION_CODE
22
+ @redirect_uri = parameters[:redirect_uri]
23
+ @code_verifier = parameters[:code_verifier]
24
+ end
25
+
26
+ private
27
+
28
+ def before_successful_response
29
+ grant.transaction do
30
+ grant.lock!
31
+ raise Errors::InvalidGrantReuse if grant.revoked?
32
+
33
+ if Doorkeeper.config.revoke_previous_authorization_code_token?
34
+ revoke_previous_tokens(grant.application, resource_owner)
35
+ end
36
+
37
+ grant.revoke
38
+
39
+ find_or_create_access_token(
40
+ client,
41
+ resource_owner,
42
+ grant.scopes,
43
+ custom_token_attributes_with_data,
44
+ server,
45
+ )
46
+ end
47
+
48
+ super
49
+ end
50
+
51
+ def resource_owner
52
+ if Doorkeeper.config.polymorphic_resource_owner?
53
+ grant.resource_owner
54
+ else
55
+ grant.resource_owner_id
56
+ end
57
+ end
58
+
59
+ def pkce_supported?
60
+ Doorkeeper.config.access_grant_model.pkce_supported?
61
+ end
62
+
63
+ def validate_params
64
+ @missing_param =
65
+ if grant&.uses_pkce? && code_verifier.blank?
66
+ :code_verifier
67
+ elsif client && !client.confidential && Doorkeeper.config.force_pkce? && code_verifier.blank?
68
+ :code_verifier
69
+ elsif redirect_uri.blank?
70
+ :redirect_uri
71
+ end
72
+
73
+ @missing_param.nil?
74
+ end
75
+
76
+ def validate_client
77
+ client.present?
78
+ end
79
+
80
+ def validate_grant
81
+ return false unless grant && grant.application_id == client.id
82
+
83
+ grant.accessible?
84
+ end
85
+
86
+ def validate_redirect_uri
87
+ Helpers::URIChecker.valid_for_authorization?(
88
+ redirect_uri,
89
+ grant.redirect_uri,
90
+ )
91
+ end
92
+
93
+ # if either side (server or client) request PKCE, check the verifier
94
+ # against the DB - if PKCE is supported
95
+ def validate_code_verifier
96
+ return true unless pkce_supported?
97
+ return grant.code_challenge.blank? if code_verifier.blank?
98
+
99
+ if grant.code_challenge_method == "S256"
100
+ grant.code_challenge == generate_code_challenge(code_verifier)
101
+ elsif grant.code_challenge_method == "plain"
102
+ grant.code_challenge == code_verifier
103
+ else
104
+ false
105
+ end
106
+ end
107
+
108
+ def generate_code_challenge(code_verifier)
109
+ Doorkeeper.config.access_grant_model.generate_code_challenge(code_verifier)
110
+ end
111
+
112
+ def custom_token_attributes_with_data
113
+ grant
114
+ .attributes
115
+ .with_indifferent_access
116
+ .slice(*Doorkeeper.config.custom_access_token_attributes)
117
+ .symbolize_keys
118
+ end
119
+
120
+ def revoke_previous_tokens(application, resource_owner)
121
+ Doorkeeper.config.access_token_model.revoke_all_for(application.id, resource_owner)
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class BaseRequest
6
+ include Validations
7
+
8
+ attr_reader :grant_type, :server
9
+
10
+ delegate :default_scopes, to: :server
11
+
12
+ def authorize
13
+ if valid?
14
+ before_successful_response
15
+ @response = TokenResponse.new(access_token)
16
+ after_successful_response
17
+ @response
18
+ elsif error == Errors::InvalidRequest
19
+ @response = InvalidRequestResponse.from_request(self)
20
+ else
21
+ @response = ErrorResponse.from_request(self)
22
+ end
23
+ end
24
+
25
+ def scopes
26
+ @scopes ||= build_scopes
27
+ end
28
+
29
+ def find_or_create_access_token(client, resource_owner, scopes, custom_attributes, server)
30
+ context = Authorization::Token.build_context(client, grant_type, scopes, resource_owner)
31
+ application = client.is_a?(Doorkeeper.config.application_model) ? client : client&.application
32
+
33
+ token_attributes = {
34
+ application: application,
35
+ resource_owner: resource_owner,
36
+ scopes: scopes,
37
+ expires_in: Authorization::Token.access_token_expires_in(server, context),
38
+ use_refresh_token: Authorization::Token.refresh_token_enabled?(server, context),
39
+ }
40
+
41
+ @access_token =
42
+ Doorkeeper.config.access_token_model.find_or_create_for(**token_attributes.merge(custom_attributes))
43
+ end
44
+
45
+ def before_successful_response
46
+ Doorkeeper.config.before_successful_strategy_response.call(self)
47
+ end
48
+
49
+ def after_successful_response
50
+ Doorkeeper.config.after_successful_strategy_response.call(self, @response)
51
+ end
52
+
53
+ private
54
+
55
+ def build_scopes
56
+ if @original_scopes.present?
57
+ OAuth::Scopes.from_string(@original_scopes)
58
+ else
59
+ client_scopes = @client&.scopes
60
+ return default_scopes if client_scopes.blank?
61
+
62
+ # Avoid using Scope#& for dynamic scopes
63
+ client_scopes.allowed(default_scopes)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class BaseResponse
6
+ def body
7
+ {}
8
+ end
9
+
10
+ def description
11
+ ""
12
+ end
13
+
14
+ def headers
15
+ {}
16
+ end
17
+
18
+ def redirectable?
19
+ false
20
+ end
21
+
22
+ def redirect_uri
23
+ ""
24
+ end
25
+
26
+ def status
27
+ :ok
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class Client
6
+ Credentials = Struct.new(:uid, :secret) do
7
+ class << self
8
+ def from_request(request, *credentials_methods)
9
+ credentials_methods.inject(nil) do |_, method|
10
+ method = self.method(method) if method.is_a?(Symbol)
11
+ credentials = Credentials.new(*method.call(request))
12
+ break credentials if credentials.present?
13
+ end
14
+ end
15
+
16
+ def from_params(request)
17
+ request.parameters.values_at(:client_id, :client_secret)
18
+ end
19
+
20
+ def from_basic(request)
21
+ authorization = request.authorization
22
+ if authorization.present? && authorization =~ /^Basic (.*)/im
23
+ Base64.decode64(Regexp.last_match(1)).split(/:/, 2)
24
+ end
25
+ end
26
+ end
27
+
28
+ # Public clients may have their secret blank, but "credentials" are
29
+ # still present
30
+ delegate :blank?, to: :uid
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class Client
6
+ attr_reader :application
7
+
8
+ delegate :id, :name, :uid, :redirect_uri, :scopes, :confidential, to: :@application
9
+
10
+ def initialize(application)
11
+ @application = application
12
+ end
13
+
14
+ def self.find(uid, method = Doorkeeper.config.application_model.method(:by_uid))
15
+ return unless (application = method.call(uid))
16
+
17
+ new(application)
18
+ end
19
+
20
+ def self.authenticate(credentials, method = Doorkeeper.config.application_model.method(:by_uid_and_secret))
21
+ return if credentials.blank?
22
+ return unless (application = method.call(credentials.uid, credentials.secret))
23
+
24
+ new(application)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module ClientCredentials
6
+ class Creator
7
+ def call(client, scopes, attributes = {})
8
+ existing_token = nil
9
+
10
+ if lookup_existing_token?
11
+ existing_token = find_active_existing_token_for(client, scopes, attributes)
12
+ return existing_token if Doorkeeper.config.reuse_access_token && existing_token&.reusable?
13
+ end
14
+
15
+ with_revocation(existing_token: existing_token) do
16
+ application = client.is_a?(Doorkeeper.config.application_model) ? client : client&.application
17
+ Doorkeeper.config.access_token_model.create_for(
18
+ application: application,
19
+ resource_owner: nil,
20
+ scopes: scopes,
21
+ **attributes,
22
+ )
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def with_revocation(existing_token:)
29
+ if existing_token && Doorkeeper.config.revoke_previous_client_credentials_token?
30
+ existing_token.with_lock do
31
+ raise Errors::DoorkeeperError, :invalid_token_reuse if existing_token.revoked?
32
+
33
+ existing_token.revoke
34
+
35
+ yield
36
+ end
37
+ else
38
+ yield
39
+ end
40
+ end
41
+
42
+ def lookup_existing_token?
43
+ Doorkeeper.config.reuse_access_token ||
44
+ Doorkeeper.config.revoke_previous_client_credentials_token?
45
+ end
46
+
47
+ def find_active_existing_token_for(client, scopes, attributes)
48
+ custom_attributes = Doorkeeper.config.access_token_model
49
+ .extract_custom_attributes(attributes).presence
50
+ Doorkeeper.config.access_token_model.matching_token_for(
51
+ client, nil, scopes, custom_attributes: custom_attributes, include_expired: false,
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module ClientCredentials
6
+ class Issuer
7
+ attr_reader :token, :validator, :error
8
+
9
+ def initialize(server, validator)
10
+ @server = server
11
+ @validator = validator
12
+ end
13
+
14
+ def create(client, scopes, attributes = {}, creator = Creator.new)
15
+ if validator.valid?
16
+ @token = create_token(client, scopes, attributes, creator)
17
+ @error = Errors::ServerError unless @token
18
+ else
19
+ @token = false
20
+ @error = validator.error
21
+ end
22
+
23
+ @token
24
+ end
25
+
26
+ private
27
+
28
+ def create_token(client, scopes, attributes, creator)
29
+ context = Authorization::Token.build_context(
30
+ client,
31
+ Doorkeeper::OAuth::CLIENT_CREDENTIALS,
32
+ scopes,
33
+ nil,
34
+ )
35
+ ttl = Authorization::Token.access_token_expires_in(@server, context)
36
+
37
+ creator.call(
38
+ client,
39
+ scopes,
40
+ use_refresh_token: false,
41
+ expires_in: ttl,
42
+ **attributes,
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ module ClientCredentials
6
+ class Validator
7
+ include Validations
8
+ include OAuth::Helpers
9
+
10
+ validate :client, error: Errors::InvalidClient
11
+ validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
12
+ validate :scopes, error: Errors::InvalidScope
13
+
14
+ def initialize(server, request)
15
+ @server = server
16
+ @request = request
17
+ @client = request.client
18
+
19
+ validate
20
+ end
21
+
22
+ private
23
+
24
+ def validate_client
25
+ @client.present?
26
+ end
27
+
28
+ def validate_client_supports_grant_flow
29
+ return if @client.blank?
30
+
31
+ Doorkeeper.config.allow_grant_flow_for_client?(
32
+ Doorkeeper::OAuth::CLIENT_CREDENTIALS,
33
+ @client.application,
34
+ )
35
+ end
36
+
37
+ def validate_scopes
38
+ application_scopes = if @client.present?
39
+ @client.application.scopes
40
+ else
41
+ ""
42
+ end
43
+ return true if @request.scopes.blank? && application_scopes.blank?
44
+
45
+ ScopeChecker.valid?(
46
+ scope_str: @request.scopes.to_s,
47
+ server_scopes: @server.scopes,
48
+ app_scopes: application_scopes,
49
+ grant_type: Doorkeeper::OAuth::CLIENT_CREDENTIALS,
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class ClientCredentialsRequest < BaseRequest
6
+ attr_reader :client, :original_scopes, :parameters, :response
7
+
8
+ alias error_response response
9
+
10
+ delegate :error, to: :issuer
11
+
12
+ def initialize(server, client, parameters = {})
13
+ @client = client
14
+ @server = server
15
+ @response = nil
16
+ @grant_type = Doorkeeper::OAuth::CLIENT_CREDENTIALS
17
+ @original_scopes = parameters[:scope]
18
+ @parameters = parameters.except(:scope)
19
+ end
20
+
21
+ def access_token
22
+ issuer.token
23
+ end
24
+
25
+ def issuer
26
+ @issuer ||= ClientCredentials::Issuer.new(
27
+ server,
28
+ ClientCredentials::Validator.new(server, self),
29
+ )
30
+ end
31
+
32
+ private
33
+
34
+ def valid?
35
+ issuer.create(client, scopes, custom_token_attributes_with_data)
36
+ end
37
+
38
+ def custom_token_attributes_with_data
39
+ parameters
40
+ .with_indifferent_access
41
+ .slice(*Doorkeeper.config.custom_access_token_attributes)
42
+ .symbolize_keys
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class CodeRequest
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::Code.new(pre_auth, resource_owner)
15
+ auth.issue_token!
16
+ CodeResponse.new(pre_auth, auth, response_on_fragment: pre_auth.response_mode == "fragment")
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,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ class CodeResponse < BaseResponse
6
+ include OAuth::Helpers
7
+
8
+ attr_reader :pre_auth, :auth, :response_on_fragment
9
+
10
+ def initialize(pre_auth, auth, options = {})
11
+ @pre_auth = pre_auth
12
+ @auth = auth
13
+ @response_on_fragment = options[:response_on_fragment]
14
+ end
15
+
16
+ def redirectable?
17
+ true
18
+ end
19
+
20
+ def issued_token
21
+ auth.token
22
+ end
23
+
24
+ def body
25
+ if auth.try(:access_token?)
26
+ {
27
+ access_token: auth.token.plaintext_token,
28
+ token_type: auth.token.token_type,
29
+ expires_in: auth.token.expires_in_seconds,
30
+ state: pre_auth.state,
31
+ }
32
+ elsif auth.try(:access_grant?)
33
+ {
34
+ code: auth.token.plaintext_token,
35
+ state: pre_auth.state,
36
+ }
37
+ end
38
+ end
39
+
40
+ def redirect_uri
41
+ if URIChecker.oob_uri?(pre_auth.redirect_uri)
42
+ auth.oob_redirect
43
+ elsif response_on_fragment
44
+ Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, body)
45
+ else
46
+ Authorization::URIBuilder.uri_with_query(pre_auth.redirect_uri, body)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OAuth
5
+ Error = Struct.new(:name, :state, :translate_options) do
6
+ def description
7
+ options = (translate_options || {}).merge(
8
+ scope: %i[doorkeeper errors messages],
9
+ default: :server_error,
10
+ )
11
+
12
+ I18n.translate(name, **options)
13
+ end
14
+ end
15
+ end
16
+ end