Class: Gem::GemcutterUtilities::WebauthnListener

Inherits:
Object
  • Object
show all
Defined in:
lib/rubygems/gemcutter_utilities/webauthn_listener.rb,
lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb
more...

Defined Under Namespace

Classes: BadRequestResponse, MethodNotAllowedResponse, NoContentResponse, NotFoundResponse, OkResponse, Response, SocketResponder

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host) ⇒ WebauthnListener

Returns a new instance of WebauthnListener.

[View source]

31
32
33
# File 'lib/rubygems/gemcutter_utilities/webauthn_listener.rb', line 31

def initialize(host)
  @host = host
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.


29
30
31
# File 'lib/rubygems/gemcutter_utilities/webauthn_listener.rb', line 29

def host
  @host
end

Class Method Details

.listener_thread(host, server) ⇒ Object

[View source]

35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/rubygems/gemcutter_utilities/webauthn_listener.rb', line 35

def self.listener_thread(host, server)
  Thread.new do
    thread = Thread.current
    thread.abort_on_exception = true
    thread.report_on_exception = false
    thread[:otp] = new(host).wait_for_otp_code(server)
  rescue Gem::WebauthnVerificationError => e
    thread[:error] = e
  ensure
    server.close
  end
end

Instance Method Details

#wait_for_otp_code(server) ⇒ Object

[View source]

48
49
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
79
# File 'lib/rubygems/gemcutter_utilities/webauthn_listener.rb', line 48

def wait_for_otp_code(server)
  loop do
    socket = server.accept
    request_line = socket.gets

    method, req_uri, _protocol = request_line.split(" ")
    req_uri = Gem::URI.parse(req_uri)

    responder = SocketResponder.new(socket)

    unless root_path?(req_uri)
      responder.send(NotFoundResponse.for(host))
      raise Gem::WebauthnVerificationError, "Page at #{req_uri.path} not found."
    end

    case method.upcase
    when "OPTIONS"
      responder.send(NoContentResponse.for(host))
      next # will be GET
    when "GET"
      if otp = parse_otp_from_uri(req_uri)
        responder.send(OkResponse.for(host))
        return otp
      end
      responder.send(BadRequestResponse.for(host))
      raise Gem::WebauthnVerificationError, "Did not receive OTP from #{host}."
    else
      responder.send(MethodNotAllowedResponse.for(host))
      raise Gem::WebauthnVerificationError, "Invalid HTTP method #{method.upcase} received."
    end
  end
end