googleauth 0.14.0 → 1.3.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/CHANGELOG.md +72 -10
  4. data/README.md +48 -13
  5. data/SECURITY.md +7 -0
  6. data/lib/googleauth/application_default.rb +10 -25
  7. data/lib/googleauth/client_id.rb +10 -25
  8. data/lib/googleauth/compute_engine.rb +16 -30
  9. data/lib/googleauth/credentials.rb +178 -74
  10. data/lib/googleauth/credentials_loader.rb +23 -44
  11. data/lib/googleauth/default_credentials.rb +10 -25
  12. data/lib/googleauth/iam.rb +11 -26
  13. data/lib/googleauth/id_tokens/errors.rb +9 -23
  14. data/lib/googleauth/id_tokens/key_sources.rb +26 -38
  15. data/lib/googleauth/id_tokens/verifier.rb +16 -32
  16. data/lib/googleauth/id_tokens.rb +9 -23
  17. data/lib/googleauth/json_key_reader.rb +10 -25
  18. data/lib/googleauth/scope_util.rb +11 -26
  19. data/lib/googleauth/service_account.rb +60 -59
  20. data/lib/googleauth/signet.rb +22 -28
  21. data/lib/googleauth/stores/file_token_store.rb +11 -25
  22. data/lib/googleauth/stores/redis_token_store.rb +11 -25
  23. data/lib/googleauth/token_store.rb +10 -25
  24. data/lib/googleauth/user_authorizer.rb +10 -25
  25. data/lib/googleauth/user_refresh.rb +15 -27
  26. data/lib/googleauth/version.rb +11 -26
  27. data/lib/googleauth/web_user_authorizer.rb +14 -32
  28. data/lib/googleauth.rb +10 -25
  29. metadata +26 -97
  30. data/.github/CODEOWNERS +0 -7
  31. data/.github/CONTRIBUTING.md +0 -74
  32. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -36
  33. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -21
  34. data/.github/ISSUE_TEMPLATE/support_request.md +0 -7
  35. data/.gitignore +0 -36
  36. data/.kokoro/build.bat +0 -16
  37. data/.kokoro/build.sh +0 -4
  38. data/.kokoro/continuous/common.cfg +0 -24
  39. data/.kokoro/continuous/linux.cfg +0 -25
  40. data/.kokoro/continuous/osx.cfg +0 -8
  41. data/.kokoro/continuous/post.cfg +0 -30
  42. data/.kokoro/continuous/windows.cfg +0 -29
  43. data/.kokoro/osx.sh +0 -4
  44. data/.kokoro/presubmit/common.cfg +0 -24
  45. data/.kokoro/presubmit/linux.cfg +0 -24
  46. data/.kokoro/presubmit/osx.cfg +0 -8
  47. data/.kokoro/presubmit/windows.cfg +0 -29
  48. data/.kokoro/release.cfg +0 -94
  49. data/.kokoro/trampoline.bat +0 -10
  50. data/.kokoro/trampoline.sh +0 -4
  51. data/.repo-metadata.json +0 -5
  52. data/.rspec +0 -2
  53. data/.rubocop.yml +0 -19
  54. data/Gemfile +0 -30
  55. data/Rakefile +0 -132
  56. data/googleauth.gemspec +0 -38
  57. data/integration/helper.rb +0 -31
  58. data/integration/id_tokens/key_source_test.rb +0 -74
  59. data/rakelib/devsite_builder.rb +0 -45
  60. data/rakelib/link_checker.rb +0 -64
  61. data/rakelib/repo_metadata.rb +0 -59
  62. data/spec/googleauth/apply_auth_examples.rb +0 -171
  63. data/spec/googleauth/client_id_spec.rb +0 -160
  64. data/spec/googleauth/compute_engine_spec.rb +0 -160
  65. data/spec/googleauth/credentials_spec.rb +0 -478
  66. data/spec/googleauth/get_application_default_spec.rb +0 -286
  67. data/spec/googleauth/iam_spec.rb +0 -80
  68. data/spec/googleauth/scope_util_spec.rb +0 -77
  69. data/spec/googleauth/service_account_spec.rb +0 -489
  70. data/spec/googleauth/signet_spec.rb +0 -142
  71. data/spec/googleauth/stores/file_token_store_spec.rb +0 -57
  72. data/spec/googleauth/stores/redis_token_store_spec.rb +0 -50
  73. data/spec/googleauth/stores/store_examples.rb +0 -58
  74. data/spec/googleauth/user_authorizer_spec.rb +0 -343
  75. data/spec/googleauth/user_refresh_spec.rb +0 -359
  76. data/spec/googleauth/web_user_authorizer_spec.rb +0 -172
  77. data/spec/spec_helper.rb +0 -92
  78. data/test/helper.rb +0 -33
  79. data/test/id_tokens/key_sources_test.rb +0 -240
  80. data/test/id_tokens/verifier_test.rb +0 -269
@@ -1,489 +0,0 @@
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
- spec_dir = File.expand_path File.join(File.dirname(__FILE__))
31
- $LOAD_PATH.unshift spec_dir
32
- $LOAD_PATH.uniq!
33
-
34
- require "apply_auth_examples"
35
- require "fakefs/safe"
36
- require "fileutils"
37
- require "googleauth/service_account"
38
- require "jwt"
39
- require "multi_json"
40
- require "openssl"
41
- require "spec_helper"
42
- require "tmpdir"
43
- require "os"
44
-
45
- include Google::Auth::CredentialsLoader
46
-
47
- shared_examples "jwt header auth" do
48
- context "when jwt_aud_uri is present" do
49
- let(:test_uri) { "https://www.googleapis.com/myservice" }
50
- let(:auth_prefix) { "Bearer " }
51
- let(:auth_key) { ServiceAccountJwtHeaderCredentials::AUTH_METADATA_KEY }
52
- let(:jwt_uri_key) { ServiceAccountJwtHeaderCredentials::JWT_AUD_URI_KEY }
53
-
54
- def expect_is_encoded_jwt hdr
55
- expect(hdr).to_not be_nil
56
- expect(hdr.start_with?(auth_prefix)).to be true
57
- authorization = hdr[auth_prefix.length..-1]
58
- payload, = JWT.decode authorization, @key.public_key, true, algorithm: "RS256"
59
- expect(payload["aud"]).to eq(test_uri)
60
- expect(payload["iss"]).to eq(client_email)
61
- end
62
-
63
- describe "#apply!" do
64
- it "should update the target hash with a jwt token" do
65
- md = { foo: "bar" }
66
- md[jwt_uri_key] = test_uri
67
- @client.apply! md
68
- auth_header = md[auth_key]
69
- expect_is_encoded_jwt auth_header
70
- expect(md[jwt_uri_key]).to be_nil
71
- end
72
- end
73
-
74
- describe "updater_proc" do
75
- it "should provide a proc that updates a hash with a jwt token" do
76
- md = { foo: "bar" }
77
- md[jwt_uri_key] = test_uri
78
- the_proc = @client.updater_proc
79
- got = the_proc.call md
80
- auth_header = got[auth_key]
81
- expect_is_encoded_jwt auth_header
82
- expect(got[jwt_uri_key]).to be_nil
83
- expect(md[jwt_uri_key]).to_not be_nil
84
- end
85
- end
86
-
87
- describe "#apply" do
88
- it "should not update the original hash with a jwt token" do
89
- md = { foo: "bar" }
90
- md[jwt_uri_key] = test_uri
91
- the_proc = @client.updater_proc
92
- got = the_proc.call md
93
- auth_header = md[auth_key]
94
- expect(auth_header).to be_nil
95
- expect(got[jwt_uri_key]).to be_nil
96
- expect(md[jwt_uri_key]).to_not be_nil
97
- end
98
-
99
- it "should add a jwt token to the returned hash" do
100
- md = { foo: "bar" }
101
- md[jwt_uri_key] = test_uri
102
- got = @client.apply md
103
- auth_header = got[auth_key]
104
- expect_is_encoded_jwt auth_header
105
- end
106
- end
107
- end
108
- end
109
-
110
- describe Google::Auth::ServiceAccountCredentials do
111
- ServiceAccountCredentials = Google::Auth::ServiceAccountCredentials
112
- let(:client_email) { "app@developer.gserviceaccount.com" }
113
- let :cred_json do
114
- {
115
- private_key_id: "a_private_key_id",
116
- private_key: @key.to_pem,
117
- client_email: client_email,
118
- client_id: "app.apps.googleusercontent.com",
119
- type: "service_account",
120
- project_id: "a_project_id",
121
- quota_project_id: "b_project_id"
122
- }
123
- end
124
-
125
- before :example do
126
- @key = OpenSSL::PKey::RSA.new 2048
127
- @client = ServiceAccountCredentials.make_creds(
128
- json_key_io: StringIO.new(cred_json_text),
129
- scope: "https://www.googleapis.com/auth/userinfo.profile"
130
- )
131
- @id_client = ServiceAccountCredentials.make_creds(
132
- json_key_io: StringIO.new(cred_json_text),
133
- target_audience: "https://pubsub.googleapis.com/"
134
- )
135
- end
136
-
137
- def make_auth_stubs opts
138
- body_fields = { "token_type" => "Bearer", "expires_in" => 3600 }
139
- body_fields["access_token"] = opts[:access_token] if opts[:access_token]
140
- body_fields["id_token"] = opts[:id_token] if opts[:id_token]
141
- body = MultiJson.dump body_fields
142
- blk = proc do |request|
143
- params = Addressable::URI.form_unencode request.body
144
- claim, _header = JWT.decode(params.assoc("assertion").last,
145
- @key.public_key, true,
146
- algorithm: "RS256")
147
- !opts[:id_token] || claim["target_audience"] == "https://pubsub.googleapis.com/"
148
- end
149
- stub_request(:post, "https://www.googleapis.com/oauth2/v4/token")
150
- .with(body: hash_including(
151
- "grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer"
152
- ), &blk)
153
- .to_return(body: body,
154
- status: 200,
155
- headers: { "Content-Type" => "application/json" })
156
- end
157
-
158
- def cred_json_text
159
- MultiJson.dump cred_json
160
- end
161
-
162
- it_behaves_like "apply/apply! are OK"
163
-
164
- context "when scope is nil" do
165
- before :example do
166
- @client.scope = nil
167
- end
168
-
169
- it_behaves_like "jwt header auth"
170
- end
171
-
172
- describe "#from_env" do
173
- before :example do
174
- @var_name = ENV_VAR
175
- @credential_vars = [
176
- ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
177
- ]
178
- @original_env_vals = {}
179
- @credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
180
- ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
181
-
182
- @scope = "https://www.googleapis.com/auth/userinfo.profile"
183
- @clz = ServiceAccountCredentials
184
- end
185
-
186
- after :example do
187
- @credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
188
- end
189
-
190
- it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do
191
- ENV.delete @var_name unless ENV[@var_name].nil?
192
- expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
193
- end
194
-
195
- it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is empty" do
196
- ENV[@var_name] = ""
197
- expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
198
- end
199
-
200
- it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do
201
- ENV.delete @var_name unless ENV[@var_name].nil?
202
- expect(ServiceAccountCredentials.from_env(@scope)).to be_nil
203
- Dir.mktmpdir do |dir|
204
- key_path = File.join dir, "does-not-exist"
205
- ENV[@var_name] = key_path
206
- expect { @clz.from_env @scope }.to raise_error RuntimeError
207
- end
208
- end
209
-
210
- it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do
211
- Dir.mktmpdir do |dir|
212
- key_path = File.join dir, "my_cert_file"
213
- FileUtils.mkdir_p File.dirname(key_path)
214
- File.write key_path, cred_json_text
215
- ENV[@var_name] = key_path
216
- expect(@clz.from_env(@scope)).to_not be_nil
217
- end
218
- end
219
-
220
- it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\
221
- " valid" do
222
- ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
223
- ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
224
- expect(@clz.from_env(@scope)).to_not be_nil
225
- end
226
-
227
- it "sets project_id when the PROJECT_ID_VAR env var is set" do
228
- ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
229
- ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
230
- ENV[PROJECT_ID_VAR] = cred_json[:project_id]
231
- ENV[ENV_VAR] = nil
232
- credentials = @clz.from_env @scope
233
- expect(credentials.project_id).to eq(cred_json[:project_id])
234
- end
235
-
236
- it "succeeds when GOOGLE_PRIVATE_KEY is escaped" do
237
- escaped_key = cred_json[:private_key].gsub "\n", '\n'
238
- ENV[PRIVATE_KEY_VAR] = "\"#{escaped_key}\""
239
- ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
240
- expect(@clz.from_env(@scope)).to_not be_nil
241
- end
242
-
243
- it "propagates default_connection option" do
244
- ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
245
- ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
246
- connection = Faraday.new headers: { "User-Agent" => "hello" }
247
- creds = @clz.from_env @scope, default_connection: connection
248
- expect(creds.build_default_connection).to be connection
249
- end
250
- end
251
-
252
- describe "#from_well_known_path" do
253
- before :example do
254
- @home = ENV["HOME"]
255
- @app_data = ENV["APPDATA"]
256
- @scope = "https://www.googleapis.com/auth/userinfo.profile"
257
- @known_path = WELL_KNOWN_PATH
258
- @clz = ServiceAccountCredentials
259
- end
260
-
261
- after :example do
262
- ENV["HOME"] = @home unless @home == ENV["HOME"]
263
- ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"]
264
- end
265
-
266
- it "is nil if no file exists" do
267
- ENV["HOME"] = File.dirname __FILE__
268
- expect(ServiceAccountCredentials.from_well_known_path(@scope)).to be_nil
269
- end
270
-
271
- it "successfully loads the file when it is present" do
272
- Dir.mktmpdir do |dir|
273
- key_path = File.join dir, ".config", @known_path
274
- key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
275
- FileUtils.mkdir_p File.dirname(key_path)
276
- File.write key_path, cred_json_text
277
- ENV["HOME"] = dir
278
- ENV["APPDATA"] = dir
279
- expect(@clz.from_well_known_path(@scope)).to_not be_nil
280
- end
281
- end
282
-
283
- it "successfully sets project_id when file is present" do
284
- Dir.mktmpdir do |dir|
285
- key_path = File.join dir, ".config", @known_path
286
- key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
287
- FileUtils.mkdir_p File.dirname(key_path)
288
- File.write key_path, cred_json_text
289
- ENV["HOME"] = dir
290
- ENV["APPDATA"] = dir
291
- credentials = @clz.from_well_known_path @scope
292
- expect(credentials.project_id).to eq(cred_json[:project_id])
293
- expect(credentials.quota_project_id).to eq(cred_json[:quota_project_id])
294
- end
295
- end
296
-
297
- it "propagates default_connection option" do
298
- Dir.mktmpdir do |dir|
299
- key_path = File.join dir, ".config", @known_path
300
- key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
301
- FileUtils.mkdir_p File.dirname(key_path)
302
- File.write key_path, cred_json_text
303
- ENV["HOME"] = dir
304
- ENV["APPDATA"] = dir
305
- connection = Faraday.new headers: { "User-Agent" => "hello" }
306
- creds = @clz.from_well_known_path @scope, default_connection: connection
307
- expect(creds.build_default_connection).to be connection
308
- end
309
- end
310
- end
311
-
312
- describe "#from_system_default_path" do
313
- before :example do
314
- @scope = "https://www.googleapis.com/auth/userinfo.profile"
315
- @program_data = ENV["ProgramData"]
316
- @prefix = OS.windows? ? "/etc/Google/Auth/" : "/etc/google/auth/"
317
- @path = File.join @prefix, CREDENTIALS_FILE_NAME
318
- @clz = ServiceAccountCredentials
319
- end
320
-
321
- after :example do
322
- ENV["ProgramData"] = @program_data
323
- end
324
-
325
- it "is nil if no file exists" do
326
- FakeFS do
327
- expect(ServiceAccountCredentials.from_system_default_path(@scope))
328
- .to be_nil
329
- end
330
- end
331
-
332
- it "successfully loads the file when it is present" do
333
- FakeFS do
334
- ENV["ProgramData"] = "/etc"
335
- FileUtils.mkdir_p File.dirname(@path)
336
- File.write @path, cred_json_text
337
- expect(@clz.from_system_default_path(@scope)).to_not be_nil
338
- File.delete @path
339
- end
340
- end
341
-
342
- it "propagates default_connection option" do
343
- FakeFS do
344
- ENV["ProgramData"] = "/etc"
345
- FileUtils.mkdir_p File.dirname(@path)
346
- File.write @path, cred_json_text
347
- connection = Faraday.new headers: { "User-Agent" => "hello" }
348
- creds = @clz.from_system_default_path @scope, default_connection: connection
349
- expect(creds.build_default_connection).to be connection
350
- File.delete @path
351
- end
352
- end
353
- end
354
- end
355
-
356
- describe Google::Auth::ServiceAccountJwtHeaderCredentials do
357
- ServiceAccountJwtHeaderCredentials =
358
- Google::Auth::ServiceAccountJwtHeaderCredentials
359
-
360
- let(:client_email) { "app@developer.gserviceaccount.com" }
361
- let(:clz) { Google::Auth::ServiceAccountJwtHeaderCredentials }
362
- let :cred_json do
363
- {
364
- private_key_id: "a_private_key_id",
365
- private_key: @key.to_pem,
366
- client_email: client_email,
367
- client_id: "app.apps.googleusercontent.com",
368
- type: "service_account",
369
- project_id: "a_project_id"
370
- }
371
- end
372
-
373
- before :example do
374
- @key = OpenSSL::PKey::RSA.new 2048
375
- @client = clz.make_creds json_key_io: StringIO.new(cred_json_text)
376
- end
377
-
378
- def cred_json_text
379
- MultiJson.dump cred_json
380
- end
381
-
382
- it_behaves_like "jwt header auth"
383
-
384
- describe "#from_env" do
385
- before :example do
386
- @var_name = ENV_VAR
387
- @credential_vars = [
388
- ENV_VAR, PRIVATE_KEY_VAR, CLIENT_EMAIL_VAR, ACCOUNT_TYPE_VAR
389
- ]
390
- @original_env_vals = {}
391
- @credential_vars.each { |var| @original_env_vals[var] = ENV[var] }
392
- ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
393
- end
394
-
395
- after :example do
396
- @credential_vars.each { |var| ENV[var] = @original_env_vals[var] }
397
- end
398
-
399
- it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is unset" do
400
- ENV.delete @var_name unless ENV[@var_name].nil?
401
- expect(clz.from_env).to be_nil
402
- end
403
-
404
- it "returns nil if the GOOGLE_APPLICATION_CREDENTIALS is empty" do
405
- ENV[@var_name] = ""
406
- expect(clz.from_env).to be_nil
407
- end
408
-
409
- it "fails if the GOOGLE_APPLICATION_CREDENTIALS path does not exist" do
410
- ENV.delete @var_name unless ENV[@var_name].nil?
411
- expect(clz.from_env).to be_nil
412
- Dir.mktmpdir do |dir|
413
- key_path = File.join dir, "does-not-exist"
414
- ENV[@var_name] = key_path
415
- expect { clz.from_env }.to raise_error RuntimeError
416
- end
417
- end
418
-
419
- it "succeeds when the GOOGLE_APPLICATION_CREDENTIALS file is valid" do
420
- Dir.mktmpdir do |dir|
421
- key_path = File.join dir, "my_cert_file"
422
- FileUtils.mkdir_p File.dirname(key_path)
423
- File.write key_path, cred_json_text
424
- ENV[@var_name] = key_path
425
- expect(clz.from_env).to_not be_nil
426
- end
427
- end
428
-
429
- it "succeeds when GOOGLE_PRIVATE_KEY and GOOGLE_CLIENT_EMAIL env vars are"\
430
- " valid" do
431
- ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
432
- ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
433
- expect(clz.from_env(@scope)).to_not be_nil
434
- end
435
-
436
- it "sets project_id when the PROJECT_ID_VAR env var is set" do
437
- ENV[PRIVATE_KEY_VAR] = cred_json[:private_key]
438
- ENV[CLIENT_EMAIL_VAR] = cred_json[:client_email]
439
- ENV[PROJECT_ID_VAR] = cred_json[:project_id]
440
- ENV[ENV_VAR] = nil
441
- credentials = clz.from_env @scope
442
- expect(credentials).to_not be_nil
443
- expect(credentials.project_id).to eq(cred_json[:project_id])
444
- end
445
- end
446
-
447
- describe "#from_well_known_path" do
448
- before :example do
449
- @home = ENV["HOME"]
450
- @app_data = ENV["APPDATA"]
451
- end
452
-
453
- after :example do
454
- ENV["HOME"] = @home unless @home == ENV["HOME"]
455
- ENV["APPDATA"] = @app_data unless @app_data == ENV["APPDATA"]
456
- end
457
-
458
- it "is nil if no file exists" do
459
- ENV["HOME"] = File.dirname __FILE__
460
- expect(clz.from_well_known_path).to be_nil
461
- end
462
-
463
- it "successfully loads the file when it is present" do
464
- Dir.mktmpdir do |dir|
465
- key_path = File.join dir, ".config", WELL_KNOWN_PATH
466
- key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
467
- FileUtils.mkdir_p File.dirname(key_path)
468
- File.write key_path, cred_json_text
469
- ENV["HOME"] = dir
470
- ENV["APPDATA"] = dir
471
- expect(clz.from_well_known_path).to_not be_nil
472
- end
473
- end
474
-
475
- it "successfully sets project_id when file is present" do
476
- Dir.mktmpdir do |dir|
477
- key_path = File.join dir, ".config", WELL_KNOWN_PATH
478
- key_path = File.join dir, WELL_KNOWN_PATH if OS.windows?
479
- FileUtils.mkdir_p File.dirname(key_path)
480
- File.write key_path, cred_json_text
481
- ENV["HOME"] = dir
482
- ENV["APPDATA"] = dir
483
- credentials = clz.from_well_known_path @scope
484
- expect(credentials.project_id).to eq(cred_json[:project_id])
485
- expect(credentials.quota_project_id).to be_nil
486
- end
487
- end
488
- end
489
- end
@@ -1,142 +0,0 @@
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
- spec_dir = File.expand_path File.join(File.dirname(__FILE__))
31
- $LOAD_PATH.unshift spec_dir
32
- $LOAD_PATH.uniq!
33
-
34
- require "apply_auth_examples"
35
- require "googleauth/signet"
36
- require "jwt"
37
- require "openssl"
38
- require "spec_helper"
39
-
40
- describe Signet::OAuth2::Client do
41
- before :example do
42
- @key = OpenSSL::PKey::RSA.new 2048
43
- @client = Signet::OAuth2::Client.new(
44
- token_credential_uri: "https://oauth2.googleapis.com/token",
45
- scope: "https://www.googleapis.com/auth/userinfo.profile",
46
- issuer: "app@example.com",
47
- audience: "https://oauth2.googleapis.com/token",
48
- signing_key: @key
49
- )
50
- @id_client = Signet::OAuth2::Client.new(
51
- token_credential_uri: "https://oauth2.googleapis.com/token",
52
- target_audience: "https://pubsub.googleapis.com/",
53
- issuer: "app@example.com",
54
- audience: "https://oauth2.googleapis.com/token",
55
- signing_key: @key
56
- )
57
- end
58
-
59
- def make_auth_stubs opts
60
- body_fields = { "token_type" => "Bearer", "expires_in" => 3600 }
61
- body_fields["access_token"] = opts[:access_token] if opts[:access_token]
62
- body_fields["id_token"] = opts[:id_token] if opts[:id_token]
63
- body = MultiJson.dump body_fields
64
- blk = proc do |request|
65
- params = Addressable::URI.form_unencode request.body
66
- claim, _header = JWT.decode(params.assoc("assertion").last,
67
- @key.public_key, true,
68
- algorithm: "RS256")
69
- !opts[:id_token] || claim["target_audience"] == "https://pubsub.googleapis.com/"
70
- end
71
- with_params = { body: hash_including(
72
- "grant_type" => "urn:ietf:params:oauth:grant-type:jwt-bearer"
73
- ) }
74
- with_params[:headers] = { "User-Agent" => opts[:user_agent] } if opts[:user_agent]
75
- stub_request(:post, "https://oauth2.googleapis.com/token")
76
- .with(with_params, &blk)
77
- .to_return(body: body,
78
- status: 200,
79
- headers: { "Content-Type" => "application/json" })
80
- end
81
-
82
- it_behaves_like "apply/apply! are OK"
83
-
84
- describe "#configure_connection" do
85
- it "honors default_connection" do
86
- token = "1/abcdef1234567890"
87
- stub = make_auth_stubs access_token: token, user_agent: "RubyRocks/1.0"
88
- conn = Faraday.new headers: { "User-Agent" => "RubyRocks/1.0" }
89
- @client.configure_connection default_connection: conn
90
- md = { foo: "bar" }
91
- @client.apply! md
92
- want = { foo: "bar", authorization: "Bearer #{token}" }
93
- expect(md).to eq(want)
94
- expect(stub).to have_been_requested
95
- end
96
-
97
- it "honors connection_builder" do
98
- token = "1/abcdef1234567890"
99
- stub = make_auth_stubs access_token: token, user_agent: "RubyRocks/2.0"
100
- connection_builder = proc do
101
- Faraday.new headers: { "User-Agent" => "RubyRocks/2.0" }
102
- end
103
- @client.configure_connection connection_builder: connection_builder
104
- md = { foo: "bar" }
105
- @client.apply! md
106
- want = { foo: "bar", authorization: "Bearer #{token}" }
107
- expect(md).to eq(want)
108
- expect(stub).to have_been_requested
109
- end
110
- end
111
-
112
- describe "#fetch_access_token!" do
113
- it "retries when orig_fetch_access_token! raises Signet::RemoteServerError" do
114
- mocked_responses = [:raise, :raise, "success"]
115
- allow(@client).to receive(:orig_fetch_access_token!).exactly(3).times do
116
- response = mocked_responses.shift
117
- response == :raise ? raise(Signet::RemoteServerError) : response
118
- end
119
- expect(@client.fetch_access_token!).to eq("success")
120
- end
121
-
122
- it "raises when the max retry count is exceeded" do
123
- mocked_responses = [:raise, :raise, :raise, :raise, :raise, :raise, "success"]
124
- allow(@client).to receive(:orig_fetch_access_token!).exactly(6).times do
125
- response = mocked_responses.shift
126
- response == :raise ? raise(Signet::RemoteServerError) : response
127
- end
128
- expect { @client.fetch_access_token! }.to raise_error Signet::AuthorizationError
129
- end
130
-
131
- it "does not retry and raises right away if it encounters a Signet::AuthorizationError" do
132
- allow(@client).to receive(:orig_fetch_access_token!).at_most(:once)
133
- .and_raise(Signet::AuthorizationError.new("Some Message"))
134
- expect { @client.fetch_access_token! }.to raise_error Signet::AuthorizationError
135
- end
136
-
137
- it "does not retry and raises right away if it encounters a Signet::ParseError" do
138
- allow(@client).to receive(:orig_fetch_access_token!).at_most(:once).and_raise(Signet::ParseError)
139
- expect { @client.fetch_access_token! }.to raise_error Signet::ParseError
140
- end
141
- end
142
- end
@@ -1,57 +0,0 @@
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
- spec_dir = File.expand_path File.join(File.dirname(__FILE__))
31
- $LOAD_PATH.unshift spec_dir
32
- $LOAD_PATH.uniq!
33
-
34
- require "googleauth"
35
- require "googleauth/stores/file_token_store"
36
- require "spec_helper"
37
- require "fakefs/safe"
38
- require "fakefs/spec_helpers"
39
- require "googleauth/stores/store_examples"
40
-
41
- module FakeFS
42
- class File
43
- # FakeFS doesn't implement. And since we don't need to actually lock,
44
- # just stub out...
45
- def flock *; end
46
- end
47
- end
48
-
49
- describe Google::Auth::Stores::FileTokenStore do
50
- include FakeFS::SpecHelpers
51
-
52
- let :store do
53
- Google::Auth::Stores::FileTokenStore.new file: "/tokens.yaml"
54
- end
55
-
56
- it_behaves_like "token store"
57
- end