Class: RubyLLM::MCP::Auth::Flows::AuthorizationCodeFlow

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb

Overview

Orchestrates OAuth 2.1 Authorization Code flow with PKCE Coordinates session management, discovery, registration, and token exchange

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(discoverer:, client_registrar:, session_manager:, token_manager:, storage:, logger:) ⇒ AuthorizationCodeFlow

rubocop:disable Metrics/ParameterLists



12
13
14
15
16
17
18
19
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 12

def initialize(discoverer:, client_registrar:, session_manager:, token_manager:, storage:, logger:) # rubocop:disable Metrics/ParameterLists
  @discoverer = discoverer
  @client_registrar = client_registrar
  @session_manager = session_manager
  @token_manager = token_manager
  @storage = storage
  @logger = logger
end

Instance Attribute Details

#client_registrarObject (readonly)

Returns the value of attribute client_registrar.



10
11
12
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 10

def client_registrar
  @client_registrar
end

#discovererObject (readonly)

Returns the value of attribute discoverer.



10
11
12
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 10

def discoverer
  @discoverer
end

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 10

def logger
  @logger
end

#session_managerObject (readonly)

Returns the value of attribute session_manager.



10
11
12
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 10

def session_manager
  @session_manager
end

#storageObject (readonly)

Returns the value of attribute storage.



10
11
12
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 10

def storage
  @storage
end

#token_managerObject (readonly)

Returns the value of attribute token_manager.



10
11
12
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 10

def token_manager
  @token_manager
end

Instance Method Details

#complete(server_url, code, state) ⇒ Token

Complete OAuth authorization flow after callback

Parameters:

  • server_url (String)

    MCP server URL

  • code (String)

    authorization code from callback

  • state (String)

    state parameter from callback

Returns:

  • (Token)

    access token



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 72

def complete(server_url, code, state)
  logger.debug("Completing OAuth authorization flow")

  # 1. Validate state and retrieve session data
  session_data = session_manager.validate_and_retrieve_session(server_url, state)

  pkce = session_data[:pkce]
  client_info = session_data[:client_info]
   = discoverer.discover(server_url)

  unless pkce && client_info
    raise Errors::TransportError.new(message: "Missing PKCE or client info")
  end

  # 2. Exchange authorization code for tokens
  token = token_manager.exchange_authorization_code(
    ,
    client_info,
    code,
    pkce,
    server_url
  )

  # 3. Store token
  storage.set_token(server_url, token)

  # 4. Clean up temporary session data
  session_manager.cleanup_session(server_url)

  logger.info("OAuth authorization completed successfully")
  token
end

#start(server_url, redirect_uri, scope, resource_metadata: nil, https_validator: nil) ⇒ String

Start OAuth authorization flow

Parameters:

  • server_url (String)

    MCP server URL

  • redirect_uri (String)

    redirect URI for callback

  • scope (String, nil)

    requested scope

  • resource_metadata (String, nil) (defaults to: nil)

    explicit resource metadata URL hint

  • https_validator (Proc) (defaults to: nil)

    callback to validate HTTPS usage

Returns:

  • (String)

    authorization URL for user to visit

Raises:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb', line 28

def start(server_url, redirect_uri, scope, resource_metadata: nil, https_validator: nil)
  logger.debug("Starting OAuth authorization flow for #{server_url}")

  # 1. Discover authorization server
   = discoverer.discover(server_url, resource_metadata_url: )
  raise Errors::TransportError.new(message: "OAuth server discovery failed") unless 

  validate_pkce_support!()

  # 2. Register client (or get cached client)
  client_info = client_registrar.get_or_register(
    server_url,
    ,
    :authorization_code,
    redirect_uri,
    scope
  )

  # 3. Create session with PKCE and CSRF state
  session = session_manager.create_session(server_url)

  # 4. Validate HTTPS usage (optional warning)
  https_validator&.call(.authorization_endpoint, "Authorization endpoint")

  # 5. Build and return authorization URL
  auth_url = UrlBuilder.build_authorization_url(
    .authorization_endpoint,
    client_info.client_id,
    client_info..redirect_uris.first,
    scope,
    session[:state],
    session[:pkce],
    server_url
  )

  logger.debug("Authorization URL: #{auth_url}")
  auth_url
end