🔍

No recent searches

# class Gem::GemcutterUtilities::WebauthnListener

### Attributes

host [R]

### Public Class Methods

listener_thread (host, server)
Source

    # 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

new (host)
Source

    # File lib/rubygems/gemcutter_utilities/webauthn_listener.rb, line 31
    def initialize(host)
      @host = host
    end

### Public Instance Methods

wait_for_otp_code (server)
Source

    # 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

### Private Instance Methods

parse_otp_from_uri (uri)
Source

    # File lib/rubygems/gemcutter_utilities/webauthn_listener.rb, line 87
    def parse_otp_from_uri(uri)
      query = uri.query
      return unless query && !query.empty?

      query.split("&") do |param|
        key, value = param.split("=", 2)
        if value && Gem::URI.decode_www_form_component(key) == "code"
          return Gem::URI.decode_www_form_component(value)
        end
      end

      nil
    end

root_path? (uri)
Source

    # File lib/rubygems/gemcutter_utilities/webauthn_listener.rb, line 83
    def root_path?(uri)
      uri.path == "/"
    end