googleauth 0.14.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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,50 +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/redis_token_store"
36
- require "spec_helper"
37
- require "fakeredis/rspec"
38
- require "googleauth/stores/store_examples"
39
-
40
- describe Google::Auth::Stores::RedisTokenStore do
41
- let :redis do
42
- Redis.new
43
- end
44
-
45
- let :store do
46
- Google::Auth::Stores::RedisTokenStore.new redis: redis
47
- end
48
-
49
- it_behaves_like "token store"
50
- end
@@ -1,58 +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 "spec_helper"
35
-
36
- shared_examples "token store" do
37
- before :each do
38
- store.store "default", "test"
39
- end
40
-
41
- it "should return a stored value" do
42
- expect(store.load("default")).to eq "test"
43
- end
44
-
45
- it "should return nil for missing tokens" do
46
- expect(store.load("notavalidkey")).to be_nil
47
- end
48
-
49
- it "should return nil for deleted tokens" do
50
- store.delete "default"
51
- expect(store.load("default")).to be_nil
52
- end
53
-
54
- it "should save overwrite values on store" do
55
- store.store "default", "test2"
56
- expect(store.load("default")).to eq "test2"
57
- end
58
- end
@@ -1,343 +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/user_authorizer"
36
- require "uri"
37
- require "multi_json"
38
- require "spec_helper"
39
-
40
- describe Google::Auth::UserAuthorizer do
41
- include TestHelpers
42
-
43
- let(:client_id) { Google::Auth::ClientId.new "testclient", "notasecret" }
44
- let(:scope) { %w[email profile] }
45
- let(:token_store) { DummyTokenStore.new }
46
- let(:callback_uri) { "https://www.example.com/oauth/callback" }
47
- let :authorizer do
48
- Google::Auth::UserAuthorizer.new(client_id,
49
- scope,
50
- token_store,
51
- callback_uri)
52
- end
53
-
54
- shared_examples "valid authorization url" do
55
- it "should have a valid base URI" do
56
- expect(uri).to match %r{https://accounts.google.com/o/oauth2/auth}
57
- end
58
-
59
- it "should request offline access" do
60
- expect(URI(uri).query).to match(/access_type=offline/)
61
- end
62
-
63
- it "should request response type code" do
64
- expect(URI(uri).query).to match(/response_type=code/)
65
- end
66
-
67
- it "should force approval" do
68
- expect(URI(uri).query).to match(/approval_prompt=force/)
69
- end
70
-
71
- it "should include granted scopes" do
72
- expect(URI(uri).query).to match(/include_granted_scopes=true/)
73
- end
74
-
75
- it "should include the correct client id" do
76
- expect(URI(uri).query).to match(/client_id=testclient/)
77
- end
78
-
79
- it "should not include a client secret" do
80
- expect(URI(uri).query).to_not match(/client_secret/)
81
- end
82
-
83
- it "should include the redirect_uri" do
84
- expect(URI(uri).query).to match(
85
- %r{redirect_uri=https://www.example.com/oauth/callback}
86
- )
87
- end
88
-
89
- it "should include the scope" do
90
- expect(URI(uri).query).to match(/scope=email%20profile/)
91
- end
92
- end
93
-
94
- context "when generating authorization URLs and callback_uri is 'postmessage'" do
95
- let(:callback_uri) { "postmessage" }
96
- let :authorizer do
97
- Google::Auth::UserAuthorizer.new(client_id,
98
- scope,
99
- token_store,
100
- callback_uri)
101
- end
102
- let :uri do
103
- authorizer.get_authorization_url login_hint: "user1", state: "mystate"
104
- end
105
-
106
- it "should include the redirect_uri 'postmessage'" do
107
- expect(URI(uri).query).to match(
108
- %r{redirect_uri=postmessage}
109
- )
110
- end
111
- end
112
-
113
- context "when generating authorization URLs with user ID & state" do
114
- let :uri do
115
- authorizer.get_authorization_url login_hint: "user1", state: "mystate"
116
- end
117
-
118
- it_behaves_like "valid authorization url"
119
-
120
- it "includes a login hint" do
121
- expect(URI(uri).query).to match(/login_hint=user1/)
122
- end
123
-
124
- it "includes the app state" do
125
- expect(URI(uri).query).to match(/state=mystate/)
126
- end
127
- end
128
-
129
- context "when generating authorization URLs with user ID and no state" do
130
- let(:uri) { authorizer.get_authorization_url login_hint: "user1" }
131
-
132
- it_behaves_like "valid authorization url"
133
-
134
- it "includes a login hint" do
135
- expect(URI(uri).query).to match(/login_hint=user1/)
136
- end
137
-
138
- it "does not include the state parameter" do
139
- expect(URI(uri).query).to_not match(/state/)
140
- end
141
- end
142
-
143
- context "when generating authorization URLs with no user ID and no state" do
144
- let(:uri) { authorizer.get_authorization_url }
145
-
146
- it_behaves_like "valid authorization url"
147
-
148
- it "does not include the login hint parameter" do
149
- expect(URI(uri).query).to_not match(/login_hint/)
150
- end
151
-
152
- it "does not include the state parameter" do
153
- expect(URI(uri).query).to_not match(/state/)
154
- end
155
- end
156
-
157
- context "when retrieving tokens" do
158
- let :token_json do
159
- MultiJson.dump(
160
- access_token: "accesstoken",
161
- refresh_token: "refreshtoken",
162
- expiration_time_millis: 1_441_234_742_000
163
- )
164
- end
165
-
166
- context "with a valid user id" do
167
- let :credentials do
168
- token_store.store "user1", token_json
169
- authorizer.get_credentials "user1"
170
- end
171
-
172
- it "should return an instance of UserRefreshCredentials" do
173
- expect(credentials).to be_instance_of(
174
- Google::Auth::UserRefreshCredentials
175
- )
176
- end
177
-
178
- it "should return credentials with a valid refresh token" do
179
- expect(credentials.refresh_token).to eq "refreshtoken"
180
- end
181
-
182
- it "should return credentials with a valid access token" do
183
- expect(credentials.access_token).to eq "accesstoken"
184
- end
185
-
186
- it "should return credentials with a valid client ID" do
187
- expect(credentials.client_id).to eq "testclient"
188
- end
189
-
190
- it "should return credentials with a valid client secret" do
191
- expect(credentials.client_secret).to eq "notasecret"
192
- end
193
-
194
- it "should return credentials with a valid scope" do
195
- expect(credentials.scope).to eq %w[email profile]
196
- end
197
-
198
- it "should return credentials with a valid expiration time" do
199
- expect(credentials.expires_at).to eq Time.at(1_441_234_742)
200
- end
201
- end
202
-
203
- context "with an invalid user id" do
204
- it "should return nil" do
205
- expect(authorizer.get_credentials("notauser")).to be_nil
206
- end
207
- end
208
- end
209
-
210
- context "when saving tokens" do
211
- let(:expiry) { Time.now.to_i }
212
- let :credentials do
213
- Google::Auth::UserRefreshCredentials.new(
214
- client_id: client_id.id,
215
- client_secret: client_id.secret,
216
- scope: scope,
217
- refresh_token: "refreshtoken",
218
- access_token: "accesstoken",
219
- expires_at: expiry
220
- )
221
- end
222
-
223
- let :token_json do
224
- authorizer.store_credentials "user1", credentials
225
- token_store.load "user1"
226
- end
227
-
228
- it "should persist in the token store" do
229
- expect(token_json).to_not be_nil
230
- end
231
-
232
- it "should persist the refresh token" do
233
- expect(MultiJson.load(token_json)["refresh_token"]).to eq "refreshtoken"
234
- end
235
-
236
- it "should persist the access token" do
237
- expect(MultiJson.load(token_json)["access_token"]).to eq "accesstoken"
238
- end
239
-
240
- it "should persist the client id" do
241
- expect(MultiJson.load(token_json)["client_id"]).to eq "testclient"
242
- end
243
-
244
- it "should persist the scope" do
245
- expect(MultiJson.load(token_json)["scope"]).to include("email", "profile")
246
- end
247
-
248
- it "should persist the expiry as milliseconds" do
249
- expected_expiry = expiry * 1000
250
- expect(MultiJson.load(token_json)["expiration_time_millis"]).to eql(
251
- expected_expiry
252
- )
253
- end
254
- end
255
-
256
- context "with valid authorization code" do
257
- let :token_json do
258
- MultiJson.dump("access_token" => "1/abc123",
259
- "token_type" => "Bearer",
260
- "expires_in" => 3600)
261
- end
262
-
263
- before :example do
264
- stub_request(:post, "https://oauth2.googleapis.com/token")
265
- .to_return(body: token_json, status: 200, headers: {
266
- "Content-Type" => "application/json"
267
- })
268
- end
269
-
270
- it "should exchange a code for credentials" do
271
- credentials = authorizer.get_credentials_from_code(
272
- user_id: "user1", code: "code"
273
- )
274
- expect(credentials.access_token).to eq "1/abc123"
275
- expect(credentials.redirect_uri.to_s).to eq "https://www.example.com/oauth/callback"
276
- end
277
-
278
- it "should not store credentials when get only requested" do
279
- authorizer.get_credentials_from_code user_id: "user1", code: "code"
280
- expect(token_store.load("user1")).to be_nil
281
- end
282
-
283
- it "should store credentials when requested" do
284
- authorizer.get_and_store_credentials_from_code(
285
- user_id: "user1", code: "code"
286
- )
287
- expect(token_store.load("user1")).to_not be_nil
288
- end
289
- end
290
-
291
- context "with invalid authorization code" do
292
- before :example do
293
- stub_request(:post, "https://oauth2.googleapis.com/token")
294
- .to_return(status: 400)
295
- end
296
-
297
- it "should raise an authorization error" do
298
- expect do
299
- authorizer.get_credentials_from_code user_id: "user1", code: "badcode"
300
- end.to raise_error Signet::AuthorizationError
301
- end
302
-
303
- it "should not store credentials when exchange fails" do
304
- expect do
305
- authorizer.get_credentials_from_code user_id: "user1", code: "badcode"
306
- end.to raise_error Signet::AuthorizationError
307
- expect(token_store.load("user1")).to be_nil
308
- end
309
- end
310
-
311
- context "when reovking authorization" do
312
- let :token_json do
313
- MultiJson.dump(
314
- access_token: "accesstoken",
315
- refresh_token: "refreshtoken",
316
- expiration_time_millis: 1_441_234_742_000
317
- )
318
- end
319
-
320
- before :example do
321
- token_store.store "user1", token_json
322
- stub_request(:post, "https://oauth2.googleapis.com/revoke")
323
- .with(body: hash_including("token" => "refreshtoken"))
324
- .to_return(status: 200)
325
- end
326
-
327
- it "should revoke the grant" do
328
- authorizer.revoke_authorization "user1"
329
- expect(a_request(
330
- :post, "https://oauth2.googleapis.com/revoke"
331
- ).with(body: hash_including("token" => "refreshtoken")))
332
- .to have_been_made
333
- end
334
-
335
- it "should remove the token from storage" do
336
- authorizer.revoke_authorization "user1"
337
- expect(token_store.load("user1")).to be_nil
338
- end
339
- end
340
-
341
- # TODO: - Test that tokens are monitored
342
- # TODO - Test scope enforcement (auth if upgrade required)
343
- end