Class: Gem::WebauthnListener

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

Overview

The WebauthnListener Response class is used by the WebauthnListener to create responses to be sent to the Gem host. It creates a Net::HTTPResponse instance when initialized and can be converted to the appropriate format to be sent by a socket using ‘to_s`. Net::HTTPResponse instances cannot be directly sent over a socket.

Types of response classes:

- OkResponse
- NoContentResponse
- BadRequestResponse
- NotFoundResponse
- MethodNotAllowedResponse

Example usage:

server = TCPServer.new(0)
socket = server.accept

response = OkResponse.for("https://rubygems.example")
socket.print response.to_s
socket.close

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.



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

def initialize(host)
  @host = host
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



26
27
28
# File 'lib/rubygems/webauthn_listener.rb', line 26

def host
  @host
end

Class Method Details

.wait_for_otp_code(host, server) ⇒ Object



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

def self.wait_for_otp_code(host, server)
  new(host).fetch_otp_from_connection(server)
end

Instance Method Details

#fetch_otp_from_connection(server) ⇒ Object



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
66
67
# File 'lib/rubygems/webauthn_listener.rb', line 36

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

    method, req_uri, _protocol = request_line.split(" ")
    req_uri = 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