summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/rubygems/gemcutter_utilities.rb8
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb59
2 files changed, 56 insertions, 11 deletions
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index 3ee8579933..c4f31dc0d6 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -2,6 +2,7 @@
require_relative "remote_fetcher"
require_relative "text"
+require_relative "webauthn_listener"
##
# Utility methods for using the RubyGems API.
@@ -260,13 +261,16 @@ module Gem::GemcutterUtilities
end
def wait_for_otp(webauthn_url)
+ server = TCPServer.new 0
+ port = server.addr[1].to_s
+
thread = Thread.new do
- Thread.current[:otp] = "Uvh6T57tkWuUnWYo"
+ Thread.current[:otp] = Gem::WebauthnListener.wait_for_otp_code(host, server)
end
thread.abort_on_exception = true
thread.report_on_exception = false
- url_with_port = "#{webauthn_url}?port=5678"
+ url_with_port = "#{webauthn_url}?port=#{port}"
say "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device."
thread.join
diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb
index aa876e6ca8..93aec0c67c 100644
--- a/test/rubygems/test_gem_gemcutter_utilities.rb
+++ b/test/rubygems/test_gem_gemcutter_utilities.rb
@@ -235,22 +235,63 @@ class TestGemGemcutterUtilities < Gem::TestCase
webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY"
response_fail = "You have enabled multifactor authentication"
api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903"
-
- util_sign_in(proc do
- @call_count ||= 0
- if (@call_count += 1).odd?
- HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized")
- else
- HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK")
+ port = 5678
+ server = TCPServer.new(port)
+
+ TCPServer.stub(:new, server) do
+ Gem::WebauthnListener.stub(:wait_for_otp_code, "Uvh6T57tkWuUnWYo") do
+ util_sign_in(proc do
+ @call_count ||= 0
+ if (@call_count += 1).odd?
+ HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized")
+ else
+ HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK")
+ end
+ end, nil, [], "", webauthn_verification_url)
end
- end, nil, [], "", webauthn_verification_url)
+ ensure
+ server.close
+ end
- url_with_port = "#{webauthn_verification_url}?port=5678"
+ url_with_port = "#{webauthn_verification_url}?port=#{port}"
assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @sign_in_ui.output
assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output
assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
end
+ def test_sign_in_with_webauthn_enabled_with_error
+ webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY"
+ response_fail = "You have enabled multifactor authentication"
+ api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903"
+ port = 5678
+ server = TCPServer.new(port)
+ raise_error = ->(*_args) { raise Gem::WebauthnVerificationError, "Something went wrong" }
+
+ error = assert_raise Gem::WebauthnVerificationError do
+ TCPServer.stub(:new, server) do
+ Gem::WebauthnListener.stub(:wait_for_otp_code, raise_error) do
+ util_sign_in(proc do
+ @call_count ||= 0
+ if (@call_count += 1).odd?
+ HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized")
+ else
+ HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK")
+ end
+ end, nil, [], "", webauthn_verification_url)
+ end
+ ensure
+ server.close
+ end
+ end
+
+ assert_equal "Security device verification failed: Something went wrong", error.message
+
+ url_with_port = "#{webauthn_verification_url}?port=#{port}"
+ assert_match "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device.", @sign_in_ui.output
+ refute_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output
+ refute_match "Signed in with API key:", @sign_in_ui.output
+ end
+
def util_sign_in(response, host = nil, args = [], extra_input = "", webauthn_url = nil)
email = "you@example.com"
password = "secret"