Skip to content

Commit 5873534

Browse files
committed
add better out-of-band fallback logic
Ensure fallback if launchy browser command exits with failure error code.
1 parent 8e715d9 commit 5873534

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

lib/aws/google.rb

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class << self
3838
# @option options [String] :domain G Suite domain for account-selection hint
3939
# @option options [String] :online if `true` only a temporary access token will be provided,
4040
# a long-lived refresh token will not be created and stored on the filesystem.
41+
# @option options [String] :port port for local server to listen on to capture oauth browser redirect.
42+
# Defaults to an out-of-band authentication process.
4143
# @option options [::Google::Auth::ClientId] :google_id
4244
def initialize(options = {})
4345
@oauth_attempted = false
@@ -54,6 +56,7 @@ def initialize(options = {})
5456
@client = options[:client] || Aws::STS::Client.new(credentials: nil)
5557
@domain = options[:domain]
5658
@online = options[:online]
59+
@port = options[:port]
5760

5861
# Use existing AWS credentials stored in the shared config if available.
5962
# If this is `nil` or expired, #refresh will be called on the first AWS API service call
@@ -96,20 +99,50 @@ def google_oauth
9699
uri_options[:hd] = @domain if @domain
97100
uri_options[:access_type] = 'online' if @online
98101

99-
require 'google/api_client/auth/installed_app'
100-
if defined?(Launchy) && Launchy::Application::Browser.new.app_list.any?
101-
::Google::APIClient::InstalledAppFlow.new(options).authorize(storage, uri_options)
102-
else
103-
credentials = ::Google::Auth::UserRefreshCredentials.new(
104-
options.merge(redirect_uri: 'urn:ietf:wg:oauth:2.0:oob')
105-
)
106-
url = credentials.authorization_uri(uri_options)
107-
print 'Open the following URL in the browser and enter the ' \
108-
"resulting code after authorization:\n#{url}\n> "
109-
credentials.code = gets
110-
credentials.fetch_access_token!
111-
credentials.tap(&storage.method(:write_credentials))
102+
credentials = ::Google::Auth::UserRefreshCredentials.new(options)
103+
credentials.code = get_oauth_code(credentials, uri_options)
104+
credentials.fetch_access_token!
105+
credentials.tap(&storage.method(:write_credentials))
106+
end
107+
108+
def get_oauth_code(client, options)
109+
raise 'fallback' unless @port
110+
require 'launchy'
111+
require 'webrick'
112+
code = nil
113+
server = WEBrick::HTTPServer.new(
114+
Port: @port,
115+
Logger: WEBrick::Log.new(STDOUT, 0),
116+
AccessLog: []
117+
)
118+
server.mount_proc '/' do |req, res|
119+
code = req.query['code']
120+
res.status = 202
121+
res.body = 'Login successful, you may close this browser window.'
122+
server.stop
112123
end
124+
trap('INT') { server.shutdown }
125+
client.redirect_uri = "http://localhost:#{@port}"
126+
launchy = Launchy.open(client.authorization_uri(options).to_s)
127+
server_thread = Thread.new do
128+
begin
129+
server.start
130+
ensure server.shutdown
131+
end
132+
end
133+
while server_thread.alive?
134+
raise 'fallback' if !launchy.alive? && !launchy.value.success?
135+
sleep 0.1
136+
end
137+
code || raise('fallback')
138+
rescue StandardError
139+
trap('INT', 'DEFAULT')
140+
# Fallback to out-of-band authentication if browser launch failed.
141+
client.redirect_uri = 'oob'
142+
url = client.authorization_uri(options)
143+
print "\nOpen the following URL in a browser and enter the " \
144+
"resulting code after authorization:\n#{url}\n> "
145+
gets
113146
end
114147

115148
def refresh

lib/aws/google/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Aws
22
class Google
3-
VERSION = '0.1.0'.freeze
3+
VERSION = '0.1.1'.freeze
44
end
55
end

0 commit comments

Comments
 (0)