diff options
-rw-r--r-- | lib/rubygems/gemcutter_utilities.rb | 24 | ||||
-rw-r--r-- | test/rubygems/test_gem_gemcutter_utilities.rb | 11 |
2 files changed, 26 insertions, 9 deletions
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index 85ea26062f..3ee8579933 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -104,7 +104,7 @@ module Gem::GemcutterUtilities response = request_with_otp(method, uri, &block) if mfa_unauthorized?(response) - ask_otp(credentials) + fetch_otp(credentials) response = request_with_otp(method, uri, &block) end @@ -250,14 +250,28 @@ module Gem::GemcutterUtilities end end - def ask_otp(credentials) - if webauthn_url = webauthn_verification_url(credentials) - say "You have enabled multi-factor authentication. Please enter OTP code from your security device by visiting #{webauthn_url}." + def fetch_otp(credentials) + options[:otp] = if webauthn_url = webauthn_verification_url(credentials) + wait_for_otp(webauthn_url) else say "You have enabled multi-factor authentication. Please enter OTP code." + ask "Code: " end + end + + def wait_for_otp(webauthn_url) + thread = Thread.new do + Thread.current[:otp] = "Uvh6T57tkWuUnWYo" + end + thread.abort_on_exception = true + thread.report_on_exception = false + + url_with_port = "#{webauthn_url}?port=5678" + say "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device." - options[:otp] = ask "Code: " + thread.join + say "You are verified with a security device. You may close the browser window." + thread[:otp] end def webauthn_verification_url(credentials) diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index 7e10405110..aa876e6ca8 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -231,10 +231,10 @@ class TestGemGemcutterUtilities < Gem::TestCase assert_equal "111111", @fetcher.last_request["OTP"] end - def test_sign_in_with_webauthn_otp + def test_sign_in_with_webauthn_enabled webauthn_verification_url = "rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY" response_fail = "You have enabled multifactor authentication" - api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" + api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" util_sign_in(proc do @call_count ||= 0 @@ -243,9 +243,12 @@ class TestGemGemcutterUtilities < Gem::TestCase else HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK") end - end, nil, [], "111111\n", webauthn_verification_url) + end, nil, [], "", webauthn_verification_url) - assert_match "You have enabled multi-factor authentication. Please enter OTP code from your security device by visiting #{webauthn_verification_url}", @sign_in_ui.output + url_with_port = "#{webauthn_verification_url}?port=5678" + 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 util_sign_in(response, host = nil, args = [], extra_input = "", webauthn_url = nil) |