googleauth 0.5.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +5 -4
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +36 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  5. data/.github/ISSUE_TEMPLATE/support_request.md +7 -0
  6. data/.kokoro/build.bat +16 -0
  7. data/.kokoro/build.sh +4 -0
  8. data/.kokoro/continuous/common.cfg +24 -0
  9. data/.kokoro/continuous/linux.cfg +25 -0
  10. data/.kokoro/continuous/osx.cfg +8 -0
  11. data/.kokoro/continuous/post.cfg +30 -0
  12. data/.kokoro/continuous/windows.cfg +29 -0
  13. data/.kokoro/osx.sh +4 -0
  14. data/.kokoro/presubmit/common.cfg +24 -0
  15. data/.kokoro/presubmit/linux.cfg +24 -0
  16. data/.kokoro/presubmit/osx.cfg +8 -0
  17. data/.kokoro/presubmit/windows.cfg +29 -0
  18. data/.kokoro/release.cfg +94 -0
  19. data/.kokoro/trampoline.bat +10 -0
  20. data/.kokoro/trampoline.sh +4 -0
  21. data/.repo-metadata.json +5 -0
  22. data/.rubocop.yml +17 -1
  23. data/CHANGELOG.md +90 -19
  24. data/CODE_OF_CONDUCT.md +43 -0
  25. data/Gemfile +16 -13
  26. data/README.md +58 -18
  27. data/Rakefile +106 -10
  28. data/googleauth.gemspec +27 -25
  29. data/lib/googleauth/application_default.rb +81 -0
  30. data/lib/googleauth/client_id.rb +21 -19
  31. data/lib/googleauth/compute_engine.rb +40 -43
  32. data/lib/googleauth/credentials.rb +375 -0
  33. data/lib/googleauth/credentials_loader.rb +117 -43
  34. data/lib/googleauth/default_credentials.rb +93 -0
  35. data/lib/googleauth/iam.rb +11 -11
  36. data/lib/googleauth/json_key_reader.rb +46 -0
  37. data/lib/googleauth/scope_util.rb +12 -12
  38. data/lib/googleauth/service_account.rb +64 -62
  39. data/lib/googleauth/signet.rb +53 -12
  40. data/lib/googleauth/stores/file_token_store.rb +8 -8
  41. data/lib/googleauth/stores/redis_token_store.rb +22 -22
  42. data/lib/googleauth/token_store.rb +6 -6
  43. data/lib/googleauth/user_authorizer.rb +80 -68
  44. data/lib/googleauth/user_refresh.rb +44 -35
  45. data/lib/googleauth/version.rb +1 -1
  46. data/lib/googleauth/web_user_authorizer.rb +77 -68
  47. data/lib/googleauth.rb +6 -96
  48. data/rakelib/devsite_builder.rb +45 -0
  49. data/rakelib/link_checker.rb +64 -0
  50. data/rakelib/repo_metadata.rb +59 -0
  51. data/spec/googleauth/apply_auth_examples.rb +47 -46
  52. data/spec/googleauth/client_id_spec.rb +75 -55
  53. data/spec/googleauth/compute_engine_spec.rb +60 -43
  54. data/spec/googleauth/credentials_spec.rb +467 -0
  55. data/spec/googleauth/get_application_default_spec.rb +149 -111
  56. data/spec/googleauth/iam_spec.rb +25 -25
  57. data/spec/googleauth/scope_util_spec.rb +26 -24
  58. data/spec/googleauth/service_account_spec.rb +261 -143
  59. data/spec/googleauth/signet_spec.rb +93 -30
  60. data/spec/googleauth/stores/file_token_store_spec.rb +12 -13
  61. data/spec/googleauth/stores/redis_token_store_spec.rb +11 -11
  62. data/spec/googleauth/stores/store_examples.rb +16 -16
  63. data/spec/googleauth/user_authorizer_spec.rb +153 -124
  64. data/spec/googleauth/user_refresh_spec.rb +186 -121
  65. data/spec/googleauth/web_user_authorizer_spec.rb +82 -69
  66. data/spec/spec_helper.rb +21 -19
  67. metadata +75 -32
  68. data/.rubocop_todo.yml +0 -32
  69. data/.travis.yml +0 -37
data/Gemfile CHANGED
@@ -1,24 +1,27 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in googleauth.gemspec
4
4
  gemspec
5
5
 
6
6
  group :development do
7
- gem 'bundler', '~> 1.9'
8
- gem 'simplecov', '~> 0.9'
9
- gem 'coveralls', '~> 0.7'
10
- gem 'fakefs', '~> 0.6'
11
- gem 'rake', '~> 10.0'
12
- gem 'rubocop', '~> 0.30'
13
- gem 'rspec', '~> 3.0'
14
- gem 'redis', '~> 3.2'
15
- gem 'fakeredis', '~> 0.5'
16
- gem 'webmock', '~> 1.21'
17
- gem 'rack-test', '~> 0.6'
18
- gem 'sinatra'
7
+ gem "bundler", ">= 1.9"
8
+ gem "coveralls", "~> 0.7"
9
+ gem "fakefs", "~> 0.6"
10
+ gem "fakeredis", "~> 0.5"
11
+ gem "google-style", "~> 1.24.0"
12
+ gem "logging", "~> 2.0"
13
+ gem "rack-test", "~> 0.6"
14
+ gem "rake", "~> 10.0"
15
+ gem "redis", "~> 3.2"
16
+ gem "rspec", "~> 3.0"
17
+ gem "simplecov", "~> 0.9"
18
+ gem "sinatra"
19
+ gem "webmock", "~> 1.21"
19
20
  end
20
21
 
21
22
  platforms :jruby do
22
23
  group :development do
23
24
  end
24
25
  end
26
+
27
+ gem "gems", "~> 1.2"
data/README.md CHANGED
@@ -1,16 +1,13 @@
1
1
  # Google Auth Library for Ruby
2
2
 
3
3
  <dl>
4
- <dt>Homepage</dt><dd><a href="http://www.github.com/google/google-auth-library-ruby">http://www.github.com/google/google-auth-library-ruby</a></dd>
4
+ <dt>Homepage</dt><dd><a href="http://www.github.com/googleapis/google-auth-library-ruby">http://www.github.com/googleapis/google-auth-library-ruby</a></dd>
5
5
  <dt>Authors</dt><dd><a href="mailto:temiola@google.com">Tim Emiola</a></dd>
6
6
  <dt>Copyright</dt><dd>Copyright © 2015 Google, Inc.</dd>
7
7
  <dt>License</dt><dd>Apache 2.0</dd>
8
8
  </dl>
9
9
 
10
10
  [![Gem Version](https://badge.fury.io/rb/googleauth.svg)](http://badge.fury.io/rb/googleauth)
11
- [![Build Status](https://secure.travis-ci.org/google/google-auth-library-ruby.png)](http://travis-ci.org/google/google-auth-library-ruby)
12
- [![Coverage Status](https://coveralls.io/repos/google/google-auth-library-ruby/badge.png)](https://coveralls.io/r/google/google-auth-library-ruby)
13
- [![Dependency Status](https://gemnasium.com/google/google-auth-library-ruby.png)](https://gemnasium.com/google/google-auth-library-ruby)
14
11
 
15
12
  ## Description
16
13
 
@@ -70,7 +67,7 @@ a generic authorizer useful for command line apps or custom integrations as
70
67
  well as a web variant tailored toward Rack-based applications.
71
68
 
72
69
  The authorizers are intended for authorization use cases. For sign-on,
73
- see [Google Idenity Platform](https://developers.google.com/identity/)
70
+ see [Google Identity Platform](https://developers.google.com/identity/)
74
71
 
75
72
  ### Example (Web)
76
73
 
@@ -92,7 +89,7 @@ get('/authorize') do
92
89
  user_id = request.session['user_id']
93
90
  credentials = authorizer.get_credentials(user_id, request)
94
91
  if credentials.nil?
95
- redirect authorizer.get_authorization_url(user_id: user_id, request: request)
92
+ redirect authorizer.get_authorization_url(login_hint: user_id, request: request)
96
93
  end
97
94
  # Credentials are valid, can call APIs
98
95
  # ...
@@ -111,6 +108,8 @@ end
111
108
  require 'googleauth'
112
109
  require 'googleauth/stores/file_token_store'
113
110
 
111
+ OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'
112
+
114
113
  scope = 'https://www.googleapis.com/auth/drive'
115
114
  client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
116
115
  token_store = Google::Auth::Stores::FileTokenStore.new(
@@ -119,7 +118,7 @@ authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)
119
118
 
120
119
  credentials = authorizer.get_credentials(user_id)
121
120
  if credentials.nil?
122
- url = authorizer.get_authorization_url(base_url: 'urn:ietf:wg:oauth:2.0:oob')
121
+ url = authorizer.get_authorization_url(base_url: OOB_URI )
123
122
  puts "Open #{url} in your browser and enter the resulting code:"
124
123
  code = gets
125
124
  credentials = authorizer.get_and_store_credentials_from_code(
@@ -129,6 +128,47 @@ end
129
128
  # OK to use credentials
130
129
  ```
131
130
 
131
+ ### Example (Service Account)
132
+
133
+ ```ruby
134
+ scope = 'https://www.googleapis.com/auth/androidpublisher'
135
+
136
+ authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
137
+ json_key_io: File.open('/path/to/service_account_json_key.json'),
138
+ scope: scope)
139
+
140
+ authorizer.fetch_access_token!
141
+ ```
142
+
143
+ ### Example (Environment Variables)
144
+
145
+ ```bash
146
+ export GOOGLE_ACCOUNT_TYPE=service_account
147
+ export GOOGLE_CLIENT_ID=000000000000000000000
148
+ export GOOGLE_CLIENT_EMAIL=xxxx@xxxx.iam.gserviceaccount.com
149
+ export GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
150
+ ```
151
+
152
+ ```ruby
153
+ require 'googleauth'
154
+ require 'google/apis/drive_v3'
155
+
156
+ Drive = ::Google::Apis::DriveV3
157
+ drive = Drive::DriveService.new
158
+
159
+ # Auths with ENV vars:
160
+ # "GOOGLE_CLIENT_ID",
161
+ # "GOOGLE_CLIENT_EMAIL",
162
+ # "GOOGLE_ACCOUNT_TYPE",
163
+ # "GOOGLE_PRIVATE_KEY"
164
+ auth = ::Google::Auth::ServiceAccountCredentials
165
+ .make_creds(scope: 'https://www.googleapis.com/auth/drive')
166
+ drive.authorization = auth
167
+
168
+ list_files = drive.list_files()
169
+
170
+ ```
171
+
132
172
  ### Storage
133
173
 
134
174
  Authorizers require a storage instance to manage long term persistence of
@@ -138,15 +178,16 @@ access and refresh tokens. Two storage implementations are included:
138
178
  * Google::Auth::Stores::RedisTokenStore
139
179
 
140
180
  Custom storage implementations can also be used. See
141
- [token_store.rb](lib/googleauth/token_store.rb) for additional details.
181
+ [token_store.rb](https://googleapis.dev/ruby/googleauth/latest/Google/Auth/TokenStore.html) for additional details.
182
+
183
+ ## Supported Ruby Versions
142
184
 
143
- ## What about auth in google-apis-ruby-client?
185
+ This library requires Ruby 2.4 or later.
144
186
 
145
- The goal is for all auth done by
146
- [google-apis-ruby-client][google-apis-ruby-client] to be performed by this
147
- library. I.e, eventually google-apis-ruby-client will just take a dependency
148
- on this library. This update is a work in progress, but should be completed
149
- by Q2 2015.
187
+ In general, this library supports Ruby versions that are considered current and
188
+ supported by Ruby Core (that is, Ruby versions that are either in normal
189
+ maintenance or in security maintenance).
190
+ See https://www.ruby-lang.org/en/downloads/branches/ for further details.
150
191
 
151
192
  ## License
152
193
 
@@ -165,7 +206,6 @@ hesitate to
165
206
  [ask questions](http://stackoverflow.com/questions/tagged/google-auth-library-ruby)
166
207
  about the client or APIs on [StackOverflow](http://stackoverflow.com).
167
208
 
168
- [google-apis-ruby-client]: (https://github.com/google/google-api-ruby-client)
169
- [application default credentials]: (https://developers.google.com/accounts/docs/application-default-credentials)
170
- [contributing]: https://github.com/google/google-auth-library-ruby/tree/master/CONTRIBUTING.md
171
- [copying]: https://github.com/google/google-auth-library-ruby/tree/master/COPYING
209
+ [application default credentials]: https://developers.google.com/accounts/docs/application-default-credentials
210
+ [contributing]: https://github.com/googleapis/google-auth-library-ruby/tree/master/.github/CONTRIBUTING.md
211
+ [copying]: https://github.com/googleapis/google-auth-library-ruby/tree/master/COPYING
data/Rakefile CHANGED
@@ -1,15 +1,111 @@
1
1
  # -*- ruby -*-
2
- require 'rspec/core/rake_task'
3
- require 'rubocop/rake_task'
4
- require 'bundler/gem_tasks'
2
+ require "json"
3
+ require "bundler/gem_tasks"
5
4
 
6
- desc 'Run Rubocop to check for style violations'
7
- RuboCop::RakeTask.new
5
+ task :ci do
6
+ header "Using Ruby - #{RUBY_VERSION}"
7
+ sh "bundle exec rubocop"
8
+ sh "bundle exec rspec"
9
+ end
8
10
 
9
- desc 'Run rake task'
10
- RSpec::Core::RakeTask.new(:spec)
11
+ task :release_gem, :tag do |_t, args|
12
+ tag = args[:tag]
13
+ raise "You must provide a tag to release." if tag.nil?
11
14
 
12
- desc 'Does rubocop lint and runs the specs'
13
- task all: [:rubocop, :spec]
15
+ # Verify the tag format "vVERSION"
16
+ m = tag.match /v(?<version>\S*)/
17
+ raise "Tag #{tag} does not match the expected format." if m.nil?
14
18
 
15
- task default: :all
19
+ version = m[:version]
20
+ raise "You must provide a version." if version.nil?
21
+
22
+ api_token = ENV["RUBYGEMS_API_TOKEN"]
23
+
24
+ require "gems"
25
+ if api_token
26
+ ::Gems.configure do |config|
27
+ config.key = api_token
28
+ end
29
+ end
30
+
31
+ Bundler.with_clean_env do
32
+ sh "rm -rf pkg"
33
+ sh "bundle update"
34
+ sh "bundle exec rake build"
35
+ end
36
+
37
+ path_to_be_pushed = "pkg/googleauth-#{version}.gem"
38
+ gem_was_published = nil
39
+ if File.file? path_to_be_pushed
40
+ begin
41
+ response = ::Gems.push File.new(path_to_be_pushed)
42
+ puts response
43
+ raise unless response.include? "Successfully registered gem:"
44
+ gem_was_published = true
45
+ puts "Successfully built and pushed googleauth for version #{version}"
46
+ rescue StandardError => e
47
+ gem_was_published = false
48
+ puts "Error while releasing googleauth version #{version}: #{e.message}"
49
+ end
50
+ else
51
+ raise "Cannot build googleauth for version #{version}"
52
+ end
53
+
54
+ Rake::Task["kokoro:publish_docs"].invoke if gem_was_published
55
+ end
56
+
57
+ namespace :kokoro do
58
+ task :load_env_vars do
59
+ service_account = "#{ENV['KOKORO_GFILE_DIR']}/service-account.json"
60
+ ENV["GOOGLE_APPLICATION_CREDENTIALS"] = service_account
61
+ filename = "#{ENV['KOKORO_GFILE_DIR']}/env_vars.json"
62
+ env_vars = JSON.parse File.read(filename)
63
+ env_vars.each { |k, v| ENV[k] = v }
64
+ end
65
+
66
+ task :presubmit do
67
+ Rake::Task["ci"].invoke
68
+ end
69
+
70
+ task :continuous do
71
+ Rake::Task["ci"].invoke
72
+ end
73
+
74
+ task :post do
75
+ require_relative "rakelib/link_checker.rb"
76
+
77
+ link_checker = LinkChecker.new
78
+ link_checker.run
79
+ exit link_checker.exit_status
80
+ end
81
+
82
+ task :nightly do
83
+ Rake::Task["ci"].invoke
84
+ end
85
+
86
+ task :release do
87
+ version = "0.1.0"
88
+ Bundler.with_clean_env do
89
+ version = `bundle exec gem list`
90
+ .split("\n").select { |line| line.include? "googleauth" }
91
+ .first.split("(").last.split(")").first || "0.1.0"
92
+ end
93
+ Rake::Task["kokoro:load_env_vars"].invoke
94
+ Rake::Task["release_gem"].invoke "v#{version}"
95
+ end
96
+
97
+ task :publish_docs do
98
+ require_relative "rakelib/devsite_builder.rb"
99
+
100
+ DevsiteBuilder.new(__dir__).publish
101
+ end
102
+ end
103
+
104
+ def header str, token = "#"
105
+ line_length = str.length + 8
106
+ puts ""
107
+ puts token * line_length
108
+ puts "#{token * 3} #{str} #{token * 3}"
109
+ puts token * line_length
110
+ puts ""
111
+ end
data/googleauth.gemspec CHANGED
@@ -1,35 +1,37 @@
1
1
  # -*- ruby -*-
2
2
  # encoding: utf-8
3
- $LOAD_PATH.push File.expand_path('../lib', __FILE__)
4
- require 'googleauth/version'
5
3
 
6
- Gem::Specification.new do |s|
7
- s.name = 'googleauth'
8
- s.version = Google::Auth::VERSION
9
- s.authors = ['Tim Emiola']
10
- s.email = 'temiola@google.com'
11
- s.homepage = 'https://github.com/google/google-auth-library-ruby'
12
- s.summary = 'Google Auth Library for Ruby'
13
- s.license = 'Apache-2.0'
14
- s.description = <<-eos
4
+ $LOAD_PATH.push File.expand_path("lib", __dir__)
5
+ require "googleauth/version"
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = "googleauth"
9
+ gem.version = Google::Auth::VERSION
10
+ gem.authors = ["Tim Emiola"]
11
+ gem.email = "temiola@google.com"
12
+ gem.homepage = "https://github.com/google/google-auth-library-ruby"
13
+ gem.summary = "Google Auth Library for Ruby"
14
+ gem.license = "Apache-2.0"
15
+ gem.description = <<-DESCRIPTION
15
16
  Allows simple authorization for accessing Google APIs.
16
17
  Provide support for Application Default Credentials, as described at
17
18
  https://developers.google.com/accounts/docs/application-default-credentials
18
- eos
19
+ DESCRIPTION
19
20
 
20
- s.files = `git ls-files`.split("\n")
21
- s.test_files = `git ls-files -- spec/*`.split("\n")
22
- s.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f|
23
- File.basename(f)
21
+ gem.files = `git ls-files`.split "\n"
22
+ gem.test_files = `git ls-files -- spec/*`.split "\n"
23
+ gem.executables = `git ls-files -- bin/*.rb`.split("\n").map do |f|
24
+ File.basename f
24
25
  end
25
- s.require_paths = ['lib']
26
- s.platform = Gem::Platform::RUBY
26
+ gem.require_paths = ["lib"]
27
+ gem.platform = Gem::Platform::RUBY
28
+ gem.required_ruby_version = ">= 2.4.0"
27
29
 
28
- s.add_dependency 'faraday', '~> 0.9'
29
- s.add_dependency 'logging', '~> 2.0'
30
- s.add_dependency 'jwt', '~> 1.4'
31
- s.add_dependency 'memoist', '~> 0.12'
32
- s.add_dependency 'multi_json', '~> 1.11'
33
- s.add_dependency 'os', '~> 0.9'
34
- s.add_dependency 'signet', '~> 0.7'
30
+ gem.add_dependency "faraday", ">= 0.17.3", "< 2.0"
31
+ gem.add_dependency "jwt", ">= 1.4", "< 3.0"
32
+ gem.add_dependency "memoist", "~> 0.16"
33
+ gem.add_dependency "multi_json", "~> 1.11"
34
+ gem.add_dependency "os", ">= 0.9", "< 2.0"
35
+ gem.add_dependency "signet", "~> 0.12"
36
+ gem.add_development_dependency "yard", "~> 0.9"
35
37
  end
@@ -0,0 +1,81 @@
1
+ # Copyright 2015, Google Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are
6
+ # met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above
11
+ # copyright notice, this list of conditions and the following disclaimer
12
+ # in the documentation and/or other materials provided with the
13
+ # distribution.
14
+ # * Neither the name of Google Inc. nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ require "googleauth/compute_engine"
31
+ require "googleauth/default_credentials"
32
+
33
+ module Google
34
+ # Module Auth provides classes that provide Google-specific authorization
35
+ # used to access Google APIs.
36
+ module Auth
37
+ NOT_FOUND_ERROR = <<~ERROR_MESSAGE.freeze
38
+ Could not load the default credentials. Browse to
39
+ https://developers.google.com/accounts/docs/application-default-credentials
40
+ for more information
41
+ ERROR_MESSAGE
42
+
43
+ module_function
44
+
45
+ # Obtains the default credentials implementation to use in this
46
+ # environment.
47
+ #
48
+ # Use this to obtain the Application Default Credentials for accessing
49
+ # Google APIs. Application Default Credentials are described in detail
50
+ # at https://cloud.google.com/docs/authentication/production.
51
+ #
52
+ # If supplied, scope is used to create the credentials instance, when it can
53
+ # be applied. E.g, on google compute engine and for user credentials the
54
+ # scope is ignored.
55
+ #
56
+ # @param scope [string|array|nil] the scope(s) to access
57
+ # @param options [Hash] Connection options. These may be used to configure
58
+ # the `Faraday::Connection` used for outgoing HTTP requests. For
59
+ # example, if a connection proxy must be used in the current network,
60
+ # you may provide a connection with with the needed proxy options.
61
+ # The following keys are recognized:
62
+ # * `:default_connection` The connection object to use for token
63
+ # refresh requests.
64
+ # * `:connection_builder` A `Proc` that creates and returns a
65
+ # connection to use for token refresh requests.
66
+ # * `:connection` The connection to use to determine whether GCE
67
+ # metadata credentials are available.
68
+ def get_application_default scope = nil, options = {}
69
+ creds = DefaultCredentials.from_env(scope, options) ||
70
+ DefaultCredentials.from_well_known_path(scope, options) ||
71
+ DefaultCredentials.from_system_default_path(scope, options)
72
+ return creds unless creds.nil?
73
+ unless GCECredentials.on_gce? options
74
+ # Clear cache of the result of GCECredentials.on_gce?
75
+ GCECredentials.unmemoize_all
76
+ raise NOT_FOUND_ERROR
77
+ end
78
+ GCECredentials.new
79
+ end
80
+ end
81
+ end
@@ -27,19 +27,20 @@
27
27
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
- require 'multi_json'
30
+ require "multi_json"
31
+ require "googleauth/credentials_loader"
31
32
 
32
33
  module Google
33
34
  module Auth
34
35
  # Representation of an application's identity for user authorization
35
36
  # flows.
36
37
  class ClientId
37
- INSTALLED_APP = 'installed'
38
- WEB_APP = 'web'
39
- CLIENT_ID = 'client_id'
40
- CLIENT_SECRET = 'client_secret'
38
+ INSTALLED_APP = "installed".freeze
39
+ WEB_APP = "web".freeze
40
+ CLIENT_ID = "client_id".freeze
41
+ CLIENT_SECRET = "client_secret".freeze
41
42
  MISSING_TOP_LEVEL_ELEMENT_ERROR =
42
- "Expected top level property 'installed' or 'web' to be present."
43
+ "Expected top level property 'installed' or 'web' to be present.".freeze
43
44
 
44
45
  # Text identifier of the client ID
45
46
  # @return [String]
@@ -62,25 +63,26 @@ module Google
62
63
  # @note Direction instantion is discouraged to avoid embedding IDs
63
64
  # & secrets in source. See {#from_file} to load from
64
65
  # `client_secrets.json` files.
65
- def initialize(id, secret)
66
- fail 'Client id can not be nil' if id.nil?
67
- fail 'Client secret can not be nil' if secret.nil?
66
+ def initialize id, secret
67
+ CredentialsLoader.warn_if_cloud_sdk_credentials id
68
+ raise "Client id can not be nil" if id.nil?
69
+ raise "Client secret can not be nil" if secret.nil?
68
70
  @id = id
69
71
  @secret = secret
70
72
  end
71
73
 
72
- # Constructs a Client ID from a JSON file downloaed from the
74
+ # Constructs a Client ID from a JSON file downloaded from the
73
75
  # Google Developers Console.
74
76
  #
75
77
  # @param [String, File] file
76
78
  # Path of file to read from
77
79
  # @return [Google::Auth::ClientID]
78
- def self.from_file(file)
79
- fail 'File can not be nil.' if file.nil?
80
- File.open(file.to_s) do |f|
80
+ def self.from_file file
81
+ raise "File can not be nil." if file.nil?
82
+ File.open file.to_s do |f|
81
83
  json = f.read
82
- config = MultiJson.load(json)
83
- from_hash(config)
84
+ config = MultiJson.load json
85
+ from_hash config
84
86
  end
85
87
  end
86
88
 
@@ -91,11 +93,11 @@ module Google
91
93
  # @param [hash] config
92
94
  # Parsed contents of the JSON file
93
95
  # @return [Google::Auth::ClientID]
94
- def self.from_hash(config)
95
- fail 'Hash can not be nil.' if config.nil?
96
+ def self.from_hash config
97
+ raise "Hash can not be nil." if config.nil?
96
98
  raw_detail = config[INSTALLED_APP] || config[WEB_APP]
97
- fail MISSING_TOP_LEVEL_ELEMENT_ERROR if raw_detail.nil?
98
- ClientId.new(raw_detail[CLIENT_ID], raw_detail[CLIENT_SECRET])
99
+ raise MISSING_TOP_LEVEL_ELEMENT_ERROR if raw_detail.nil?
100
+ ClientId.new raw_detail[CLIENT_ID], raw_detail[CLIENT_SECRET]
99
101
  end
100
102
  end
101
103
  end
@@ -27,57 +27,51 @@
27
27
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
- require 'faraday'
31
- require 'googleauth/signet'
32
- require 'memoist'
30
+ require "faraday"
31
+ require "googleauth/signet"
32
+ require "memoist"
33
33
 
34
34
  module Google
35
35
  # Module Auth provides classes that provide Google-specific authorization
36
36
  # used to access Google APIs.
37
37
  module Auth
38
- NO_METADATA_SERVER_ERROR = <<END
39
- Error code 404 trying to get security access token
40
- from Compute Engine metadata for the default service account. This
41
- may be because the virtual machine instance does not have permission
42
- scopes specified.
43
- END
44
- UNEXPECTED_ERROR_SUFFIX = <<END
45
- trying to get security access token from Compute Engine metadata for
46
- the default service account
47
- END
38
+ NO_METADATA_SERVER_ERROR = <<~ERROR.freeze
39
+ Error code 404 trying to get security access token
40
+ from Compute Engine metadata for the default service account. This
41
+ may be because the virtual machine instance does not have permission
42
+ scopes specified.
43
+ ERROR
44
+ UNEXPECTED_ERROR_SUFFIX = <<~ERROR.freeze
45
+ trying to get security access token from Compute Engine metadata for
46
+ the default service account
47
+ ERROR
48
48
 
49
49
  # Extends Signet::OAuth2::Client so that the auth token is obtained from
50
50
  # the GCE metadata server.
51
51
  class GCECredentials < Signet::OAuth2::Client
52
52
  # The IP Address is used in the URIs to speed up failures on non-GCE
53
53
  # systems.
54
- COMPUTE_AUTH_TOKEN_URI = 'http://169.254.169.254/computeMetadata/v1/'\
55
- 'instance/service-accounts/default/token'
56
- COMPUTE_CHECK_URI = 'http://169.254.169.254'
54
+ COMPUTE_AUTH_TOKEN_URI = "http://169.254.169.254/computeMetadata/v1/"\
55
+ "instance/service-accounts/default/token".freeze
56
+ COMPUTE_CHECK_URI = "http://169.254.169.254".freeze
57
57
 
58
58
  class << self
59
59
  extend Memoist
60
60
 
61
61
  # Detect if this appear to be a GCE instance, by checking if metadata
62
- # is available
63
- def on_gce?(options = {})
62
+ # is available.
63
+ def on_gce? options = {}
64
+ # TODO: This should use google-cloud-env instead.
64
65
  c = options[:connection] || Faraday.default_connection
65
- resp = c.get(COMPUTE_CHECK_URI) do |req|
66
- # Comment from: oauth2client/client.py
67
- #
68
- # Note: the explicit `timeout` below is a workaround. The underlying
69
- # issue is that resolving an unknown host on some networks will take
70
- # 20-30 seconds; making this timeout short fixes the issue, but
71
- # could lead to false negatives in the event that we are on GCE, but
72
- # the metadata resolution was particularly slow. The latter case is
73
- # "unlikely".
74
- req.options.timeout = 0.1
66
+ headers = { "Metadata-Flavor" => "Google" }
67
+ resp = c.get COMPUTE_CHECK_URI, nil, headers do |req|
68
+ req.options.timeout = 1.0
69
+ req.options.open_timeout = 0.1
75
70
  end
76
71
  return false unless resp.status == 200
77
- return false unless resp.headers.key?('Metadata-Flavor')
78
- return resp.headers['Metadata-Flavor'] == 'Google'
72
+ resp.headers["Metadata-Flavor"] == "Google"
79
73
  rescue Faraday::TimeoutError, Faraday::ConnectionFailed
80
- return false
74
+ false
81
75
  end
82
76
 
83
77
  memoize :on_gce?
@@ -85,19 +79,22 @@ END
85
79
 
86
80
  # Overrides the super class method to change how access tokens are
87
81
  # fetched.
88
- def fetch_access_token(options = {})
82
+ def fetch_access_token options = {}
89
83
  c = options[:connection] || Faraday.default_connection
90
- c.headers = { 'Metadata-Flavor' => 'Google' }
91
- resp = c.get(COMPUTE_AUTH_TOKEN_URI)
92
- case resp.status
93
- when 200
94
- Signet::OAuth2.parse_credentials(resp.body,
95
- resp.headers['content-type'])
96
- when 404
97
- fail(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR)
98
- else
99
- msg = "Unexpected error code #{resp.status}" + UNEXPECTED_ERROR_SUFFIX
100
- fail(Signet::AuthorizationError, msg)
84
+ retry_with_error do
85
+ headers = { "Metadata-Flavor" => "Google" }
86
+ resp = c.get COMPUTE_AUTH_TOKEN_URI, nil, headers
87
+ case resp.status
88
+ when 200
89
+ Signet::OAuth2.parse_credentials(resp.body,
90
+ resp.headers["content-type"])
91
+ when 404
92
+ raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
93
+ else
94
+ msg = "Unexpected error code #{resp.status}" \
95
+ "#{UNEXPECTED_ERROR_SUFFIX}"
96
+ raise Signet::AuthorizationError, msg
97
+ end
101
98
  end
102
99
  end
103
100
  end