summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJenny Shen <jenny.shen@shopify.com>2023-02-15 10:51:43 -0500
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2023-04-12 11:51:04 +0900
commit6e7bf0677d74a721e3be95e7e60d3033228bb73d (patch)
tree4e2e83fd95c1ffc15d314d6868c14732b51e6a3e /test
parent27322e51a757f0ac6d1fd66802e02978def9904f (diff)
downloadruby-6e7bf0677d74a721e3be95e7e60d3033228bb73d.tar.gz
[rubygems/rubygems] Add WebauthnListener class
https://github.com/rubygems/rubygems/commit/d42ddbb73c Co-authored-by: Ashley Ellis Pierce <anellis12@gmail.com> Co-authored-by: Jacques Chester <jacques.chester@shopify.com>
Diffstat (limited to 'test')
-rw-r--r--test/rubygems/test_webauthn_listener.rb120
1 files changed, 120 insertions, 0 deletions
diff --git a/test/rubygems/test_webauthn_listener.rb b/test/rubygems/test_webauthn_listener.rb
new file mode 100644
index 0000000000..5677546e42
--- /dev/null
+++ b/test/rubygems/test_webauthn_listener.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/webauthn_listener"
+
+class WebauthnListenerTest < Gem::TestCase
+ def setup
+ super
+ @server = TCPServer.new 0
+ @port = @server.addr[1].to_s
+ end
+
+ def test_wait_for_otp_code_get_follows_options
+ wait_for_otp_code
+ assert Gem::MockBrowser.options(URI("http://localhost:#{@port}?code=xyz")).is_a? Net::HTTPNoContent
+ assert Gem::MockBrowser.get(URI("http://localhost:#{@port}?code=xyz")).is_a? Net::HTTPOK
+ end
+
+ def test_wait_for_otp_code_options_request
+ wait_for_otp_code
+ response = Gem::MockBrowser.options URI("http://localhost:#{@port}?code=xyz")
+
+ assert response.is_a? Net::HTTPNoContent
+ assert_equal Gem.host, response["access-control-allow-origin"]
+ assert_equal "POST", response["access-control-allow-methods"]
+ assert_equal "Content-Type, Authorization, x-csrf-token", response["access-control-allow-headers"]
+ assert_equal "close", response["Connection"]
+ end
+
+ def test_wait_for_otp_code_get_request
+ wait_for_otp_code
+ response = Gem::MockBrowser.get URI("http://localhost:#{@port}?code=xyz")
+
+ assert response.is_a? Net::HTTPOK
+ assert_equal "text/plain", response["Content-Type"]
+ assert_equal "7", response["Content-Length"]
+ assert_equal Gem.host, response["access-control-allow-origin"]
+ assert_equal "POST", response["access-control-allow-methods"]
+ assert_equal "Content-Type, Authorization, x-csrf-token", response["access-control-allow-headers"]
+ assert_equal "close", response["Connection"]
+ assert_equal "success", response.body
+
+ @thread.join
+ assert_equal "xyz", @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_invalid_post_req_method
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Invalid HTTP method POST received.")
+ response = Gem::MockBrowser.post URI("http://localhost:#{@port}?code=xyz")
+
+ assert response
+ assert response.is_a? Net::HTTPMethodNotAllowed
+ assert_equal "GET, OPTIONS", response["allow"]
+ assert_equal "close", response["Connection"]
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_incorrect_path
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Page at /path not found.")
+ response = Gem::MockBrowser.post URI("http://localhost:#{@port}/path?code=xyz")
+
+ assert response.is_a? Net::HTTPNotFound
+ assert_equal "close", response["Connection"]
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_no_params_response
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.")
+ response = Gem::MockBrowser.get URI("http://localhost:#{@port}")
+
+ assert response.is_a? Net::HTTPBadRequest
+ assert_equal "text/plain", response["Content-Type"]
+ assert_equal "22", response["Content-Length"]
+ assert_equal "close", response["Connection"]
+ assert_equal "missing code parameter", response.body
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_incorrect_params
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.")
+ response = Gem::MockBrowser.get URI("http://localhost:#{@port}?param=xyz")
+
+ assert response.is_a? Net::HTTPBadRequest
+ assert_equal "text/plain", response["Content-Type"]
+ assert_equal "22", response["Content-Length"]
+ assert_equal "close", response["Connection"]
+ assert_equal "missing code parameter", response.body
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ private
+
+ def wait_for_otp_code
+ @thread = Thread.new do
+ Thread.current[:otp] = Gem::WebauthnListener.wait_for_otp_code(Gem.host, @server)
+ end
+ @thread.abort_on_exception = true
+ @thread.report_on_exception = false
+ end
+
+ def wait_for_otp_code_expect_error_with_message(message)
+ @thread = Thread.new do
+ error = assert_raise Gem::WebauthnVerificationError do
+ Thread.current[:otp] = Gem::WebauthnListener.wait_for_otp_code(Gem.host, @server)
+ end
+
+ assert_equal message, error.message
+ end
+ @thread.abort_on_exception = true
+ @thread.report_on_exception = false
+ end
+end