Skip to content

Commit c74e8ff

Browse files
committed
Support browserless environments
Uses out-of-band auth flow to obtain authorization code from separate browser.
1 parent 8d8f15a commit c74e8ff

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

lib/aws/google.rb

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
require 'googleauth'
66
require 'google/api_client/auth/storage'
77
require 'google/api_client/auth/storages/file_store'
8-
require 'google/api_client/auth/installed_app'
98

109
module Aws
1110
# An auto-refreshing credential provider that works by assuming
@@ -36,6 +35,9 @@ class << self
3635
# @option options [String] :external_id
3736
# @option options [STS::Client] :client STS::Client to use (default: create new client)
3837
# @option options [String] :profile AWS Profile to store temporary credentials (default `default`)
38+
# @option options [String] :domain G Suite domain for account-selection hint
39+
# @option options [String] :online if `true` only a temporary access token will be provided,
40+
# a long-lived refresh token will not be created and stored on the filesystem.
3941
# @option options [::Google::Auth::ClientId] :google_id
4042
def initialize(options = {})
4143
@oauth_attempted = false
@@ -50,6 +52,8 @@ def initialize(options = {})
5052
options[:google_client_secret]
5153
)
5254
@client = options[:client] || Aws::STS::Client.new(credentials: nil)
55+
@domain = options[:domain]
56+
@online = options[:online]
5357

5458
# Use existing AWS credentials stored in the shared config if available.
5559
# If this is `nil` or expired, #refresh will be called on the first AWS API service call
@@ -74,18 +78,38 @@ def google_client
7478
# Create an OAuth2 Client using Google's default browser-based OAuth InstalledAppFlow.
7579
# Store cached credentials to the standard Google Application Default Credentials location.
7680
# Ref: http://goo.gl/IUuyuX
81+
# @return [Signet::OAuth2::Client]
7782
def google_oauth
7883
return nil if @oauth_attempted
7984
@oauth_attempted = true
80-
require 'google/api_client/auth/installed_app'
81-
flow = ::Google::APIClient::InstalledAppFlow.new(
82-
client_id: @google_id.id,
83-
client_secret: @google_id.secret,
84-
scope: %w[email profile]
85-
)
85+
8686
path = "#{ENV['HOME']}/.config/#{::Google::Auth::CredentialsLoader::WELL_KNOWN_PATH}"
8787
FileUtils.mkdir_p(File.dirname(path))
88-
flow.authorize(GoogleStorage.new(::Google::APIClient::FileStore.new(path)))
88+
storage = GoogleStorage.new(::Google::APIClient::FileStore.new(path))
89+
90+
options = {
91+
client_id: @google_id.id,
92+
client_secret: @google_id.secret,
93+
scope: %w[openid email]
94+
}
95+
uri_options = {include_granted_scopes: true}
96+
uri_options[:hd] = @domain if @domain
97+
uri_options[:access_type] = 'online' if @online
98+
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))
112+
end
89113
end
90114

91115
def refresh

0 commit comments

Comments
 (0)