Class: McpToolkit::Auth::Authenticator

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

Overview

SATELLITE side. Resolves the authenticated, scoped context for a tool call:

1. Introspect the bearer token against the central app (cached).
2. Reject if invalid / expired.
3. Resolve the active central account id, enforcing tenancy:
   - accounts_user token  => its single bound `account_id`. A supplied
     selector, if present, MUST match it.
   - user (superuser) token => the selector is REQUIRED and MUST be one of
     the token's `account_ids`.
4. Map that central account id to the LOCAL scope root via
 `config.account_resolver` (e.g. Account.find_by(synced_id:)) and return
 it as the tools' `scope_root`.

The required scope (explicitly declared per resource via required_permissions_scope, or the registry default) is enforced separately by Tools::Base (#with_account / #with_authentication) via authorized_for_scope?; the authenticator only validates the token and resolves the tenant.

The account selector mirrors what a gateway forwards: the resolved account id arrives as _meta[config.account_meta_key]. We also accept an account_id tool argument and the config.account_id_header header as fallbacks.

Defined Under Namespace

Classes: Context

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token:, meta:, arguments:, header_account_id:, config: McpToolkit.config) ⇒ Authenticator

Returns a new instance of Authenticator.



37
38
39
40
41
42
43
# File 'lib/mcp_toolkit/auth/authenticator.rb', line 37

def initialize(token:, meta:, arguments:, header_account_id:, config: McpToolkit.config)
  @token = token
  @meta = (meta || {}).transform_keys(&:to_s)
  @arguments = (arguments || {}).transform_keys(&:to_s)
  @header_account_id = 
  @config = config
end

Class Method Details

.call(token:, meta: {}, arguments: {}, header_account_id: nil, config: McpToolkit.config) ⇒ Object

Parameters:

  • token (String)

    the plaintext bearer the central app forwarded

  • meta (Hash) (defaults to: {})

    the JSON-RPC _meta (string or symbol keys)

  • arguments (Hash) (defaults to: {})

    the tool-call arguments (may carry account_id)

  • header_account_id (Integer, String, nil) (defaults to: nil)

    the account-id header value

  • config (McpToolkit::Configuration) (defaults to: McpToolkit.config)


33
34
35
# File 'lib/mcp_toolkit/auth/authenticator.rb', line 33

def self.call(token:, meta: {}, arguments: {}, header_account_id: nil, config: McpToolkit.config)
  new(token:, meta:, arguments:, header_account_id:, config:).call
end

Instance Method Details

#callObject



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/mcp_toolkit/auth/authenticator.rb', line 45

def call
  introspection = McpToolkit::Auth::Introspection.call(token, config:)
  raise McpToolkit::Errors::Unauthorized, "invalid or expired token" unless introspection.valid?

   = (introspection)
  scope_root = config..call()
  unless scope_root
    raise McpToolkit::Errors::Unauthorized, "no local scope found for account_id=#{}"
  end

  Context.new(scope_root:, introspection:)
end