Class: Legate::Auth::Coordinator

Inherits:
Object
  • Object
show all
Defined in:
lib/legate/auth/coordinator.rb

Overview

Base class for authentication coordinators that handle the fiber-based authentication flow. Coordinators are responsible for managing the state of an authentication flow, including pausing execution, waiting for user input/authentication, and resuming with appropriate credentials.

Defined Under Namespace

Modules: Status

Constant Summary collapse

DEFAULT_TIMEOUT =

Default timeout for authentication flow (in seconds)

300

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scheme:, credential:, session_service:, token_store: nil, timeout: DEFAULT_TIMEOUT) ⇒ Coordinator

Initialize a new authentication coordinator

Parameters:



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/legate/auth/coordinator.rb', line 34

def initialize(scheme:, credential:, session_service:, token_store: nil, timeout: DEFAULT_TIMEOUT)
  @scheme = scheme
  @credential = credential
  @session_service = session_service
  @token_store = token_store || TokenStore.new(session_service)
  @timeout = timeout
  @request_id = SecureRandom.uuid
  @status = Status::PENDING
  @start_time = nil
  @auth_fiber = nil
  @result = nil
  @error = nil
end

Instance Attribute Details

#errorLegate::Auth::Error? (readonly)

Get the error that occurred during authentication, if any

Returns:



145
146
147
# File 'lib/legate/auth/coordinator.rb', line 145

def error
  @error
end

#resultLegate::Auth::ExchangedCredential? (readonly)

Get the result of the authentication flow

Returns:



149
150
151
# File 'lib/legate/auth/coordinator.rb', line 149

def result
  @result
end

#statusSymbol (readonly)

Get the current status of the authentication flow

Returns:

  • (Symbol)

    The current status



141
142
143
# File 'lib/legate/auth/coordinator.rb', line 141

def status
  @status
end

Instance Method Details

#cancel(reason = nil) ⇒ Boolean

Cancel the authentication flow

Parameters:

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

    Optional reason for cancellation

Returns:

  • (Boolean)

    True if the flow was successfully cancelled



130
131
132
133
134
135
136
137
# File 'lib/legate/auth/coordinator.rb', line 130

def cancel(reason = nil)
  return false unless @status == Status::PENDING

  @status = Status::CANCELLED
  @error = Legate::Auth::Error.new("Authentication cancelled#{reason ? ": #{reason}" : ''}")
  save_auth_state
  true
end

#complete?Boolean

Check if the authentication flow is complete

Returns:

  • (Boolean)

    True if the flow is complete (success or failure)



153
154
155
# File 'lib/legate/auth/coordinator.rb', line 153

def complete?
  @status != Status::PENDING
end

#resume(response) ⇒ Legate::Auth::ExchangedCredential?

Resume the authentication flow with a response from the client

Parameters:

  • response (Hash)

    The response from the client

Returns:

Raises:



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/legate/auth/coordinator.rb', line 83

def resume(response)
  raise Legate::Auth::Error, "Authentication flow is not in progress (status: #{@status})" unless @status == Status::PENDING

  # Check for timeout
  if @timeout && Time.now - @start_time > @timeout
    @status = Status::TIMEOUT
    @error = Legate::Auth::Error.new("Authentication timed out after #{@timeout} seconds")
    save_auth_state
    return nil
  end

  # Resume the fiber with the client response
  begin
    result = @auth_fiber.resume(response)

    # If the fiber yields again, we need more input from the client
    if @auth_fiber.alive?
      # Return the next authentication request
      return {
        request_id: @request_id,
        scheme_type: @scheme.scheme_type,
        auth_request: result
      }
    end

    # Authentication completed
    @status = Status::COMPLETED if @status == Status::PENDING
    save_auth_state

    # Store the token if we have one
    if @result && @result.is_a?(Legate::Auth::ExchangedCredential) && @token_store
      cache_key = generate_cache_key(@scheme, @credential)
      @token_store.store(cache_key, @result)
    end

    @result
  rescue StandardError => e
    @error = Legate::Auth::Error.new("Error resuming authentication: #{e.message}", e)
    @status = Status::FAILED
    save_auth_state
    nil
  end
end

#startHash

Start the authentication flow

Returns:

  • (Hash)

    The authentication request details to be sent to the client



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/legate/auth/coordinator.rb', line 50

def start
  # Create a new fiber for this authentication flow
  @auth_fiber = Fiber.new do
    @start_time = Time.now
    @result = authenticate
    @status = Status::COMPLETED
  rescue Legate::Auth::Error => e
    @error = e
    @status = Status::FAILED
    nil
  rescue StandardError => e
    @error = Legate::Auth::Error.new("Unexpected error during authentication: #{e.message}", e)
    @status = Status::FAILED
    nil
  end

  # Start the fiber to get the initial authentication request
  auth_request = @auth_fiber.resume

  # Record start of authentication in session
  save_auth_state

  # Return the authentication request to be sent to the client
  {
    request_id: @request_id,
    scheme_type: @scheme.scheme_type,
    auth_request: auth_request
  }
end

#success?Boolean

Check if the authentication flow is successful

Returns:

  • (Boolean)

    True if the flow completed successfully



159
160
161
# File 'lib/legate/auth/coordinator.rb', line 159

def success?
  @status == Status::COMPLETED && @result
end