googleauth 0.9.0 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/CHANGELOG.md +113 -21
  4. data/README.md +13 -15
  5. data/SECURITY.md +7 -0
  6. data/lib/googleauth/application_default.rb +9 -9
  7. data/lib/googleauth/compute_engine.rb +55 -30
  8. data/lib/googleauth/credentials.rb +253 -64
  9. data/lib/googleauth/credentials_loader.rb +15 -16
  10. data/lib/googleauth/iam.rb +1 -1
  11. data/{spec/googleauth/stores/store_examples.rb → lib/googleauth/id_tokens/errors.rb} +36 -23
  12. data/lib/googleauth/id_tokens/key_sources.rb +396 -0
  13. data/lib/googleauth/id_tokens/verifier.rb +142 -0
  14. data/lib/googleauth/id_tokens.rb +233 -0
  15. data/lib/googleauth/json_key_reader.rb +6 -2
  16. data/lib/googleauth/scope_util.rb +1 -1
  17. data/lib/googleauth/service_account.rb +61 -36
  18. data/lib/googleauth/signet.rb +9 -7
  19. data/lib/googleauth/stores/file_token_store.rb +1 -0
  20. data/lib/googleauth/stores/redis_token_store.rb +1 -0
  21. data/lib/googleauth/user_authorizer.rb +8 -3
  22. data/lib/googleauth/user_refresh.rb +1 -1
  23. data/lib/googleauth/version.rb +1 -1
  24. data/lib/googleauth/web_user_authorizer.rb +5 -8
  25. data/lib/googleauth.rb +1 -0
  26. metadata +33 -76
  27. data/.github/CONTRIBUTING.md +0 -74
  28. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -36
  29. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -21
  30. data/.github/ISSUE_TEMPLATE/support_request.md +0 -7
  31. data/.gitignore +0 -36
  32. data/.kokoro/build.bat +0 -16
  33. data/.kokoro/build.sh +0 -4
  34. data/.kokoro/continuous/common.cfg +0 -24
  35. data/.kokoro/continuous/linux.cfg +0 -15
  36. data/.kokoro/continuous/osx.cfg +0 -3
  37. data/.kokoro/continuous/windows.cfg +0 -19
  38. data/.kokoro/osx.sh +0 -4
  39. data/.kokoro/presubmit/common.cfg +0 -24
  40. data/.kokoro/presubmit/linux.cfg +0 -14
  41. data/.kokoro/presubmit/osx.cfg +0 -3
  42. data/.kokoro/presubmit/windows.cfg +0 -19
  43. data/.kokoro/release.cfg +0 -53
  44. data/.kokoro/trampoline.bat +0 -10
  45. data/.kokoro/trampoline.sh +0 -4
  46. data/.rspec +0 -2
  47. data/.rubocop.yml +0 -42
  48. data/Gemfile +0 -25
  49. data/Rakefile +0 -89
  50. data/googleauth.gemspec +0 -35
  51. data/spec/googleauth/apply_auth_examples.rb +0 -148
  52. data/spec/googleauth/client_id_spec.rb +0 -160
  53. data/spec/googleauth/compute_engine_spec.rb +0 -122
  54. data/spec/googleauth/credentials_spec.rb +0 -459
  55. data/spec/googleauth/get_application_default_spec.rb +0 -286
  56. data/spec/googleauth/iam_spec.rb +0 -80
  57. data/spec/googleauth/scope_util_spec.rb +0 -77
  58. data/spec/googleauth/service_account_spec.rb +0 -482
  59. data/spec/googleauth/signet_spec.rb +0 -134
  60. data/spec/googleauth/stores/file_token_store_spec.rb +0 -57
  61. data/spec/googleauth/stores/redis_token_store_spec.rb +0 -50
  62. data/spec/googleauth/user_authorizer_spec.rb +0 -323
  63. data/spec/googleauth/user_refresh_spec.rb +0 -359
  64. data/spec/googleauth/web_user_authorizer_spec.rb +0 -172
  65. data/spec/spec_helper.rb +0 -92
  66. /data/{COPYING → LICENSE} +0 -0
@@ -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,323 +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 callback 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 with user ID & state" do
95
- let :uri do
96
- authorizer.get_authorization_url login_hint: "user1", state: "mystate"
97
- end
98
-
99
- it_behaves_like "valid authorization url"
100
-
101
- it "includes a login hint" do
102
- expect(URI(uri).query).to match(/login_hint=user1/)
103
- end
104
-
105
- it "includes the app state" do
106
- expect(URI(uri).query).to match(/state=mystate/)
107
- end
108
- end
109
-
110
- context "when generating authorization URLs with user ID and no state" do
111
- let(:uri) { authorizer.get_authorization_url login_hint: "user1" }
112
-
113
- it_behaves_like "valid authorization url"
114
-
115
- it "includes a login hint" do
116
- expect(URI(uri).query).to match(/login_hint=user1/)
117
- end
118
-
119
- it "does not include the state parameter" do
120
- expect(URI(uri).query).to_not match(/state/)
121
- end
122
- end
123
-
124
- context "when generating authorization URLs with no user ID and no state" do
125
- let(:uri) { authorizer.get_authorization_url }
126
-
127
- it_behaves_like "valid authorization url"
128
-
129
- it "does not include the login hint parameter" do
130
- expect(URI(uri).query).to_not match(/login_hint/)
131
- end
132
-
133
- it "does not include the state parameter" do
134
- expect(URI(uri).query).to_not match(/state/)
135
- end
136
- end
137
-
138
- context "when retrieving tokens" do
139
- let :token_json do
140
- MultiJson.dump(
141
- access_token: "accesstoken",
142
- refresh_token: "refreshtoken",
143
- expiration_time_millis: 1_441_234_742_000
144
- )
145
- end
146
-
147
- context "with a valid user id" do
148
- let :credentials do
149
- token_store.store "user1", token_json
150
- authorizer.get_credentials "user1"
151
- end
152
-
153
- it "should return an instance of UserRefreshCredentials" do
154
- expect(credentials).to be_instance_of(
155
- Google::Auth::UserRefreshCredentials
156
- )
157
- end
158
-
159
- it "should return credentials with a valid refresh token" do
160
- expect(credentials.refresh_token).to eq "refreshtoken"
161
- end
162
-
163
- it "should return credentials with a valid access token" do
164
- expect(credentials.access_token).to eq "accesstoken"
165
- end
166
-
167
- it "should return credentials with a valid client ID" do
168
- expect(credentials.client_id).to eq "testclient"
169
- end
170
-
171
- it "should return credentials with a valid client secret" do
172
- expect(credentials.client_secret).to eq "notasecret"
173
- end
174
-
175
- it "should return credentials with a valid scope" do
176
- expect(credentials.scope).to eq %w[email profile]
177
- end
178
-
179
- it "should return credentials with a valid expiration time" do
180
- expect(credentials.expires_at).to eq Time.at(1_441_234_742)
181
- end
182
- end
183
-
184
- context "with an invalid user id" do
185
- it "should return nil" do
186
- expect(authorizer.get_credentials("notauser")).to be_nil
187
- end
188
- end
189
- end
190
-
191
- context "when saving tokens" do
192
- let(:expiry) { Time.now.to_i }
193
- let :credentials do
194
- Google::Auth::UserRefreshCredentials.new(
195
- client_id: client_id.id,
196
- client_secret: client_id.secret,
197
- scope: scope,
198
- refresh_token: "refreshtoken",
199
- access_token: "accesstoken",
200
- expires_at: expiry
201
- )
202
- end
203
-
204
- let :token_json do
205
- authorizer.store_credentials "user1", credentials
206
- token_store.load "user1"
207
- end
208
-
209
- it "should persist in the token store" do
210
- expect(token_json).to_not be_nil
211
- end
212
-
213
- it "should persist the refresh token" do
214
- expect(MultiJson.load(token_json)["refresh_token"]).to eq "refreshtoken"
215
- end
216
-
217
- it "should persist the access token" do
218
- expect(MultiJson.load(token_json)["access_token"]).to eq "accesstoken"
219
- end
220
-
221
- it "should persist the client id" do
222
- expect(MultiJson.load(token_json)["client_id"]).to eq "testclient"
223
- end
224
-
225
- it "should persist the scope" do
226
- expect(MultiJson.load(token_json)["scope"]).to include("email", "profile")
227
- end
228
-
229
- it "should persist the expiry as milliseconds" do
230
- expected_expiry = expiry * 1000
231
- expect(MultiJson.load(token_json)["expiration_time_millis"]).to eql(
232
- expected_expiry
233
- )
234
- end
235
- end
236
-
237
- context "with valid authorization code" do
238
- let :token_json do
239
- MultiJson.dump("access_token" => "1/abc123",
240
- "token_type" => "Bearer",
241
- "expires_in" => 3600)
242
- end
243
-
244
- before :example do
245
- stub_request(:post, "https://oauth2.googleapis.com/token")
246
- .to_return(body: token_json, status: 200, headers: {
247
- "Content-Type" => "application/json"
248
- })
249
- end
250
-
251
- it "should exchange a code for credentials" do
252
- credentials = authorizer.get_credentials_from_code(
253
- user_id: "user1", code: "code"
254
- )
255
- expect(credentials.access_token).to eq "1/abc123"
256
- end
257
-
258
- it "should not store credentials when get only requested" do
259
- authorizer.get_credentials_from_code user_id: "user1", code: "code"
260
- expect(token_store.load("user1")).to be_nil
261
- end
262
-
263
- it "should store credentials when requested" do
264
- authorizer.get_and_store_credentials_from_code(
265
- user_id: "user1", code: "code"
266
- )
267
- expect(token_store.load("user1")).to_not be_nil
268
- end
269
- end
270
-
271
- context "with invalid authorization code" do
272
- before :example do
273
- stub_request(:post, "https://oauth2.googleapis.com/token")
274
- .to_return(status: 400)
275
- end
276
-
277
- it "should raise an authorization error" do
278
- expect do
279
- authorizer.get_credentials_from_code user_id: "user1", code: "badcode"
280
- end.to raise_error Signet::AuthorizationError
281
- end
282
-
283
- it "should not store credentials when exchange fails" do
284
- expect do
285
- authorizer.get_credentials_from_code user_id: "user1", code: "badcode"
286
- end.to raise_error Signet::AuthorizationError
287
- expect(token_store.load("user1")).to be_nil
288
- end
289
- end
290
-
291
- context "when reovking authorization" do
292
- let :token_json do
293
- MultiJson.dump(
294
- access_token: "accesstoken",
295
- refresh_token: "refreshtoken",
296
- expiration_time_millis: 1_441_234_742_000
297
- )
298
- end
299
-
300
- before :example do
301
- token_store.store "user1", token_json
302
- stub_request(:post, "https://oauth2.googleapis.com/revoke")
303
- .with(body: hash_including("token" => "refreshtoken"))
304
- .to_return(status: 200)
305
- end
306
-
307
- it "should revoke the grant" do
308
- authorizer.revoke_authorization "user1"
309
- expect(a_request(
310
- :post, "https://oauth2.googleapis.com/revoke"
311
- ).with(body: hash_including("token" => "refreshtoken")))
312
- .to have_been_made
313
- end
314
-
315
- it "should remove the token from storage" do
316
- authorizer.revoke_authorization "user1"
317
- expect(token_store.load("user1")).to be_nil
318
- end
319
- end
320
-
321
- # TODO: - Test that tokens are monitored
322
- # TODO - Test scope enforcement (auth if upgrade required)
323
- end