googleauth 0.6.2 → 0.6.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cb647efa48b73b48d9bf0aec7c572f944f31de67
4
- data.tar.gz: 915dd9da0fc858a9f4b9dbdceaa64228218ff87c
2
+ SHA256:
3
+ metadata.gz: 1528ae25e5c678b4b8be00b85095ee5f95ca83fdbcca2c7629cc429d80565e1c
4
+ data.tar.gz: cbc4aef5eea0fab23d0b529c8af5d9a2aa297c107e38e9fa1d220682d0f6fa61
5
5
  SHA512:
6
- metadata.gz: b35a1ef32bc166af59bc0d0f491768957ff8f7d7a2d7cb303b375cd8f0fb90f6fda87d9fec4749850ce589393b94d69d181c8606d32c5b9cee04c8f8cae2744c
7
- data.tar.gz: bc366d1b2a2dc4f49c4eced0ab9c2358070a47c88c3be922e36b68149f69f0b87ab215c8e6fa07c9677b3292664958f131a8efc3d3a36ce0a93c1c9a651bbdd1
6
+ metadata.gz: 13caa772bb5c2ebf1565f18160b59132839d5cd76560764cc235d2390df7b032196c6402fcd075e8356404a69d7970011bfde9904a86c20861a4a5031b221c81
7
+ data.tar.gz: e25c85dd789d8267e6c5aa4e7cd3041b5ce4185b97157cbee0b92e98a5a66c7cbd2dcdae459493d5b5f74d81e415958c764ab0ac4c998281bdc04b103363354a
@@ -13,7 +13,7 @@ Metrics/MethodLength:
13
13
  Max: 20
14
14
  Metrics/ClassLength:
15
15
  Enabled: false
16
- Style/IndentHeredoc:
16
+ Layout/IndentHeredoc:
17
17
  Enabled: false
18
18
  Style/FormatString:
19
19
  Enabled: false
@@ -1,3 +1,11 @@
1
+ ## 0.6.3 (2018/08/02)
2
+
3
+ * Resolve issue where token_store was being written to twice
4
+
5
+ ## 0.6.2 (2018/08/01)
6
+
7
+ * Add warning when using cloud sdk credentials
8
+
1
9
  ## 0.6.1 (2017/10/18)
2
10
 
3
11
  * Fix file permissions
@@ -0,0 +1,43 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project,
4
+ and in the interest of fostering an open and welcoming community,
5
+ we pledge to respect all people who contribute through reporting issues,
6
+ posting feature requests, updating documentation,
7
+ submitting pull requests or patches, and other activities.
8
+
9
+ We are committed to making participation in this project
10
+ a harassment-free experience for everyone,
11
+ regardless of level of experience, gender, gender identity and expression,
12
+ sexual orientation, disability, personal appearance,
13
+ body size, race, ethnicity, age, religion, or nationality.
14
+
15
+ Examples of unacceptable behavior by participants include:
16
+
17
+ * The use of sexualized language or imagery
18
+ * Personal attacks
19
+ * Trolling or insulting/derogatory comments
20
+ * Public or private harassment
21
+ * Publishing other's private information,
22
+ such as physical or electronic
23
+ addresses, without explicit permission
24
+ * Other unethical or unprofessional conduct.
25
+
26
+ Project maintainers have the right and responsibility to remove, edit, or reject
27
+ comments, commits, code, wiki edits, issues, and other contributions
28
+ that are not aligned to this Code of Conduct.
29
+ By adopting this Code of Conduct,
30
+ project maintainers commit themselves to fairly and consistently
31
+ applying these principles to every aspect of managing this project.
32
+ Project maintainers who do not follow or enforce the Code of Conduct
33
+ may be permanently removed from the project team.
34
+
35
+ This code of conduct applies both within project spaces and in public spaces
36
+ when an individual is representing the project or its community.
37
+
38
+ Instances of abusive, harassing, or otherwise unacceptable behavior
39
+ may be reported by opening an issue
40
+ or contacting one or more of the project maintainers.
41
+
42
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
43
+ available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ group :development do
8
8
  gem 'coveralls', '~> 0.7'
9
9
  gem 'fakefs', '~> 0.6'
10
10
  gem 'fakeredis', '~> 0.5'
11
+ gem 'logging', '~> 2.0'
11
12
  gem 'rack-test', '~> 0.6'
12
13
  gem 'rake', '~> 10.0'
13
14
  gem 'redis', '~> 3.2'
data/README.md CHANGED
@@ -143,6 +143,15 @@ authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
143
143
  authorizer.fetch_access_token!
144
144
  ```
145
145
 
146
+ ### Example (Environment Variables)
147
+
148
+ ```bash
149
+ export GOOGLE_ACCOUNT_TYPE=service_account
150
+ export GOOGLE_CLIENT_ID=000000000000000000000
151
+ export GOOGLE_CLIENT_EMAIL=xxxx@xxxx.iam.gserviceaccount.com
152
+ export GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
153
+ ```
154
+
146
155
  ### Storage
147
156
 
148
157
  Authorizers require a storage instance to manage long term persistence of
@@ -27,10 +27,9 @@ Gem::Specification.new do |s|
27
27
  s.platform = Gem::Platform::RUBY
28
28
 
29
29
  s.add_dependency 'faraday', '~> 0.12'
30
- s.add_dependency 'logging', '~> 2.0'
31
30
  s.add_dependency 'jwt', '>= 1.4', '< 3.0'
32
31
  s.add_dependency 'memoist', '~> 0.12'
33
32
  s.add_dependency 'multi_json', '~> 1.11'
34
- s.add_dependency 'os', '~> 0.9'
33
+ s.add_dependency 'os', '>= 0.9', '< 2.0'
35
34
  s.add_dependency 'signet', '~> 0.7'
36
35
  end
@@ -58,7 +58,11 @@ ERROR_MESSAGE
58
58
  DefaultCredentials.from_well_known_path(scope) ||
59
59
  DefaultCredentials.from_system_default_path(scope)
60
60
  return creds unless creds.nil?
61
- raise NOT_FOUND_ERROR unless GCECredentials.on_gce?(options)
61
+ unless GCECredentials.on_gce?(options)
62
+ # Clear cache of the result of GCECredentials.on_gce?
63
+ GCECredentials.unmemoize_all
64
+ raise NOT_FOUND_ERROR
65
+ end
62
66
  GCECredentials.new
63
67
  end
64
68
 
@@ -28,6 +28,7 @@
28
28
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
30
  require 'multi_json'
31
+ require 'googleauth/credentials_loader'
31
32
 
32
33
  module Google
33
34
  module Auth
@@ -63,13 +64,14 @@ module Google
63
64
  # & secrets in source. See {#from_file} to load from
64
65
  # `client_secrets.json` files.
65
66
  def initialize(id, secret)
67
+ CredentialsLoader.warn_if_cloud_sdk_credentials id
66
68
  raise 'Client id can not be nil' if id.nil?
67
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
@@ -79,7 +81,7 @@ module Google
79
81
  raise 'File can not be nil.' if file.nil?
80
82
  File.open(file.to_s) do |f|
81
83
  json = f.read
82
- config = MultiJson.load(json)
84
+ config = MultiJson.load json
83
85
  from_hash(config)
84
86
  end
85
87
  end
@@ -31,15 +31,15 @@ require 'forwardable'
31
31
  require 'json'
32
32
  require 'signet/oauth_2/client'
33
33
 
34
- require 'googleauth/default_credentials'
34
+ require 'googleauth/credentials_loader'
35
35
 
36
36
  module Google
37
37
  module Auth
38
38
  # This class is intended to be inherited by API-specific classes
39
39
  # which overrides the SCOPE constant.
40
40
  class Credentials
41
- TOKEN_CREDENTIAL_URI = 'https://accounts.google.com/o/oauth2/token'.freeze
42
- AUDIENCE = 'https://accounts.google.com/o/oauth2/token'.freeze
41
+ TOKEN_CREDENTIAL_URI = 'https://oauth2.googleapis.com/token'.freeze
42
+ AUDIENCE = 'https://oauth2.googleapis.com/token'.freeze
43
43
  SCOPE = [].freeze
44
44
  PATH_ENV_VARS = [].freeze
45
45
  JSON_ENV_VARS = [].freeze
@@ -68,6 +68,7 @@ module Google
68
68
  json['scope'] ||= scope
69
69
  @client = init_client json
70
70
  end
71
+ CredentialsLoader.warn_if_cloud_sdk_credentials @client.client_id
71
72
  @client.fetch_access_token!
72
73
  end
73
74
 
@@ -78,16 +79,16 @@ module Google
78
79
  def self.default(options = {})
79
80
  scope = options[:scope]
80
81
  # First try to find keyfile file from environment variables.
81
- client = from_path_vars(scope)
82
+ client = from_path_vars scope
82
83
 
83
84
  # Second try to find keyfile json from environment variables.
84
- client ||= from_json_vars(scope)
85
+ client ||= from_json_vars scope
85
86
 
86
87
  # Third try to find keyfile file from known file paths.
87
- client ||= from_default_paths(scope)
88
+ client ||= from_default_paths scope
88
89
 
89
90
  # Finally get instantiated client from Google::Auth
90
- client ||= from_application_default(scope)
91
+ client ||= from_application_default scope
91
92
  client
92
93
  end
93
94
 
@@ -57,6 +57,17 @@ module Google
57
57
  SYSTEM_DEFAULT_ERROR =
58
58
  'Unable to read the system default credential file'.freeze
59
59
 
60
+ CLOUD_SDK_CLIENT_ID = '764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.app'\
61
+ 's.googleusercontent.com'.freeze
62
+
63
+ CLOUD_SDK_CREDENTIALS_WARNING = 'Your application has authenticated '\
64
+ 'using end user credentials from Google Cloud SDK. We recommend that '\
65
+ 'most server applications use service accounts instead. If your '\
66
+ 'application continues to use end user credentials from Cloud SDK, '\
67
+ 'you might receive a "quota exceeded" or "API not enabled" error. For'\
68
+ ' more information about service accounts, see '\
69
+ 'https://cloud.google.com/docs/authentication/.'.freeze
70
+
60
71
  # make_creds proxies the construction of a credentials instance
61
72
  #
62
73
  # By default, it calls #new on the current class, but this behaviour can
@@ -119,6 +130,12 @@ module Google
119
130
  raise "#{SYSTEM_DEFAULT_ERROR}: #{e}"
120
131
  end
121
132
 
133
+ # Issues warning if cloud sdk client id is used
134
+ def warn_if_cloud_sdk_credentials(client_id)
135
+ warn CLOUD_SDK_CREDENTIALS_WARNING if client_id == CLOUD_SDK_CLIENT_ID
136
+ end
137
+ module_function :warn_if_cloud_sdk_credentials
138
+
122
139
  private
123
140
 
124
141
  def service_account_env_vars?
@@ -49,9 +49,11 @@ module Google
49
49
  json_key_io, scope = options.values_at(:json_key_io, :scope)
50
50
  if json_key_io
51
51
  json_key, clz = determine_creds_class(json_key_io)
52
+ warn_if_cloud_sdk_credentials json_key['client_id']
52
53
  clz.make_creds(json_key_io: StringIO.new(MultiJson.dump(json_key)),
53
54
  scope: scope)
54
55
  else
56
+ warn_if_cloud_sdk_credentials ENV[CLIENT_ID_VAR]
55
57
  clz = read_creds
56
58
  clz.make_creds(scope: scope)
57
59
  end
@@ -73,7 +75,7 @@ module Google
73
75
 
74
76
  # Reads the input json and determines which creds class to use.
75
77
  def self.determine_creds_class(json_key_io)
76
- json_key = MultiJson.load(json_key_io.read)
78
+ json_key = MultiJson.load json_key_io.read
77
79
  key = 'type'
78
80
  raise "the json is missing the '#{key}' field" unless json_key.key?(key)
79
81
  type = json_key[key]
@@ -0,0 +1,45 @@
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
+ module Google
31
+ # Module Auth provides classes that provide Google-specific authorization
32
+ # used to access Google APIs.
33
+ module Auth
34
+ # JsonKeyReader contains the behaviour used to read private key and
35
+ # client email fields from the service account
36
+ module JsonKeyReader
37
+ def read_json_key(json_key_io)
38
+ json_key = MultiJson.load(json_key_io.read)
39
+ raise 'missing client_email' unless json_key.key?('client_email')
40
+ raise 'missing private_key' unless json_key.key?('private_key')
41
+ [json_key['private_key'], json_key['client_email']]
42
+ end
43
+ end
44
+ end
45
+ end
@@ -29,6 +29,7 @@
29
29
 
30
30
  require 'googleauth/signet'
31
31
  require 'googleauth/credentials_loader'
32
+ require 'googleauth/json_key_reader'
32
33
  require 'jwt'
33
34
  require 'multi_json'
34
35
  require 'stringio'
@@ -48,6 +49,7 @@ module Google
48
49
  class ServiceAccountCredentials < Signet::OAuth2::Client
49
50
  TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v4/token'.freeze
50
51
  extend CredentialsLoader
52
+ extend JsonKeyReader
51
53
 
52
54
  # Creates a ServiceAccountCredentials.
53
55
  #
@@ -58,7 +60,7 @@ module Google
58
60
  if json_key_io
59
61
  private_key, client_email = read_json_key(json_key_io)
60
62
  else
61
- private_key = ENV[CredentialsLoader::PRIVATE_KEY_VAR]
63
+ private_key = unescape ENV[CredentialsLoader::PRIVATE_KEY_VAR]
62
64
  client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
63
65
  end
64
66
 
@@ -69,13 +71,13 @@ module Google
69
71
  signing_key: OpenSSL::PKey::RSA.new(private_key))
70
72
  end
71
73
 
72
- # Reads the private key and client email fields from the service account
73
- # JSON key.
74
- def self.read_json_key(json_key_io)
75
- json_key = MultiJson.load(json_key_io.read)
76
- raise 'missing client_email' unless json_key.key?('client_email')
77
- raise 'missing private_key' unless json_key.key?('private_key')
78
- [json_key['private_key'], json_key['client_email']]
74
+ # Handles certain escape sequences that sometimes appear in input.
75
+ # Specifically, interprets the "\n" sequence for newline, and removes
76
+ # enclosing quotes.
77
+ def self.unescape(str)
78
+ str = str.gsub '\n', "\n"
79
+ str = str[1..-2] if str.start_with?('"') && str.end_with?('"')
80
+ str
79
81
  end
80
82
 
81
83
  def initialize(options = {})
@@ -123,6 +125,7 @@ module Google
123
125
  SIGNING_ALGORITHM = 'RS256'.freeze
124
126
  EXPIRY = 60
125
127
  extend CredentialsLoader
128
+ extend JsonKeyReader
126
129
 
127
130
  # make_creds proxies the construction of a credentials instance
128
131
  #
@@ -135,15 +138,6 @@ module Google
135
138
  new(json_key_io: args[0][:json_key_io])
136
139
  end
137
140
 
138
- # Reads the private key and client email fields from the service account
139
- # JSON key.
140
- def self.read_json_key(json_key_io)
141
- json_key = MultiJson.load(json_key_io.read)
142
- raise 'missing client_email' unless json_key.key?('client_email')
143
- raise 'missing private_key' unless json_key.key?('private_key')
144
- [json_key['private_key'], json_key['client_email']]
145
- end
146
-
147
141
  # Initializes a ServiceAccountJwtHeaderCredentials.
148
142
  #
149
143
  # @param json_key_io [IO] an IO from which the JSON key can be read
@@ -198,7 +198,6 @@ module Google
198
198
  # Credentials if exchange is successful
199
199
  def get_and_store_credentials_from_code(options = {})
200
200
  credentials = get_credentials_from_code(options)
201
- monitor_credentials(options[:user_id], credentials)
202
201
  store_credentials(options[:user_id], credentials)
203
202
  end
204
203
 
@@ -46,9 +46,9 @@ module Google
46
46
  #
47
47
  # cf [Application Default Credentials](http://goo.gl/mkAHpZ)
48
48
  class UserRefreshCredentials < Signet::OAuth2::Client
49
- TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v4/token'.freeze
49
+ TOKEN_CRED_URI = 'https://oauth2.googleapis.com/token'.freeze
50
50
  AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'.freeze
51
- REVOKE_TOKEN_URI = 'https://accounts.google.com/o/oauth2/revoke'.freeze
51
+ REVOKE_TOKEN_URI = 'https://oauth2.googleapis.com/revoke'.freeze
52
52
  extend CredentialsLoader
53
53
 
54
54
  # Create a UserRefreshCredentials.
@@ -31,6 +31,6 @@ module Google
31
31
  # Module Auth provides classes that provide Google-specific authorization
32
32
  # used to access Google APIs.
33
33
  module Auth
34
- VERSION = '0.6.2'.freeze
34
+ VERSION = '0.6.3'.freeze
35
35
  end
36
36
  end
@@ -48,7 +48,7 @@ describe Google::Auth::ClientId do
48
48
 
49
49
  shared_examples 'it can successfully load client_id' do
50
50
  context 'loaded from hash' do
51
- let(:client_id) { Google::Auth::ClientId.from_hash(config) }
51
+ let(:client_id) { Google::Auth::ClientId.from_hash config }
52
52
 
53
53
  it_behaves_like 'it has a valid config'
54
54
  end
@@ -103,7 +103,7 @@ describe Google::Auth::ClientId do
103
103
  end
104
104
 
105
105
  it 'should raise error' do
106
- expect { Google::Auth::ClientId.from_hash(config) }.to raise_error(
106
+ expect { Google::Auth::ClientId.from_hash config }.to raise_error(
107
107
  /Expected top level property/
108
108
  )
109
109
  end
@@ -119,7 +119,7 @@ describe Google::Auth::ClientId do
119
119
  end
120
120
 
121
121
  it 'should raise error' do
122
- expect { Google::Auth::ClientId.from_hash(config) }.to raise_error(
122
+ expect { Google::Auth::ClientId.from_hash config }.to raise_error(
123
123
  /Client id can not be nil/
124
124
  )
125
125
  end
@@ -135,9 +135,26 @@ describe Google::Auth::ClientId do
135
135
  end
136
136
 
137
137
  it 'should raise error' do
138
- expect { Google::Auth::ClientId.from_hash(config) }.to raise_error(
138
+ expect { Google::Auth::ClientId.from_hash config }.to raise_error(
139
139
  /Client secret can not be nil/
140
140
  )
141
141
  end
142
142
  end
143
+
144
+ context 'with cloud sdk credentials' do
145
+ let(:config) do
146
+ {
147
+ 'web' => {
148
+ 'client_id' => Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID,
149
+ 'client_secret' => 'notasecret'
150
+ }
151
+ }
152
+ end
153
+
154
+ it 'should raise warning' do
155
+ expect { Google::Auth::ClientId.from_hash config }.to output(
156
+ Google::Auth::CredentialsLoader::CLOUD_SDK_CREDENTIALS_WARNING + "\n"
157
+ ).to_stderr
158
+ end
159
+ end
143
160
  end
@@ -29,6 +29,7 @@
29
29
 
30
30
  require 'googleauth'
31
31
 
32
+
32
33
  # This test is testing the private class Google::Auth::Credentials. We want to
33
34
  # make sure that the passed in scope propogates to the Signet object. This means
34
35
  # testing the private API, which is generally frowned on.
@@ -46,9 +47,10 @@ describe Google::Auth::Credentials, :private do
46
47
  it 'uses a default scope' do
47
48
  mocked_signet = double('Signet::OAuth2::Client')
48
49
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
50
+ allow(mocked_signet).to receive(:client_id)
49
51
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
50
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
51
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
52
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
53
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
52
54
  expect(options[:scope]).to eq([])
53
55
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
54
56
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -62,9 +64,10 @@ describe Google::Auth::Credentials, :private do
62
64
  it 'uses a custom scope' do
63
65
  mocked_signet = double('Signet::OAuth2::Client')
64
66
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
67
+ allow(mocked_signet).to receive(:client_id)
65
68
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
66
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
67
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
69
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
70
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
68
71
  expect(options[:scope]).to eq(['http://example.com/scope'])
69
72
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
70
73
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -93,9 +96,10 @@ describe Google::Auth::Credentials, :private do
93
96
 
94
97
  mocked_signet = double('Signet::OAuth2::Client')
95
98
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
99
+ allow(mocked_signet).to receive(:client_id)
96
100
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
97
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
98
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
101
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
102
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
99
103
  expect(options[:scope]).to eq(['http://example.com/scope'])
100
104
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
101
105
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -124,9 +128,10 @@ describe Google::Auth::Credentials, :private do
124
128
 
125
129
  mocked_signet = double('Signet::OAuth2::Client')
126
130
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
131
+ allow(mocked_signet).to receive(:client_id)
127
132
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
128
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
129
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
133
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
134
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
130
135
  expect(options[:scope]).to eq(['http://example.com/scope'])
131
136
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
132
137
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -154,9 +159,10 @@ describe Google::Auth::Credentials, :private do
154
159
 
155
160
  mocked_signet = double('Signet::OAuth2::Client')
156
161
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
162
+ allow(mocked_signet).to receive(:client_id)
157
163
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
158
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
159
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
164
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
165
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
160
166
  expect(options[:scope]).to eq(['http://example.com/scope'])
161
167
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
162
168
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -185,9 +191,10 @@ describe Google::Auth::Credentials, :private do
185
191
 
186
192
  mocked_signet = double('Signet::OAuth2::Client')
187
193
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
194
+ allow(mocked_signet).to receive(:client_id)
188
195
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
189
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
190
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
196
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
197
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
191
198
  expect(options[:scope]).to eq(['http://example.com/scope'])
192
199
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
193
200
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -215,6 +222,7 @@ describe Google::Auth::Credentials, :private do
215
222
 
216
223
  mocked_signet = double('Signet::OAuth2::Client')
217
224
  allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
225
+ allow(mocked_signet).to receive(:client_id)
218
226
  allow(Google::Auth).to receive(:get_application_default) do |scope|
219
227
  expect(scope).to eq(TestCredentials::SCOPE)
220
228
 
@@ -223,8 +231,8 @@ describe Google::Auth::Credentials, :private do
223
231
  default_keyfile_hash
224
232
  end
225
233
  allow(Signet::OAuth2::Client).to receive(:new) do |options|
226
- expect(options[:token_credential_uri]).to eq('https://accounts.google.com/o/oauth2/token')
227
- expect(options[:audience]).to eq('https://accounts.google.com/o/oauth2/token')
234
+ expect(options[:token_credential_uri]).to eq('https://oauth2.googleapis.com/token')
235
+ expect(options[:audience]).to eq('https://oauth2.googleapis.com/token')
228
236
  expect(options[:scope]).to eq(['http://example.com/scope'])
229
237
  expect(options[:issuer]).to eq(default_keyfile_hash['client_email'])
230
238
  expect(options[:signing_key]).to be_a_kind_of(OpenSSL::PKey::RSA)
@@ -236,4 +244,16 @@ describe Google::Auth::Credentials, :private do
236
244
  expect(creds).to be_a_kind_of(TestCredentials)
237
245
  expect(creds.client).to eq(mocked_signet)
238
246
  end
247
+
248
+ it 'warns when cloud sdk credentials are used' do
249
+ mocked_signet = double('Signet::OAuth2::Client')
250
+ allow(mocked_signet).to receive(:fetch_access_token!).and_return(true)
251
+ allow(Signet::OAuth2::Client).to receive(:new) do |options|
252
+ mocked_signet
253
+ end
254
+ allow(mocked_signet).to receive(:client_id).and_return(Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID)
255
+ expect { Google::Auth::Credentials.new default_keyfile_hash }.to output(
256
+ Google::Auth::CredentialsLoader::CLOUD_SDK_CREDENTIALS_WARNING + "\n"
257
+ ).to_stderr
258
+ end
239
259
  end
@@ -63,7 +63,7 @@ describe '#get_application_default' do
63
63
  Dir.mktmpdir do |dir|
64
64
  key_path = File.join(dir, 'does-not-exist')
65
65
  ENV[@var_name] = key_path
66
- expect { Google::Auth.get_application_default(@scope, options) }
66
+ expect { Google::Auth.get_application_default @scope, options }
67
67
  .to raise_error RuntimeError
68
68
  end
69
69
  end
@@ -76,7 +76,7 @@ describe '#get_application_default' do
76
76
  ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
77
77
  ENV['HOME'] = dir # no config present in this tmp dir
78
78
  expect do
79
- Google::Auth.get_application_default(@scope, options)
79
+ Google::Auth.get_application_default @scope, options
80
80
  end.to raise_error RuntimeError
81
81
  end
82
82
  expect(stub).to have_been_requested
@@ -90,7 +90,7 @@ describe '#get_application_default' do
90
90
  FileUtils.mkdir_p(File.dirname(key_path))
91
91
  File.write(key_path, cred_json_text)
92
92
  ENV[@var_name] = key_path
93
- expect(Google::Auth.get_application_default(@scope, options))
93
+ expect(Google::Auth.get_application_default @scope, options)
94
94
  .to_not be_nil
95
95
  end
96
96
  end
@@ -102,7 +102,7 @@ describe '#get_application_default' do
102
102
  FileUtils.mkdir_p(File.dirname(key_path))
103
103
  File.write(key_path, cred_json_text)
104
104
  ENV['HOME'] = dir
105
- expect(Google::Auth.get_application_default(@scope, options))
105
+ expect(Google::Auth.get_application_default @scope, options)
106
106
  .to_not be_nil
107
107
  end
108
108
  end
@@ -114,7 +114,7 @@ describe '#get_application_default' do
114
114
  FileUtils.mkdir_p(File.dirname(key_path))
115
115
  File.write(key_path, cred_json_text)
116
116
  ENV['HOME'] = dir
117
- expect(Google::Auth.get_application_default(nil, options)).to_not be_nil
117
+ expect(Google::Auth.get_application_default nil, options).to_not be_nil
118
118
  end
119
119
  end
120
120
 
@@ -125,7 +125,7 @@ describe '#get_application_default' do
125
125
  Dir.mktmpdir do |dir|
126
126
  ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
127
127
  ENV['HOME'] = dir # no config present in this tmp dir
128
- creds = Google::Auth.get_application_default(@scope, options)
128
+ creds = Google::Auth.get_application_default @scope, options
129
129
  expect(creds).to_not be_nil
130
130
  end
131
131
  expect(stub).to have_been_requested
@@ -137,7 +137,7 @@ describe '#get_application_default' do
137
137
  key_path = File.join('/etc/google/auth/', CREDENTIALS_FILE_NAME)
138
138
  FileUtils.mkdir_p(File.dirname(key_path))
139
139
  File.write(key_path, cred_json_text)
140
- expect(Google::Auth.get_application_default(@scope, options))
140
+ expect(Google::Auth.get_application_default @scope, options)
141
141
  .to_not be_nil
142
142
  File.delete(key_path)
143
143
  end
@@ -151,9 +151,22 @@ describe '#get_application_default' do
151
151
  ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret]
152
152
  ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token]
153
153
  ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
154
- expect(Google::Auth.get_application_default(@scope, options))
154
+ expect(Google::Auth.get_application_default @scope, options)
155
155
  .to_not be_nil
156
156
  end
157
+
158
+ it 'warns when using cloud sdk credentials' do
159
+ ENV.delete(@var_name) unless ENV[@var_name].nil? # no env var
160
+ ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
161
+ ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
162
+ ENV[CLIENT_ID_VAR] = Google::Auth::CredentialsLoader::CLOUD_SDK_CLIENT_ID
163
+ ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret]
164
+ ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token]
165
+ ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
166
+ expect { Google::Auth.get_application_default @scope, options }.to output(
167
+ Google::Auth::CredentialsLoader::CLOUD_SDK_CREDENTIALS_WARNING + "\n"
168
+ ).to_stderr
169
+ end
157
170
  end
158
171
 
159
172
  describe 'when credential type is service account' do
@@ -216,7 +229,7 @@ describe '#get_application_default' do
216
229
  File.write(key_path, cred_json_text)
217
230
  ENV[@var_name] = key_path
218
231
  expect do
219
- Google::Auth.get_application_default(@scope, options)
232
+ Google::Auth.get_application_default @scope, options
220
233
  end.to raise_error RuntimeError
221
234
  end
222
235
  end
@@ -229,7 +242,7 @@ describe '#get_application_default' do
229
242
  File.write(key_path, cred_json_text)
230
243
  ENV['HOME'] = dir
231
244
  expect do
232
- Google::Auth.get_application_default(@scope, options)
245
+ Google::Auth.get_application_default @scope, options
233
246
  end.to raise_error RuntimeError
234
247
  end
235
248
  end
@@ -238,7 +251,7 @@ describe '#get_application_default' do
238
251
  ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
239
252
  ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
240
253
  expect do
241
- Google::Auth.get_application_default(@scope, options)
254
+ Google::Auth.get_application_default @scope, options
242
255
  end.to raise_error RuntimeError
243
256
  end
244
257
  end
@@ -211,6 +211,13 @@ describe Google::Auth::ServiceAccountCredentials do
211
211
  ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
212
212
  expect(@clz.from_env(@scope)).to_not be_nil
213
213
  end
214
+
215
+ it 'succeeds when GOOGLE_PRIVATE_KEY is escaped' do
216
+ escaped_key = cred_json[:private_key].gsub "\n", '\n'
217
+ ENV[PRIVATE_KEY_VAR] = "\"#{escaped_key}\""
218
+ ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
219
+ expect(@clz.from_env(@scope)).to_not be_nil
220
+ end
214
221
  end
215
222
 
216
223
  describe '#from_well_known_path' do
@@ -41,10 +41,10 @@ describe Signet::OAuth2::Client do
41
41
  before(:example) do
42
42
  @key = OpenSSL::PKey::RSA.new(2048)
43
43
  @client = Signet::OAuth2::Client.new(
44
- token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
44
+ token_credential_uri: 'https://oauth2.googleapis.com/token',
45
45
  scope: 'https://www.googleapis.com/auth/userinfo.profile',
46
46
  issuer: 'app@example.com',
47
- audience: 'https://accounts.google.com/o/oauth2/token',
47
+ audience: 'https://oauth2.googleapis.com/token',
48
48
  signing_key: @key
49
49
  )
50
50
  end
@@ -60,7 +60,7 @@ describe Signet::OAuth2::Client do
60
60
  @key.public_key, true,
61
61
  algorithm: 'RS256')
62
62
  end
63
- stub_request(:post, 'https://accounts.google.com/o/oauth2/token')
63
+ stub_request(:post, 'https://oauth2.googleapis.com/token')
64
64
  .with(body: hash_including(
65
65
  'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer'
66
66
  ), &blk)
@@ -242,7 +242,7 @@ describe Google::Auth::UserAuthorizer do
242
242
  end
243
243
 
244
244
  before(:example) do
245
- stub_request(:post, 'https://www.googleapis.com/oauth2/v4/token')
245
+ stub_request(:post, 'https://oauth2.googleapis.com/token')
246
246
  .to_return(body: token_json, status: 200, headers: {
247
247
  'Content-Type' => 'application/json'
248
248
  })
@@ -270,7 +270,7 @@ describe Google::Auth::UserAuthorizer do
270
270
 
271
271
  context 'with invalid authorization code' do
272
272
  before(:example) do
273
- stub_request(:post, 'https://www.googleapis.com/oauth2/v4/token')
273
+ stub_request(:post, 'https://oauth2.googleapis.com/token')
274
274
  .to_return(status: 400)
275
275
  end
276
276
 
@@ -300,7 +300,7 @@ describe Google::Auth::UserAuthorizer do
300
300
  before(:example) do
301
301
  token_store.store('user1', token_json)
302
302
  stub_request(
303
- :get, 'https://accounts.google.com/o/oauth2/revoke?token=refreshtoken'
303
+ :get, 'https://oauth2.googleapis.com/revoke?token=refreshtoken'
304
304
  )
305
305
  .to_return(status: 200)
306
306
  end
@@ -308,7 +308,7 @@ describe Google::Auth::UserAuthorizer do
308
308
  it 'should revoke the grant' do
309
309
  authorizer.revoke_authorization('user1')
310
310
  expect(a_request(
311
- :get, 'https://accounts.google.com/o/oauth2/revoke?token=refreshtoken'
311
+ :get, 'https://oauth2.googleapis.com/revoke?token=refreshtoken'
312
312
  ))
313
313
  .to have_been_made
314
314
  end
@@ -68,7 +68,7 @@ describe Google::Auth::UserRefreshCredentials do
68
68
  body = MultiJson.dump('access_token' => access_token,
69
69
  'token_type' => 'Bearer',
70
70
  'expires_in' => 3600)
71
- stub_request(:post, 'https://www.googleapis.com/oauth2/v4/token')
71
+ stub_request(:post, 'https://oauth2.googleapis.com/token')
72
72
  .with(body: hash_including('grant_type' => 'refresh_token'))
73
73
  .to_return(body: body,
74
74
  status: 200,
@@ -246,7 +246,7 @@ describe Google::Auth::UserRefreshCredentials do
246
246
 
247
247
  describe 'when revoking a refresh token' do
248
248
  let(:stub) do
249
- stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
249
+ stub_request(:get, 'https://oauth2.googleapis.com/revoke' \
250
250
  '?token=refreshtoken')
251
251
  .to_return(status: 200,
252
252
  headers: { 'Content-Type' => 'application/json' })
@@ -262,7 +262,7 @@ describe Google::Auth::UserRefreshCredentials do
262
262
 
263
263
  describe 'when revoking an access token' do
264
264
  let(:stub) do
265
- stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
265
+ stub_request(:get, 'https://oauth2.googleapis.com/revoke' \
266
266
  '?token=accesstoken')
267
267
  .to_return(status: 200,
268
268
  headers: { 'Content-Type' => 'application/json' })
@@ -280,7 +280,7 @@ describe Google::Auth::UserRefreshCredentials do
280
280
 
281
281
  describe 'when revoking an invalid token' do
282
282
  let(:stub) do
283
- stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
283
+ stub_request(:get, 'https://oauth2.googleapis.com/revoke' \
284
284
  '?token=refreshtoken')
285
285
  .to_return(status: 400,
286
286
  headers: { 'Content-Type' => 'application/json' })
@@ -294,7 +294,7 @@ describe Google::Auth::UserRefreshCredentials do
294
294
  end
295
295
  end
296
296
 
297
- describe 'when erros occurred with request' do
297
+ describe 'when errors occurred with request' do
298
298
  it 'should fail with Signet::AuthorizationError if request times out' do
299
299
  allow_any_instance_of(Faraday::Connection).to receive(:get)
300
300
  .and_raise(Faraday::TimeoutError)
@@ -107,7 +107,7 @@ describe Google::Auth::WebUserAuthorizer do
107
107
  end
108
108
 
109
109
  before(:example) do
110
- stub_request(:post, 'https://www.googleapis.com/oauth2/v4/token')
110
+ stub_request(:post, 'https://oauth2.googleapis.com/token')
111
111
  .to_return(body: token_json,
112
112
  status: 200,
113
113
  headers: { 'Content-Type' => 'application/json' })
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: googleauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Emiola
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-10 00:00:00.000000000 Z
11
+ date: 2018-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.12'
27
- - !ruby/object:Gem::Dependency
28
- name: logging
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2.0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2.0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: jwt
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -90,16 +76,22 @@ dependencies:
90
76
  name: os
91
77
  requirement: !ruby/object:Gem::Requirement
92
78
  requirements:
93
- - - "~>"
79
+ - - ">="
94
80
  - !ruby/object:Gem::Version
95
81
  version: '0.9'
82
+ - - "<"
83
+ - !ruby/object:Gem::Version
84
+ version: '2.0'
96
85
  type: :runtime
97
86
  prerelease: false
98
87
  version_requirements: !ruby/object:Gem::Requirement
99
88
  requirements:
100
- - - "~>"
89
+ - - ">="
101
90
  - !ruby/object:Gem::Version
102
91
  version: '0.9'
92
+ - - "<"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.0'
103
95
  - !ruby/object:Gem::Dependency
104
96
  name: signet
105
97
  requirement: !ruby/object:Gem::Requirement
@@ -128,6 +120,7 @@ files:
128
120
  - ".rubocop.yml"
129
121
  - ".travis.yml"
130
122
  - CHANGELOG.md
123
+ - CODE_OF_CONDUCT.md
131
124
  - CONTRIBUTING.md
132
125
  - COPYING
133
126
  - Gemfile
@@ -142,6 +135,7 @@ files:
142
135
  - lib/googleauth/credentials_loader.rb
143
136
  - lib/googleauth/default_credentials.rb
144
137
  - lib/googleauth/iam.rb
138
+ - lib/googleauth/json_key_reader.rb
145
139
  - lib/googleauth/scope_util.rb
146
140
  - lib/googleauth/service_account.rb
147
141
  - lib/googleauth/signet.rb
@@ -188,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
182
  version: '0'
189
183
  requirements: []
190
184
  rubyforge_project:
191
- rubygems_version: 2.4.8
185
+ rubygems_version: 2.7.6
192
186
  signing_key:
193
187
  specification_version: 4
194
188
  summary: Google Auth Library for Ruby