Class: McpToolkit::Auth::Introspection

Inherits:
Object
  • Object
show all
Defined in:
lib/mcp_toolkit/auth/introspection.rb

Overview

SATELLITE side. Authenticates the bearer token the central app forwards by calling the central app's introspection endpoint, with a short-TTL cache so a burst of tool calls in one session does not hammer the central app.

POST {central_app_url}{introspect_path}
Authorization: Bearer <token>

Response contract (the AUTHORITY emits this; see Auth::Authority):

{ valid: bool,
kind: <one of McpToolkit::TokenKinds — accounts-user or superuser>,
account_id: <id|null>,
account_ids: [...],
expires_at: <iso8601|null>,
scopes: [...] }   # OAuth-style `<app>__<action>` scopes a token carries

Authorization is purely scope-based: a token reaches a tool when it carries the scope that tool explicitly requires (declared per resource via required_permissions_scope, or the registry default; enforced in Tools::Base#with_account / #with_authentication via authorized_for_scope?).

The cache is keyed on a SHA-256 of the token (never the plaintext) so cached entries can't be reversed back to a usable credential from cache storage. The HTTP call itself is delegated to Auth::AuthorityServerClient.

Defined Under Namespace

Classes: Result

Constant Summary collapse

CACHE_PREFIX =
"mcp_toolkit:introspection:"
INVALID =
Result.new(valid: false).freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token, config: McpToolkit.config) ⇒ Introspection

Returns a new instance of Introspection.



108
109
110
111
# File 'lib/mcp_toolkit/auth/introspection.rb', line 108

def initialize(token, config: McpToolkit.config)
  @token = token
  @config = config
end

Class Method Details

.call(token, config: McpToolkit.config) ⇒ Object

Returns an Introspection::Result. Invalid/expired/unreachable => a result whose valid? is false. Caches positive AND negative results briefly.



104
105
106
# File 'lib/mcp_toolkit/auth/introspection.rb', line 104

def self.call(token, config: McpToolkit.config)
  new(token, config:).call
end

Instance Method Details

#callObject



113
114
115
116
117
118
119
120
121
122
# File 'lib/mcp_toolkit/auth/introspection.rb', line 113

def call
  return INVALID if token.to_s.empty?

  cached = cache.read(cache_key)
  return cached if cached

  result = fetch
  cache.write(cache_key, result, expires_in: config.introspection_cache_ttl)
  result
end