actionmcp 0.72.0 → 0.80.0

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/controllers/action_mcp/application_controller.rb +20 -12
  4. data/app/models/action_mcp/session/message.rb +31 -20
  5. data/app/models/action_mcp/session/resource.rb +35 -20
  6. data/app/models/action_mcp/session/sse_event.rb +23 -17
  7. data/app/models/action_mcp/session/subscription.rb +22 -15
  8. data/app/models/action_mcp/session.rb +42 -119
  9. data/config/routes.rb +0 -13
  10. data/db/migrate/20250727000001_remove_oauth_support.rb +59 -0
  11. data/lib/action_mcp/client/streamable_http_transport.rb +1 -46
  12. data/lib/action_mcp/client.rb +2 -25
  13. data/lib/action_mcp/configuration.rb +51 -24
  14. data/lib/action_mcp/engine.rb +0 -7
  15. data/lib/action_mcp/filtered_logger.rb +2 -6
  16. data/lib/action_mcp/gateway_identifier.rb +187 -3
  17. data/lib/action_mcp/gateway_identifiers/api_key_identifier.rb +56 -0
  18. data/lib/action_mcp/gateway_identifiers/devise_identifier.rb +34 -0
  19. data/lib/action_mcp/gateway_identifiers/request_env_identifier.rb +58 -0
  20. data/lib/action_mcp/gateway_identifiers/warden_identifier.rb +38 -0
  21. data/lib/action_mcp/gateway_identifiers.rb +26 -0
  22. data/lib/action_mcp/server/base_session.rb +2 -0
  23. data/lib/action_mcp/version.rb +1 -1
  24. data/lib/action_mcp.rb +1 -6
  25. data/lib/generators/action_mcp/identifier/identifier_generator.rb +189 -0
  26. data/lib/generators/action_mcp/identifier/templates/identifier.rb.erb +35 -0
  27. data/lib/generators/action_mcp/install/install_generator.rb +1 -1
  28. data/lib/generators/action_mcp/install/templates/application_gateway.rb +80 -31
  29. data/lib/generators/action_mcp/install/templates/mcp.yml +4 -21
  30. metadata +13 -97
  31. data/app/controllers/action_mcp/oauth/endpoints_controller.rb +0 -265
  32. data/app/controllers/action_mcp/oauth/metadata_controller.rb +0 -125
  33. data/app/controllers/action_mcp/oauth/registration_controller.rb +0 -201
  34. data/app/models/action_mcp/oauth_client.rb +0 -159
  35. data/app/models/action_mcp/oauth_token.rb +0 -142
  36. data/db/migrate/20250608112101_add_oauth_to_sessions.rb +0 -28
  37. data/db/migrate/20250708105124_create_action_mcp_oauth_clients.rb +0 -44
  38. data/db/migrate/20250708105226_create_action_mcp_oauth_tokens.rb +0 -39
  39. data/lib/action_mcp/client/jwt_client_provider.rb +0 -135
  40. data/lib/action_mcp/client/oauth_client_provider/memory_storage.rb +0 -47
  41. data/lib/action_mcp/client/oauth_client_provider.rb +0 -234
  42. data/lib/action_mcp/jwt_decoder.rb +0 -28
  43. data/lib/action_mcp/jwt_identifier.rb +0 -28
  44. data/lib/action_mcp/none_identifier.rb +0 -19
  45. data/lib/action_mcp/o_auth_identifier.rb +0 -34
  46. data/lib/action_mcp/oauth/active_record_storage.rb +0 -183
  47. data/lib/action_mcp/oauth/error.rb +0 -79
  48. data/lib/action_mcp/oauth/memory_storage.rb +0 -132
  49. data/lib/action_mcp/oauth/middleware.rb +0 -128
  50. data/lib/action_mcp/oauth/provider.rb +0 -406
  51. data/lib/action_mcp/oauth.rb +0 -12
  52. data/lib/action_mcp/omniauth/mcp_strategy.rb +0 -162
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActionMCP
4
- module OAuth
5
- # In-memory storage for OAuth tokens and codes
6
- # This is suitable for development and testing, but not for production
7
- class MemoryStorage
8
- def initialize
9
- @authorization_codes = {}
10
- @access_tokens = {}
11
- @refresh_tokens = {}
12
- @client_registrations = {}
13
- @mutex = Mutex.new
14
- end
15
-
16
- # Authorization code storage
17
- def store_authorization_code(code, data)
18
- @mutex.synchronize do
19
- @authorization_codes[code] = data
20
- end
21
- end
22
-
23
- def retrieve_authorization_code(code)
24
- @mutex.synchronize do
25
- @authorization_codes[code]
26
- end
27
- end
28
-
29
- def remove_authorization_code(code)
30
- @mutex.synchronize do
31
- @authorization_codes.delete(code)
32
- end
33
- end
34
-
35
- # Access token storage
36
- def store_access_token(token, data)
37
- @mutex.synchronize do
38
- @access_tokens[token] = data
39
- end
40
- end
41
-
42
- def retrieve_access_token(token)
43
- @mutex.synchronize do
44
- @access_tokens[token]
45
- end
46
- end
47
-
48
- def remove_access_token(token)
49
- @mutex.synchronize do
50
- @access_tokens.delete(token)
51
- end
52
- end
53
-
54
- # Refresh token storage
55
- def store_refresh_token(token, data)
56
- @mutex.synchronize do
57
- @refresh_tokens[token] = data
58
- end
59
- end
60
-
61
- def retrieve_refresh_token(token)
62
- @mutex.synchronize do
63
- @refresh_tokens[token]
64
- end
65
- end
66
-
67
- def update_refresh_token(token, new_access_token)
68
- @mutex.synchronize do
69
- @refresh_tokens[token][:access_token] = new_access_token if @refresh_tokens[token]
70
- end
71
- end
72
-
73
- def remove_refresh_token(token)
74
- @mutex.synchronize do
75
- @refresh_tokens.delete(token)
76
- end
77
- end
78
-
79
- # Client registration storage
80
- def store_client_registration(client_id, data)
81
- @mutex.synchronize do
82
- @client_registrations[client_id] = data
83
- end
84
- end
85
-
86
- def retrieve_client_registration(client_id)
87
- @mutex.synchronize do
88
- @client_registrations[client_id]
89
- end
90
- end
91
-
92
- def remove_client_registration(client_id)
93
- @mutex.synchronize do
94
- @client_registrations.delete(client_id)
95
- end
96
- end
97
-
98
- # Cleanup expired tokens (optional utility method)
99
- def cleanup_expired
100
- current_time = Time.current
101
-
102
- @mutex.synchronize do
103
- @authorization_codes.reject! { |_, data| data[:expires_at] < current_time }
104
- @access_tokens.reject! { |_, data| data[:expires_at] < current_time }
105
- @refresh_tokens.reject! { |_, data| data[:expires_at] < current_time }
106
- end
107
- end
108
-
109
- # Statistics (for debugging/monitoring)
110
- def stats
111
- @mutex.synchronize do
112
- {
113
- authorization_codes: @authorization_codes.size,
114
- access_tokens: @access_tokens.size,
115
- refresh_tokens: @refresh_tokens.size,
116
- client_registrations: @client_registrations.size
117
- }
118
- end
119
- end
120
-
121
- # Clear all data (for testing)
122
- def clear_all
123
- @mutex.synchronize do
124
- @authorization_codes.clear
125
- @access_tokens.clear
126
- @refresh_tokens.clear
127
- @client_registrations.clear
128
- end
129
- end
130
- end
131
- end
132
- end
@@ -1,128 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "error"
4
-
5
- module ActionMCP
6
- module OAuth
7
- # OAuth middleware that integrates with Omniauth for request authentication
8
- # Handles Bearer token validation for API requests
9
- class Middleware
10
- def initialize(app)
11
- @app = app
12
- end
13
-
14
- def call(env)
15
- request = ActionDispatch::Request.new(env)
16
-
17
- # Skip OAuth processing for non-MCP requests or if OAuth not configured
18
- return @app.call(env) unless should_process_oauth?(request)
19
-
20
- # Skip OAuth processing for metadata endpoints
21
- return @app.call(env) if request.path.start_with?("/.well-known/") || request.path.start_with?("/oauth/")
22
-
23
- # Skip OAuth processing for initialization-related requests
24
- return @app.call(env) if initialization_related_request?(request)
25
-
26
- # Validate Bearer token for API requests
27
- if (bearer_token = extract_bearer_token(request))
28
- validate_oauth_token(request, bearer_token)
29
- end
30
-
31
- @app.call(env)
32
- rescue ActionMCP::OAuth::Error => e
33
- oauth_error_response(e)
34
- end
35
-
36
- private
37
-
38
- def should_process_oauth?(_request)
39
- # Check if OAuth is enabled in configuration
40
- auth_methods = ActionMCP.configuration.authentication_methods
41
- return false unless auth_methods&.include?("oauth")
42
-
43
- # Process all MCP requests (ActionMCP serves at root "/") and OAuth-related paths
44
- true
45
- end
46
-
47
- def initialization_related_request?(request)
48
- # Only check JSON-RPC POST requests to MCP endpoints
49
- # The path might include the mount path (e.g., /action_mcp/ or just /)
50
- return false unless request.post? && request.content_type&.include?("application/json")
51
-
52
- # Check if this is an MCP endpoint (ends with / or is the root)
53
- path = request.path
54
- return false unless path == "/" || path.match?(%r{/action_mcp/?$})
55
-
56
- # Read and parse the request body
57
- body = request.body.read
58
- request.body.rewind # Reset for subsequent reads
59
-
60
- json = JSON.parse(body)
61
- method = json["method"]
62
-
63
- # Check if it's an initialization-related method
64
- %w[initialize notifications/initialized].include?(method)
65
- rescue JSON::ParserError, StandardError
66
- false
67
- end
68
-
69
- def extract_bearer_token(request)
70
- auth_header = request.headers["Authorization"] || request.headers["authorization"]
71
- return nil unless auth_header&.start_with?("Bearer ")
72
-
73
- auth_header.split(" ", 2).last
74
- end
75
-
76
- def validate_oauth_token(request, token)
77
- # Use the OAuth provider for token introspection
78
- token_info = ActionMCP::OAuth::Provider.introspect_token(token)
79
-
80
- unless token_info && token_info[:active]
81
- raise ActionMCP::OAuth::InvalidTokenError, "Invalid or expired OAuth token"
82
- end
83
-
84
- # Store OAuth token info in request environment for Gateway
85
- request.env["action_mcp.oauth_token_info"] = token_info
86
- request.env["action_mcp.oauth_token"] = token
87
- end
88
-
89
- def oauth_error_response(error)
90
- status = case error
91
- when ActionMCP::OAuth::InvalidTokenError
92
- 401
93
- when ActionMCP::OAuth::InsufficientScopeError
94
- 403
95
- else
96
- 400
97
- end
98
-
99
- headers = {
100
- "Content-Type" => "application/json",
101
- "WWW-Authenticate" => www_authenticate_header(error)
102
- }
103
-
104
- body = {
105
- error: error.oauth_error_code,
106
- error_description: error.message
107
- }.to_json
108
-
109
- [ status, headers, [ body ] ]
110
- end
111
-
112
- def www_authenticate_header(error)
113
- params = []
114
- params << 'realm="MCP API"'
115
-
116
- case error
117
- when ActionMCP::OAuth::InvalidTokenError
118
- params << 'error="invalid_token"'
119
- when ActionMCP::OAuth::InsufficientScopeError
120
- params << 'error="insufficient_scope"'
121
- params << "scope=\"#{error.required_scope}\"" if error.required_scope
122
- end
123
-
124
- "Bearer #{params.join(', ')}"
125
- end
126
- end
127
- end
128
- end
@@ -1,406 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "securerandom"
4
- require "digest"
5
- require "base64"
6
-
7
- module ActionMCP
8
- module OAuth
9
- # OAuth 2.1 Provider implementation
10
- # Handles authorization codes, access tokens, refresh tokens, and token validation
11
- class Provider
12
- class << self
13
- # Generate authorization code for OAuth flow
14
- # @param client_id [String] OAuth client identifier
15
- # @param redirect_uri [String] Client redirect URI
16
- # @param scope [String] Requested scope
17
- # @param code_challenge [String] PKCE code challenge
18
- # @param code_challenge_method [String] PKCE challenge method (S256, plain)
19
- # @param user_id [String] User identifier
20
- # @return [String] Authorization code
21
- def generate_authorization_code(client_id:, redirect_uri:, scope:, user_id:, code_challenge: nil,
22
- code_challenge_method: nil)
23
- # Validate scope
24
- validate_scope(scope) if scope
25
-
26
- code = SecureRandom.urlsafe_base64(32)
27
-
28
- # Store authorization code with metadata
29
- store_authorization_code(code, {
30
- client_id: client_id,
31
- redirect_uri: redirect_uri,
32
- scope: scope,
33
- code_challenge: code_challenge,
34
- code_challenge_method: code_challenge_method,
35
- user_id: user_id,
36
- created_at: Time.current,
37
- expires_at: 10.minutes.from_now
38
- })
39
-
40
- code
41
- end
42
-
43
- # Exchange authorization code for access token
44
- # @param code [String] Authorization code
45
- # @param client_id [String] OAuth client identifier
46
- # @param client_secret [String] OAuth client secret (optional for public clients)
47
- # @param redirect_uri [String] Client redirect URI
48
- # @param code_verifier [String] PKCE code verifier
49
- # @return [Hash] Token response with access_token, token_type, expires_in, scope
50
- def exchange_code_for_token(code:, client_id:, redirect_uri:, client_secret: nil, code_verifier: nil)
51
- # Retrieve and validate authorization code
52
- code_data = retrieve_authorization_code(code)
53
- raise InvalidGrantError, "Invalid authorization code" unless code_data
54
- raise InvalidGrantError, "Authorization code expired" if code_data[:expires_at] < Time.current
55
-
56
- # Validate client
57
- validate_client(client_id, client_secret)
58
-
59
- # Validate redirect URI matches
60
- raise InvalidGrantError, "Redirect URI mismatch" unless code_data[:redirect_uri] == redirect_uri
61
-
62
- # Validate client ID matches
63
- raise InvalidGrantError, "Client ID mismatch" unless code_data[:client_id] == client_id
64
-
65
- # Validate PKCE if challenge was provided during authorization
66
- if code_data[:code_challenge]
67
- validate_pkce(code_data[:code_challenge], code_data[:code_challenge_method], code_verifier)
68
- end
69
-
70
- # Generate access token
71
- access_token = generate_access_token(
72
- client_id: client_id,
73
- scope: code_data[:scope],
74
- user_id: code_data[:user_id]
75
- )
76
-
77
- # Generate refresh token if enabled
78
- refresh_token = nil
79
- if oauth_config[:enable_refresh_tokens]
80
- refresh_token = generate_refresh_token(
81
- client_id: client_id,
82
- scope: code_data[:scope],
83
- user_id: code_data[:user_id],
84
- access_token: access_token
85
- )
86
- end
87
-
88
- # Remove used authorization code
89
- remove_authorization_code(code)
90
-
91
- # Return token response
92
- response = {
93
- access_token: access_token,
94
- token_type: "Bearer",
95
- expires_in: token_expires_in,
96
- scope: code_data[:scope]
97
- }
98
- response[:refresh_token] = refresh_token if refresh_token
99
- response
100
- end
101
-
102
- # Refresh access token using refresh token
103
- # @param refresh_token [String] Refresh token
104
- # @param client_id [String] OAuth client identifier
105
- # @param client_secret [String] OAuth client secret
106
- # @param scope [String] Requested scope (optional, must be subset of original)
107
- # @return [Hash] New token response
108
- def refresh_access_token(refresh_token:, client_id:, client_secret: nil, scope: nil)
109
- # Retrieve refresh token data
110
- token_data = retrieve_refresh_token(refresh_token)
111
- raise InvalidGrantError, "Invalid refresh token" unless token_data
112
- raise InvalidGrantError, "Refresh token expired" if token_data[:expires_at] < Time.current
113
-
114
- # Validate client
115
- validate_client(client_id, client_secret)
116
-
117
- # Validate client ID matches
118
- raise InvalidGrantError, "Client ID mismatch" unless token_data[:client_id] == client_id
119
-
120
- # Validate scope if provided
121
- if scope
122
- requested_scopes = scope.split(" ")
123
- original_scopes = token_data[:scope].split(" ")
124
- unless (requested_scopes - original_scopes).empty?
125
- raise InvalidScopeError, "Requested scope exceeds original scope"
126
- end
127
- else
128
- scope = token_data[:scope]
129
- end
130
-
131
- # Revoke old access token
132
- revoke_access_token(token_data[:access_token]) if token_data[:access_token]
133
-
134
- # Generate new access token
135
- access_token = generate_access_token(
136
- client_id: client_id,
137
- scope: scope,
138
- user_id: token_data[:user_id]
139
- )
140
-
141
- # Update refresh token with new access token
142
- update_refresh_token(refresh_token, access_token)
143
-
144
- {
145
- access_token: access_token,
146
- token_type: "Bearer",
147
- expires_in: token_expires_in,
148
- scope: scope
149
- }
150
- end
151
-
152
- # Validate access token and return token info
153
- # @param access_token [String] Access token to validate
154
- # @return [Hash] Token info with active, client_id, scope, user_id, exp
155
- def introspect_token(access_token)
156
- token_data = retrieve_access_token(access_token)
157
-
158
- return { active: false } unless token_data
159
-
160
- if token_data[:expires_at] < Time.current
161
- remove_access_token(access_token)
162
- return { active: false }
163
- end
164
-
165
- {
166
- active: true,
167
- client_id: token_data[:client_id],
168
- scope: token_data[:scope],
169
- user_id: token_data[:user_id],
170
- exp: token_data[:expires_at].to_i,
171
- iat: token_data[:created_at].to_i,
172
- token_type: "Bearer"
173
- }
174
- end
175
-
176
- # Revoke access or refresh token
177
- # @param token [String] Token to revoke
178
- # @param token_type_hint [String] Type hint: "access_token" or "refresh_token"
179
- # @return [Boolean] True if token was revoked
180
- def revoke_token(token, token_type_hint: nil)
181
- revoked = false
182
-
183
- # Try access token first if hint suggests it or no hint provided
184
- if (token_type_hint == "access_token" || token_type_hint.nil?) && retrieve_access_token(token)
185
- revoke_access_token(token)
186
- revoked = true
187
- end
188
-
189
- # Try refresh token if not revoked yet
190
- if !revoked && (token_type_hint == "refresh_token" || token_type_hint.nil?) && retrieve_refresh_token(token)
191
- revoke_refresh_token(token)
192
- revoked = true
193
- end
194
-
195
- revoked
196
- end
197
-
198
- # Register a new OAuth client (Dynamic Client Registration)
199
- # @param client_info [Hash] Client registration information
200
- # @return [Hash] Registered client information
201
- def register_client(client_info)
202
- # Store client registration
203
- storage.store_client_registration(client_info[:client_id], client_info)
204
- client_info
205
- end
206
-
207
- # Retrieve registered client information
208
- # @param client_id [String] OAuth client identifier
209
- # @return [Hash, nil] Client information or nil if not found
210
- def get_client(client_id)
211
- storage.retrieve_client_registration(client_id)
212
- end
213
-
214
- # Client Credentials Grant (for server-to-server)
215
- # @param client_id [String] OAuth client identifier
216
- # @param client_secret [String] OAuth client secret
217
- # @param scope [String] Requested scope
218
- # @return [Hash] Token response
219
- def client_credentials_grant(client_id:, client_secret:, scope: nil)
220
- unless oauth_config[:enable_client_credentials]
221
- raise UnsupportedGrantTypeError, "Client credentials grant not supported"
222
- end
223
-
224
- # Validate client credentials
225
- validate_client(client_id, client_secret, require_secret: true)
226
-
227
- # Validate scope
228
- if scope
229
- validate_scope(scope)
230
- else
231
- scope = default_scope
232
- end
233
-
234
- # Generate access token (no user context for client credentials)
235
- access_token = generate_access_token(
236
- client_id: client_id,
237
- scope: scope,
238
- user_id: nil
239
- )
240
-
241
- {
242
- access_token: access_token,
243
- token_type: "Bearer",
244
- expires_in: token_expires_in,
245
- scope: scope
246
- }
247
- end
248
-
249
- private
250
-
251
- def oauth_config
252
- @oauth_config ||= HashWithIndifferentAccess.new(ActionMCP.configuration.oauth_config || {})
253
- end
254
-
255
- def validate_client(client_id, client_secret, require_secret: false)
256
- # First check if client is registered via dynamic registration
257
- client_info = get_client(client_id)
258
- if client_info
259
- # Validate client secret for confidential clients
260
- if client_info[:client_secret]
261
- raise InvalidClientError, "Invalid client credentials" unless client_secret == client_info[:client_secret]
262
- elsif require_secret
263
- raise InvalidClientError, "Client authentication required"
264
- end
265
- return true
266
- end
267
-
268
- # Fall back to custom provider validation
269
- provider_class = oauth_config[:provider]
270
- if provider_class.respond_to?(:validate_client)
271
- provider_class.validate_client(client_id, client_secret)
272
- elsif require_secret && client_secret.nil?
273
- raise InvalidClientError, "Client authentication required"
274
- else
275
- # In development, allow unregistered clients if configured
276
- return true if Rails.env.development? && oauth_config[:allow_unregistered_clients] != false
277
-
278
- raise InvalidClientError, "Unknown client"
279
- end
280
- end
281
-
282
- def validate_pkce(code_challenge, method, code_verifier)
283
- raise InvalidGrantError, "Code verifier required" unless code_verifier
284
-
285
- case method
286
- when "S256"
287
- expected_challenge = Base64.urlsafe_encode64(
288
- Digest::SHA256.digest(code_verifier), padding: false
289
- )
290
- raise InvalidGrantError, "Invalid code verifier" unless code_challenge == expected_challenge
291
- when "plain"
292
- raise InvalidGrantError, "Plain PKCE not allowed" unless oauth_config[:allow_plain_pkce]
293
- raise InvalidGrantError, "Invalid code verifier" unless code_challenge == code_verifier
294
- else
295
- raise InvalidGrantError, "Unsupported code challenge method"
296
- end
297
- end
298
-
299
- def validate_scope(scope)
300
- supported_scopes = oauth_config.fetch(:scopes_supported, [ "mcp:tools", "mcp:resources", "mcp:prompts" ])
301
- requested_scopes = scope.split(" ")
302
- unsupported = requested_scopes - supported_scopes
303
- return unless unsupported.any?
304
-
305
- raise InvalidScopeError, "Unsupported scopes: #{unsupported.join(', ')}"
306
- end
307
-
308
- def default_scope
309
- oauth_config.fetch(:default_scope, "mcp:tools mcp:resources mcp:prompts")
310
- end
311
-
312
- def generate_access_token(client_id:, scope:, user_id:)
313
- token = SecureRandom.urlsafe_base64(32)
314
-
315
- store_access_token(token, {
316
- client_id: client_id,
317
- scope: scope,
318
- user_id: user_id,
319
- created_at: Time.current,
320
- expires_at: token_expires_in.seconds.from_now
321
- })
322
-
323
- token
324
- end
325
-
326
- def generate_refresh_token(client_id:, scope:, user_id:, access_token:)
327
- token = SecureRandom.urlsafe_base64(32)
328
-
329
- store_refresh_token(token, {
330
- client_id: client_id,
331
- scope: scope,
332
- user_id: user_id,
333
- access_token: access_token,
334
- created_at: Time.current,
335
- expires_at: refresh_token_expires_in.seconds.from_now
336
- })
337
-
338
- token
339
- end
340
-
341
- def token_expires_in
342
- oauth_config.fetch(:access_token_expires_in, 3600) # 1 hour
343
- end
344
-
345
- def refresh_token_expires_in
346
- oauth_config.fetch(:refresh_token_expires_in, 7.days.to_i) # 1 week
347
- end
348
-
349
- # Storage methods - these delegate to a configurable storage backend
350
- def storage
351
- @storage ||= begin
352
- # Default to ActiveRecord storage for production, memory for test
353
- default_storage = Rails.env.test? ? "ActionMCP::OAuth::MemoryStorage" : "ActionMCP::OAuth::ActiveRecordStorage"
354
- storage_class = oauth_config.fetch(:storage, default_storage)
355
- storage_class = storage_class.constantize if storage_class.is_a?(String)
356
- storage_class.new
357
- end
358
- end
359
-
360
- def store_authorization_code(code, data)
361
- storage.store_authorization_code(code, data)
362
- end
363
-
364
- def retrieve_authorization_code(code)
365
- storage.retrieve_authorization_code(code)
366
- end
367
-
368
- def remove_authorization_code(code)
369
- storage.remove_authorization_code(code)
370
- end
371
-
372
- def store_access_token(token, data)
373
- storage.store_access_token(token, data)
374
- end
375
-
376
- def retrieve_access_token(token)
377
- storage.retrieve_access_token(token)
378
- end
379
-
380
- def remove_access_token(token)
381
- storage.remove_access_token(token)
382
- end
383
-
384
- def revoke_access_token(token)
385
- storage.remove_access_token(token)
386
- end
387
-
388
- def store_refresh_token(token, data)
389
- storage.store_refresh_token(token, data)
390
- end
391
-
392
- def retrieve_refresh_token(token)
393
- storage.retrieve_refresh_token(token)
394
- end
395
-
396
- def update_refresh_token(token, new_access_token)
397
- storage.update_refresh_token(token, new_access_token)
398
- end
399
-
400
- def revoke_refresh_token(token)
401
- storage.remove_refresh_token(token)
402
- end
403
- end
404
- end
405
- end
406
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActionMCP
4
- module OAuth
5
- # Load OAuth components
6
- autoload :Error, "action_mcp/oauth/error"
7
- autoload :Provider, "action_mcp/oauth/provider"
8
- autoload :Middleware, "action_mcp/oauth/middleware"
9
- autoload :MemoryStorage, "action_mcp/oauth/memory_storage"
10
- autoload :ActiveRecordStorage, "action_mcp/oauth/active_record_storage"
11
- end
12
- end