Class: Keycardai::OAuth::Loopback::CallbackServer

Inherits:
Object
  • Object
show all
Defined in:
lib/keycardai/oauth/authenticate.rb

Overview

A single-shot loopback HTTP server receiving the OAuth redirect.

Constant Summary collapse

PATH =
"/callback"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(port:) ⇒ CallbackServer

Returns a new instance of CallbackServer.



152
153
154
155
# File 'lib/keycardai/oauth/authenticate.rb', line 152

def initialize(port:)
  @server = TCPServer.new("127.0.0.1", port)
  @redirect_uri = "http://127.0.0.1:#{@server.addr[1]}#{PATH}"
end

Instance Attribute Details

#redirect_uriString (readonly)

Returns the redirect URI registered for this flow.

Returns:

  • (String)

    the redirect URI registered for this flow



141
142
143
# File 'lib/keycardai/oauth/authenticate.rb', line 141

def redirect_uri
  @redirect_uri
end

Class Method Details

.open(port:) ⇒ Object



143
144
145
146
147
148
149
150
# File 'lib/keycardai/oauth/authenticate.rb', line 143

def self.open(port:)
  server = new(port: port)
  begin
    yield server
  ensure
    server.close
  end
end

Instance Method Details

#closeObject



157
158
159
# File 'lib/keycardai/oauth/authenticate.rb', line 157

def close
  @server.close unless @server.closed?
end

#wait_for_code(state:, timeout:) ⇒ Object

Wait for the redirect, validate its state, and return the code.

Raises:



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/keycardai/oauth/authenticate.rb', line 166

def wait_for_code(state:, timeout:)
  deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
  loop do
    remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
    raise InteractionTimeoutError, "no redirect received within #{timeout}s" if remaining <= 0
    next unless @server.wait_readable(remaining)

    params = accept_redirect
    next unless params

    return validate(params, state)
  end
end