signet 0.15.0 → 0.16.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.
- checksums.yaml +4 -4
- data/.yardopts +11 -0
- data/CHANGELOG.md +13 -0
- data/CODE_OF_CONDUCT.md +43 -0
- data/SECURITY.md +7 -0
- data/lib/signet/oauth_1/credential.rb +1 -1
- data/lib/signet/oauth_1/signature_methods/hmac_sha1.rb +1 -1
- data/lib/signet/oauth_1/signature_methods/plaintext.rb +1 -1
- data/lib/signet/oauth_1/signature_methods/rsa_sha1.rb +1 -1
- data/lib/signet/oauth_1.rb +1 -1
- data/lib/signet/oauth_2/client.rb +17 -12
- data/lib/signet/oauth_2.rb +1 -1
- data/lib/signet/version.rb +1 -1
- data/lib/signet.rb +1 -1
- metadata +24 -24
- data/Gemfile +0 -8
- data/Rakefile +0 -112
- data/signet.gemspec +0 -45
- data/spec/signet/oauth_1/client_spec.rb +0 -810
- data/spec/signet/oauth_1/credential_spec.rb +0 -169
- data/spec/signet/oauth_1/server_spec.rb +0 -839
- data/spec/signet/oauth_1/signature_methods/hmac_sha1_spec.rb +0 -61
- data/spec/signet/oauth_1/signature_methods/plaintext_spec.rb +0 -61
- data/spec/signet/oauth_1/signature_methods/rsa_sha1_spec.rb +0 -126
- data/spec/signet/oauth_1_spec.rb +0 -1036
- data/spec/signet/oauth_2/client_spec.rb +0 -1254
- data/spec/signet/oauth_2_spec.rb +0 -194
- data/spec/signet_spec.rb +0 -78
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -10
- data/spec/spec_helper_spec.rb +0 -17
- data/website/index.html +0 -95
@@ -1,1254 +0,0 @@
|
|
1
|
-
# Copyright (C) 2010 Google Inc.
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
require "spec_helper"
|
15
|
-
require "signet/oauth_2/client"
|
16
|
-
require "openssl"
|
17
|
-
require "jwt"
|
18
|
-
require "date"
|
19
|
-
|
20
|
-
conn = Faraday.default_connection
|
21
|
-
|
22
|
-
def build_json_response payload
|
23
|
-
[200, { "Content-Type" => "application/json; charset=utf-8" }, MultiJson.dump(payload)]
|
24
|
-
end
|
25
|
-
|
26
|
-
def build_form_encoded_response payload
|
27
|
-
[200, { "Content-Type" => "application/json; charset=utf-8" }, Addressable::URI.form_encode(payload)]
|
28
|
-
end
|
29
|
-
|
30
|
-
describe Signet::OAuth2::Client, "unconfigured" do
|
31
|
-
before do
|
32
|
-
@client = Signet::OAuth2::Client.new
|
33
|
-
end
|
34
|
-
it "should allow additional paraemters to be set." do
|
35
|
-
@client.additional_parameters["type"] = "web_server"
|
36
|
-
expect(@client.additional_parameters).to eq({ "type" => "web_server" })
|
37
|
-
end
|
38
|
-
it "should raise an error if a bogus scope is provided" do
|
39
|
-
expect(lambda do
|
40
|
-
@client = Signet::OAuth2::Client.new scope: :bogus
|
41
|
-
end).to raise_error(TypeError)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should raise an error if a scope array is provided with spaces" do
|
45
|
-
expect(lambda do
|
46
|
-
@client = Signet::OAuth2::Client.new(
|
47
|
-
scope: ["legit", "bogus bogus"]
|
48
|
-
)
|
49
|
-
end).to raise_error(ArgumentError)
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should allow the scope to be set to a String" do
|
53
|
-
@client.scope = "legit"
|
54
|
-
expect(@client.scope).to eq ["legit"]
|
55
|
-
@client.scope = "legit alsolegit"
|
56
|
-
expect(@client.scope).to eq ["legit", "alsolegit"]
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should allow the scope to be set to an Array" do
|
60
|
-
@client.scope = ["legit"]
|
61
|
-
expect(@client.scope).to eq ["legit"]
|
62
|
-
@client.scope = ["legit", "alsolegit"]
|
63
|
-
expect(@client.scope).to eq ["legit", "alsolegit"]
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should raise an error if a bogus redirect URI is provided" do
|
67
|
-
expect(lambda do
|
68
|
-
@client = Signet::OAuth2::Client.new redirect_uri: :bogus
|
69
|
-
end).to raise_error(TypeError)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should raise an error if a relative redirect URI is provided" do
|
73
|
-
expect(lambda do
|
74
|
-
@client = Signet::OAuth2::Client.new redirect_uri: "/relative/path"
|
75
|
-
end).to raise_error(ArgumentError)
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'should allow "postmessage" as a redirect URI (Google hack)' do
|
79
|
-
@client.authorization_uri = "https://example.com/authorize"
|
80
|
-
@client.client_id = "s6BhdRkqt3"
|
81
|
-
@client.redirect_uri = "postmessage"
|
82
|
-
expect(@client.authorization_uri.query_values["redirect_uri"]).to eq "postmessage"
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should allow oob values as a redirect URI (for installed apps)" do
|
86
|
-
@client.authorization_uri = "https://example.com/authorize"
|
87
|
-
@client.client_id = "s6BhdRkqt3"
|
88
|
-
@client.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
89
|
-
expect(@client.authorization_uri.query_values["redirect_uri"]).to eq "urn:ietf:wg:oauth:2.0:oob"
|
90
|
-
@client.redirect_uri = "oob"
|
91
|
-
expect(@client.authorization_uri.query_values["redirect_uri"]).to eq "oob"
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should have no authorization_uri" do
|
95
|
-
expect(@client.authorization_uri).to eq nil
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should allow the authorization_uri to be set to a String" do
|
99
|
-
@client.authorization_uri = "https://example.com/authorize"
|
100
|
-
@client.client_id = "s6BhdRkqt3"
|
101
|
-
@client.redirect_uri = "https://example.client.com/callback"
|
102
|
-
expect(@client.authorization_uri.to_s).to include(
|
103
|
-
"https://example.com/authorize"
|
104
|
-
)
|
105
|
-
expect(@client.authorization_uri.query_values["client_id"]).to eq "s6BhdRkqt3"
|
106
|
-
expect(@client.authorization_uri.query_values["redirect_uri"]).to eq(
|
107
|
-
"https://example.client.com/callback"
|
108
|
-
)
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should allow the authorization_uri to be set to a Hash" do
|
112
|
-
@client.authorization_uri = {
|
113
|
-
scheme: "https", host: "example.com", path: "/authorize"
|
114
|
-
}
|
115
|
-
@client.client_id = "s6BhdRkqt3"
|
116
|
-
@client.redirect_uri = "https://example.client.com/callback"
|
117
|
-
expect(@client.authorization_uri.to_s).to include(
|
118
|
-
"https://example.com/authorize"
|
119
|
-
)
|
120
|
-
expect(@client.authorization_uri.query_values["client_id"]).to eq "s6BhdRkqt3"
|
121
|
-
expect(@client.authorization_uri.query_values["redirect_uri"]).to eq(
|
122
|
-
"https://example.client.com/callback"
|
123
|
-
)
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should allow the authorization_uri to be set to a URI" do
|
127
|
-
@client.authorization_uri =
|
128
|
-
Addressable::URI.parse "https://example.com/authorize"
|
129
|
-
@client.client_id = "s6BhdRkqt3"
|
130
|
-
@client.redirect_uri =
|
131
|
-
Addressable::URI.parse "https://example.client.com/callback"
|
132
|
-
expect(@client.authorization_uri.to_s).to include(
|
133
|
-
"https://example.com/authorize"
|
134
|
-
)
|
135
|
-
expect(@client.authorization_uri.query_values["client_id"]).to eq "s6BhdRkqt3"
|
136
|
-
expect(@client.authorization_uri.query_values["redirect_uri"]).to eq(
|
137
|
-
"https://example.client.com/callback"
|
138
|
-
)
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should require a redirect URI when getting the authorization_uri" do
|
142
|
-
@client.authorization_uri =
|
143
|
-
Addressable::URI.parse "https://example.com/authorize"
|
144
|
-
@client.client_id = "s6BhdRkqt3"
|
145
|
-
expect(lambda do
|
146
|
-
@client.authorization_uri
|
147
|
-
end).to raise_error(ArgumentError)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should require a client ID when getting the authorization_uri" do
|
151
|
-
@client.authorization_uri =
|
152
|
-
Addressable::URI.parse "https://example.com/authorize"
|
153
|
-
@client.redirect_uri =
|
154
|
-
Addressable::URI.parse "https://example.client.com/callback"
|
155
|
-
expect(lambda do
|
156
|
-
@client.authorization_uri
|
157
|
-
end).to raise_error(ArgumentError)
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should have no token_credential_uri" do
|
161
|
-
expect(@client.token_credential_uri).to eq nil
|
162
|
-
end
|
163
|
-
|
164
|
-
it "should allow the token_credential_uri to be set to a String" do
|
165
|
-
@client.token_credential_uri = "https://example.com/token"
|
166
|
-
expect(@client.token_credential_uri.to_s).to eq "https://example.com/token"
|
167
|
-
end
|
168
|
-
|
169
|
-
it "should allow the token_credential_uri to be set to a Hash" do
|
170
|
-
@client.token_credential_uri = {
|
171
|
-
scheme: "https", host: "example.com", path: "/token"
|
172
|
-
}
|
173
|
-
expect(@client.token_credential_uri.to_s).to eq "https://example.com/token"
|
174
|
-
end
|
175
|
-
|
176
|
-
it "should allow the token_credential_uri to be set to a URI" do
|
177
|
-
@client.token_credential_uri =
|
178
|
-
Addressable::URI.parse "https://example.com/token"
|
179
|
-
expect(@client.token_credential_uri.to_s).to eq "https://example.com/token"
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
describe Signet::OAuth2::Client, "configured for assertions profile" do
|
184
|
-
describe "when using RSA keys" do
|
185
|
-
before do
|
186
|
-
@key = OpenSSL::PKey::RSA.new 2048
|
187
|
-
@client = Signet::OAuth2::Client.new(
|
188
|
-
token_credential_uri: "https://oauth2.googleapis.com/token",
|
189
|
-
scope: "https://www.googleapis.com/auth/userinfo.profile",
|
190
|
-
issuer: "app@example.com",
|
191
|
-
audience: "https://oauth2.googleapis.com/token",
|
192
|
-
signing_key: @key
|
193
|
-
)
|
194
|
-
end
|
195
|
-
|
196
|
-
it "should generate valid JWTs" do
|
197
|
-
jwt = @client.to_jwt
|
198
|
-
expect(jwt).not_to be_nil
|
199
|
-
|
200
|
-
claim, header = JWT.decode jwt, @key.public_key, true, algorithm: "RS256"
|
201
|
-
expect(claim["iss"]).to eq "app@example.com"
|
202
|
-
expect(claim["scope"]).to eq "https://www.googleapis.com/auth/userinfo.profile"
|
203
|
-
expect(claim["aud"]).to eq "https://oauth2.googleapis.com/token"
|
204
|
-
end
|
205
|
-
|
206
|
-
it "should generate valid JWTs for impersonation" do
|
207
|
-
@client.principal = "user@example.com"
|
208
|
-
jwt = @client.to_jwt
|
209
|
-
expect(jwt).not_to be_nil
|
210
|
-
|
211
|
-
claim, header = JWT.decode jwt, @key.public_key, true, algorithm: "RS256"
|
212
|
-
expect(claim["iss"]).to eq "app@example.com"
|
213
|
-
expect(claim["prn"]).to eq "user@example.com"
|
214
|
-
expect(claim["scope"]).to eq "https://www.googleapis.com/auth/userinfo.profile"
|
215
|
-
expect(claim["aud"]).to eq "https://oauth2.googleapis.com/token"
|
216
|
-
end
|
217
|
-
|
218
|
-
it "should generate valid JWTs for impersonation using deprecated person attribute" do
|
219
|
-
@client.person = "user@example.com"
|
220
|
-
jwt = @client.to_jwt
|
221
|
-
expect(jwt).not_to be_nil
|
222
|
-
|
223
|
-
claim, header = JWT.decode jwt, @key.public_key, true, algorithm: "RS256"
|
224
|
-
expect(claim["iss"]).to eq "app@example.com"
|
225
|
-
expect(claim["prn"]).to eq "user@example.com"
|
226
|
-
expect(claim["scope"]).to eq "https://www.googleapis.com/auth/userinfo.profile"
|
227
|
-
expect(claim["aud"]).to eq "https://oauth2.googleapis.com/token"
|
228
|
-
end
|
229
|
-
|
230
|
-
it "should generate valid JWTs for impersonation using the sub attribute" do
|
231
|
-
@client.sub = "user@example.com"
|
232
|
-
jwt = @client.to_jwt
|
233
|
-
expect(jwt).not_to be_nil
|
234
|
-
|
235
|
-
claim, header = JWT.decode jwt, @key.public_key, true, algorithm: "RS256"
|
236
|
-
expect(claim["iss"]).to eq "app@example.com"
|
237
|
-
expect(claim["sub"]).to eq "user@example.com"
|
238
|
-
expect(claim["scope"]).to eq "https://www.googleapis.com/auth/userinfo.profile"
|
239
|
-
expect(claim["aud"]).to eq "https://oauth2.googleapis.com/token"
|
240
|
-
end
|
241
|
-
|
242
|
-
it "should generate a JSON representation of the client" do
|
243
|
-
@client.principal = "user@example.com"
|
244
|
-
json = @client.to_json
|
245
|
-
expect(json).not_to be_nil
|
246
|
-
|
247
|
-
deserialized = MultiJson.load json
|
248
|
-
expect(deserialized["token_credential_uri"]).to eq "https://oauth2.googleapis.com/token"
|
249
|
-
expect(deserialized["scope"]).to eq ["https://www.googleapis.com/auth/userinfo.profile"]
|
250
|
-
expect(deserialized["issuer"]).to eq "app@example.com"
|
251
|
-
expect(deserialized["audience"]).to eq "https://oauth2.googleapis.com/token"
|
252
|
-
expect(deserialized["signing_key"]).to eq @key.to_s
|
253
|
-
end
|
254
|
-
|
255
|
-
it "should send valid access token request" do
|
256
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
257
|
-
stub.post "/token" do |env|
|
258
|
-
params = Addressable::URI.form_unencode env[:body]
|
259
|
-
claim, header = JWT.decode params.assoc("assertion").last, @key.public_key, true, algorithm: "RS256"
|
260
|
-
expect(params.assoc("grant_type")).to eq ["grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"]
|
261
|
-
build_json_response(
|
262
|
-
"access_token" => "1/abcdef1234567890",
|
263
|
-
"token_type" => "Bearer",
|
264
|
-
"expires_in" => 3600
|
265
|
-
)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
269
|
-
builder.adapter :test, stubs
|
270
|
-
end
|
271
|
-
|
272
|
-
@client.fetch_access_token! connection: connection
|
273
|
-
expect(@client.access_token).to eq "1/abcdef1234567890"
|
274
|
-
stubs.verify_stubbed_calls
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
describe "when using shared secrets" do
|
279
|
-
before do
|
280
|
-
@key = "my secret key"
|
281
|
-
@client = Signet::OAuth2::Client.new(
|
282
|
-
token_credential_uri: "https://oauth2.googleapis.com/token",
|
283
|
-
scope: "https://www.googleapis.com/auth/userinfo.profile",
|
284
|
-
issuer: "app@example.com",
|
285
|
-
audience: "https://oauth2.googleapis.com/token",
|
286
|
-
signing_key: @key
|
287
|
-
)
|
288
|
-
end
|
289
|
-
|
290
|
-
it "should generate valid JWTs" do
|
291
|
-
jwt = @client.to_jwt
|
292
|
-
expect(jwt).not_to be_nil
|
293
|
-
|
294
|
-
claim, header = JWT.decode jwt, @key, true, algorithm: "HS256"
|
295
|
-
expect(claim["iss"]).to eq "app@example.com"
|
296
|
-
expect(claim["scope"]).to eq "https://www.googleapis.com/auth/userinfo.profile"
|
297
|
-
expect(claim["aud"]).to eq "https://oauth2.googleapis.com/token"
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
describe Signet::OAuth2::Client, "configured for Google userinfo API" do
|
303
|
-
before do
|
304
|
-
@client = Signet::OAuth2::Client.new(
|
305
|
-
authorization_uri: "https://accounts.google.com/o/oauth2/auth",
|
306
|
-
token_credential_uri: "https://oauth2.googleapis.com/token",
|
307
|
-
scope: "https://www.googleapis.com/auth/userinfo.profile"
|
308
|
-
)
|
309
|
-
end
|
310
|
-
|
311
|
-
it "should not have a grant type by default" do
|
312
|
-
expect(@client.grant_type).to eq nil
|
313
|
-
end
|
314
|
-
|
315
|
-
it "should use the authorization_code grant type if given code" do
|
316
|
-
@client.code = "00000"
|
317
|
-
@client.redirect_uri = "http://www.example.com/"
|
318
|
-
expect(@client.grant_type).to eq "authorization_code"
|
319
|
-
end
|
320
|
-
|
321
|
-
it "should use the refresh_token grant type if given refresh token" do
|
322
|
-
@client.refresh_token = "54321"
|
323
|
-
expect(@client.grant_type).to eq "refresh_token"
|
324
|
-
end
|
325
|
-
|
326
|
-
it "should use the password grant type if given username and password" do
|
327
|
-
@client.username = "johndoe"
|
328
|
-
@client.password = "incognito"
|
329
|
-
expect(@client.grant_type).to eq "password"
|
330
|
-
end
|
331
|
-
|
332
|
-
it "should allow the grant type to be set manually" do
|
333
|
-
@client.grant_type = "authorization_code"
|
334
|
-
expect(@client.grant_type).to eq "authorization_code"
|
335
|
-
@client.grant_type = "refresh_token"
|
336
|
-
expect(@client.grant_type).to eq "refresh_token"
|
337
|
-
@client.grant_type = "password"
|
338
|
-
expect(@client.grant_type).to eq "password"
|
339
|
-
end
|
340
|
-
|
341
|
-
it "should allow the grant type to be set to an extension" do
|
342
|
-
@client.grant_type = "urn:ietf:params:oauth:grant-type:saml2-bearer"
|
343
|
-
@client.extension_parameters["assertion"] =
|
344
|
-
"PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU"
|
345
|
-
|
346
|
-
expect(@client.grant_type).to eq Addressable::URI.parse("urn:ietf:params:oauth:grant-type:saml2-bearer")
|
347
|
-
expect(@client.extension_parameters).to eq ({ "assertion" => "PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU" })
|
348
|
-
end
|
349
|
-
|
350
|
-
it "should raise an error if extension parameters are bogus" do
|
351
|
-
expect(lambda do
|
352
|
-
@client.extension_parameters = :bogus
|
353
|
-
end).to raise_error(TypeError)
|
354
|
-
end
|
355
|
-
|
356
|
-
it "should include extension parameters in token request" do
|
357
|
-
@client.grant_type = "urn:ietf:params:oauth:grant-type:saml2-bearer"
|
358
|
-
@client.extension_parameters["assertion"] =
|
359
|
-
"PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU"
|
360
|
-
|
361
|
-
request = @client.generate_access_token_request
|
362
|
-
expect(request).to include("assertion" => "PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU")
|
363
|
-
end
|
364
|
-
|
365
|
-
it "should include the scope in token request" do
|
366
|
-
@client.scope = ["https://www.googleapis.com/auth/userinfo.profile"]
|
367
|
-
|
368
|
-
request = @client.generate_access_token_request use_configured_scope: true
|
369
|
-
expect(request).to include("scope" => ["https://www.googleapis.com/auth/userinfo.profile"])
|
370
|
-
end
|
371
|
-
|
372
|
-
it "should allow the token to be updated" do
|
373
|
-
issued_at = Time.now
|
374
|
-
@client.update_token!(
|
375
|
-
:access_token => "12345",
|
376
|
-
refresh_token: "54321",
|
377
|
-
:expires_in => 3600,
|
378
|
-
:issued_at => issued_at
|
379
|
-
)
|
380
|
-
expect(@client.access_token).to eq "12345"
|
381
|
-
expect(@client.refresh_token).to eq "54321"
|
382
|
-
expect(@client.expires_in).to eq 3600
|
383
|
-
expect(@client.issued_at).to eq issued_at
|
384
|
-
expect(@client).to_not be_expired
|
385
|
-
end
|
386
|
-
|
387
|
-
it "should handle expires as equivalent to expires_in" do
|
388
|
-
issued_at = Time.now
|
389
|
-
@client.update_token!(
|
390
|
-
:access_token => "12345",
|
391
|
-
refresh_token: "54321",
|
392
|
-
:expires => 600,
|
393
|
-
:issued_at => issued_at
|
394
|
-
)
|
395
|
-
expect(@client.expires_in).to eq 600
|
396
|
-
end
|
397
|
-
|
398
|
-
it "should allow the token to be updated without an expiration" do
|
399
|
-
@client.update_token!(
|
400
|
-
:access_token => "12345",
|
401
|
-
refresh_token: "54321"
|
402
|
-
)
|
403
|
-
expect(@client.access_token).to eq "12345"
|
404
|
-
expect(@client.refresh_token).to eq "54321"
|
405
|
-
expect(@client.expires_in).to eq nil
|
406
|
-
expect(@client.issued_at).to eq nil
|
407
|
-
expect(@client).to_not be_expired
|
408
|
-
end
|
409
|
-
|
410
|
-
it "should allow the token expiration to be cleared" do
|
411
|
-
issued_at = Time.now
|
412
|
-
@client.update_token!(
|
413
|
-
:access_token => "12345",
|
414
|
-
refresh_token: "54321",
|
415
|
-
:expires_in => 3600,
|
416
|
-
:issued_at => issued_at
|
417
|
-
)
|
418
|
-
@client.expires_in = nil
|
419
|
-
@client.issued_at = nil
|
420
|
-
expect(@client).to_not be_expired
|
421
|
-
end
|
422
|
-
|
423
|
-
it "should allow the expires_at time to be updated" do
|
424
|
-
expires_at = Time.now
|
425
|
-
@client.update_token!(
|
426
|
-
expires_at: expires_at.to_i,
|
427
|
-
expires_in: nil
|
428
|
-
)
|
429
|
-
expect(@client.expires_at).to be_within(1).of(expires_at)
|
430
|
-
expect(@client).to be_expired
|
431
|
-
end
|
432
|
-
|
433
|
-
it "should calculate the expires_at from issued_at when issued_at is set" do
|
434
|
-
expires_in = 3600
|
435
|
-
issued_at = Time.now - expires_in
|
436
|
-
@client.update_token!(
|
437
|
-
:issued_at => issued_at,
|
438
|
-
expires_in: expires_in
|
439
|
-
)
|
440
|
-
expect(@client.expires_at).to eq issued_at + expires_in
|
441
|
-
expect(@client).to be_expired
|
442
|
-
end
|
443
|
-
|
444
|
-
it "should calculate expires_at from Time.now when issed_at is NOT set" do
|
445
|
-
expires_in = 3600
|
446
|
-
expires_at = Time.now + expires_in
|
447
|
-
@client.update_token! expires_in: expires_in
|
448
|
-
expect(@client.expires_at).to be_within(1).of(expires_at)
|
449
|
-
expect(@client).to_not be_expired
|
450
|
-
end
|
451
|
-
|
452
|
-
# This test is to document the way that expires_in has always been used:
|
453
|
-
# If expires_in is set on the client, it always resets the issued_at time
|
454
|
-
# to Time.now
|
455
|
-
it "sets issued_at to Time.now when expires_in is not set through update_token!" do
|
456
|
-
one_hour = 3600
|
457
|
-
issued_at = Time.now - (2 * one_hour)
|
458
|
-
current_time = Time.now
|
459
|
-
|
460
|
-
@client.issued_at = issued_at
|
461
|
-
@client.expires_in = one_hour
|
462
|
-
|
463
|
-
expect(@client.issued_at).to_not eq issued_at
|
464
|
-
expect(@client.issued_at).to be_within(1).of(current_time)
|
465
|
-
expect(@client).to_not be_expired
|
466
|
-
end
|
467
|
-
|
468
|
-
it "should allow setting expires_at manually" do
|
469
|
-
expires_at = Time.now + 100
|
470
|
-
@client.expires_at = expires_at.to_i
|
471
|
-
expect(@client.expires_at).to be_within(1).of(expires_at)
|
472
|
-
expect(@client).to_not be_expired
|
473
|
-
end
|
474
|
-
|
475
|
-
it "should normalize values of expires_at to instances of time" do
|
476
|
-
time_formats = [DateTime.new, "12:00", 100, Time.new]
|
477
|
-
normalized_time_formats = []
|
478
|
-
time_formats.each do |time|
|
479
|
-
@client.expires_at = time
|
480
|
-
normalized_time_formats << @client.expires_at
|
481
|
-
end
|
482
|
-
normalized_time_formats.each do |time|
|
483
|
-
expect(time).to be_an_instance_of(Time)
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
it "should set expires_in when expires_at is set" do
|
488
|
-
issued_at = Time.now
|
489
|
-
expires_at = Time.now + 100
|
490
|
-
@client.expires_at = expires_at.to_i
|
491
|
-
@client.issued_at = issued_at
|
492
|
-
expect(@client.expires_in).to be_within(1).of (expires_at - issued_at).to_i
|
493
|
-
@client.expires_at = nil
|
494
|
-
expect(@client.expires_in).to be_nil
|
495
|
-
end
|
496
|
-
|
497
|
-
it "should set expires_in to nil when expires_at is set to nil" do
|
498
|
-
@client.expires_at = nil
|
499
|
-
expect(@client.expires_in).to be_nil
|
500
|
-
end
|
501
|
-
|
502
|
-
it "should set expires_at when expires_in is set" do
|
503
|
-
expires_in = 100
|
504
|
-
@client.expires_in = expires_in
|
505
|
-
expect(@client.expires_at).to eq (@client.issued_at + expires_in)
|
506
|
-
@client.expires_in = nil
|
507
|
-
expect(@client.expires_at).to be_nil
|
508
|
-
end
|
509
|
-
|
510
|
-
it "should set expires_at to nil when expires_in is set to nil" do
|
511
|
-
@client.expires_in = nil
|
512
|
-
expect(@client.expires_at).to be_nil
|
513
|
-
end
|
514
|
-
|
515
|
-
it "should indicate the token is not expired if expired_at nil" do
|
516
|
-
@client.expires_at = nil
|
517
|
-
expect(@client.expires_within?(60)).to be false
|
518
|
-
expect(@client.expired?).to be false
|
519
|
-
end
|
520
|
-
|
521
|
-
it "should indicate the token is not expiring when expiry beyond window" do
|
522
|
-
@client.expires_at = Time.now + 100
|
523
|
-
expect(@client.expires_within?(60)).to be false
|
524
|
-
end
|
525
|
-
|
526
|
-
it "should indicate the token is expiring soon when expiry within window" do
|
527
|
-
@client.expires_at = Time.now + 30
|
528
|
-
expect(@client.expires_within?(60)).to be true
|
529
|
-
end
|
530
|
-
|
531
|
-
it "should raise an error if the authorization endpoint is not secure" do
|
532
|
-
@client.client_id = "client-12345"
|
533
|
-
@client.client_secret = "secret-12345"
|
534
|
-
@client.redirect_uri = "http://www.example.com/"
|
535
|
-
@client.authorization_uri = "http://accounts.google.com/o/oauth2/auth"
|
536
|
-
expect(lambda do
|
537
|
-
@client.authorization_uri
|
538
|
-
end).to raise_error(Signet::UnsafeOperationError)
|
539
|
-
end
|
540
|
-
|
541
|
-
it "should raise an error if token credential URI is missing" do
|
542
|
-
@client.token_credential_uri = nil
|
543
|
-
expect(lambda do
|
544
|
-
@client.fetch_access_token!
|
545
|
-
end).to raise_error(ArgumentError)
|
546
|
-
end
|
547
|
-
|
548
|
-
it "should raise an error if unauthorized" do
|
549
|
-
@client.client_id = "client-12345"
|
550
|
-
@client.client_secret = "secret-12345"
|
551
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
552
|
-
stub.post "/token" do
|
553
|
-
[401, {}, "User authorization failed or something."]
|
554
|
-
end
|
555
|
-
end
|
556
|
-
expect(lambda do
|
557
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
558
|
-
builder.adapter :test, stubs
|
559
|
-
end
|
560
|
-
@client.fetch_access_token!(
|
561
|
-
connection: connection
|
562
|
-
)
|
563
|
-
end).to raise_error(Signet::AuthorizationError)
|
564
|
-
stubs.verify_stubbed_calls
|
565
|
-
end
|
566
|
-
|
567
|
-
it "should raise a remote server error if the server gives a 5xx status" do
|
568
|
-
@client.client_id = "client-12345"
|
569
|
-
@client.client_secret = "secret-12345"
|
570
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
571
|
-
stub.post "/token" do
|
572
|
-
[509, {}, "Rate limit hit or something."]
|
573
|
-
end
|
574
|
-
end
|
575
|
-
expect(lambda do
|
576
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
577
|
-
builder.adapter :test, stubs
|
578
|
-
end
|
579
|
-
@client.fetch_access_token!(
|
580
|
-
connection: connection
|
581
|
-
)
|
582
|
-
end).to raise_error(Signet::RemoteServerError)
|
583
|
-
stubs.verify_stubbed_calls
|
584
|
-
end
|
585
|
-
|
586
|
-
it "should raise an unexpected error if the token server gives an unexpected status" do
|
587
|
-
@client.client_id = "client-12345"
|
588
|
-
@client.client_secret = "secret-12345"
|
589
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
590
|
-
stub.post "/token" do
|
591
|
-
[309, {}, "Rate limit hit or something."]
|
592
|
-
end
|
593
|
-
end
|
594
|
-
expect(lambda do
|
595
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
596
|
-
builder.adapter :test, stubs
|
597
|
-
end
|
598
|
-
@client.fetch_access_token!(
|
599
|
-
connection: connection
|
600
|
-
)
|
601
|
-
end).to raise_error(Signet::UnexpectedStatusError)
|
602
|
-
stubs.verify_stubbed_calls
|
603
|
-
end
|
604
|
-
|
605
|
-
it "should correctly fetch an access token" do
|
606
|
-
@client.client_id = "client-12345"
|
607
|
-
@client.client_secret = "secret-12345"
|
608
|
-
@client.code = "00000"
|
609
|
-
@client.redirect_uri = "https://www.example.com/"
|
610
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
611
|
-
stub.post "/token" do
|
612
|
-
build_json_response(
|
613
|
-
"access_token" => "12345",
|
614
|
-
"refresh_token" => "54321",
|
615
|
-
"expires_in" => "3600"
|
616
|
-
)
|
617
|
-
end
|
618
|
-
end
|
619
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
620
|
-
builder.adapter :test, stubs
|
621
|
-
end
|
622
|
-
@client.fetch_access_token!(
|
623
|
-
connection: connection
|
624
|
-
)
|
625
|
-
expect(@client.access_token).to eq "12345"
|
626
|
-
expect(@client.refresh_token).to eq "54321"
|
627
|
-
expect(@client.expires_in).to eq 3600
|
628
|
-
stubs.verify_stubbed_calls
|
629
|
-
end
|
630
|
-
|
631
|
-
it "should correctly fetch an access token with a password" do
|
632
|
-
@client.client_id = "client-12345"
|
633
|
-
@client.client_secret = "secret-12345"
|
634
|
-
@client.username = "johndoe"
|
635
|
-
@client.password = "incognito"
|
636
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
637
|
-
stub.post "/token" do
|
638
|
-
build_json_response(
|
639
|
-
"access_token" => "12345",
|
640
|
-
"refresh_token" => "54321",
|
641
|
-
"expires_in" => "3600"
|
642
|
-
)
|
643
|
-
end
|
644
|
-
end
|
645
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
646
|
-
builder.adapter :test, stubs
|
647
|
-
end
|
648
|
-
@client.fetch_access_token!(
|
649
|
-
connection: connection
|
650
|
-
)
|
651
|
-
expect(@client.access_token).to eq "12345"
|
652
|
-
expect(@client.refresh_token).to eq "54321"
|
653
|
-
expect(@client.expires_in).to eq 3600
|
654
|
-
stubs.verify_stubbed_calls
|
655
|
-
end
|
656
|
-
|
657
|
-
it "should correctly refresh an access token" do
|
658
|
-
@client.client_id = "client-12345"
|
659
|
-
@client.client_secret = "secret-12345"
|
660
|
-
@client.refresh_token = "54321"
|
661
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
662
|
-
stub.post "/token" do
|
663
|
-
build_json_response(
|
664
|
-
"access_token" => "12345",
|
665
|
-
"refresh_token" => "54321",
|
666
|
-
"expires_in" => "3600"
|
667
|
-
)
|
668
|
-
end
|
669
|
-
end
|
670
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
671
|
-
builder.adapter :test, stubs
|
672
|
-
end
|
673
|
-
@client.fetch_access_token!(
|
674
|
-
connection: connection
|
675
|
-
)
|
676
|
-
expect(@client.access_token).to eq "12345"
|
677
|
-
expect(@client.refresh_token).to eq "54321"
|
678
|
-
expect(@client.expires_in).to eq 3600
|
679
|
-
stubs.verify_stubbed_calls
|
680
|
-
end
|
681
|
-
|
682
|
-
it "should detect unintential grant type of none" do
|
683
|
-
@client.client_id = "client-12345"
|
684
|
-
@client.client_secret = "secret-12345"
|
685
|
-
@client.redirect_uri = "https://www.example.com/"
|
686
|
-
expect(lambda do
|
687
|
-
@client.fetch_access_token!
|
688
|
-
end).to raise_error(ArgumentError)
|
689
|
-
end
|
690
|
-
|
691
|
-
it "should correctly fetch protected resources" do
|
692
|
-
@client.client_id = "client-12345"
|
693
|
-
@client.client_secret = "secret-12345"
|
694
|
-
@client.access_token = "12345"
|
695
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
696
|
-
stub.get "/oauth2/v1/userinfo?alt=json" do
|
697
|
-
[200, {}, <<~JSON]
|
698
|
-
{
|
699
|
-
"id": "116452824309856782163",
|
700
|
-
"name": "Bob Aman",
|
701
|
-
"given_name": "Bob",
|
702
|
-
"family_name": "Aman",
|
703
|
-
"link": "https://plus.google.com/116452824309856782163"
|
704
|
-
}
|
705
|
-
JSON
|
706
|
-
end
|
707
|
-
end
|
708
|
-
connection = Faraday.new url: "https://www.googleapis.com" do |builder|
|
709
|
-
builder.adapter :test, stubs
|
710
|
-
end
|
711
|
-
response = @client.fetch_protected_resource(
|
712
|
-
connection: connection,
|
713
|
-
uri: "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"
|
714
|
-
)
|
715
|
-
expect(response.status).to eq 200
|
716
|
-
expect(response.body).to eq <<~JSON
|
717
|
-
{
|
718
|
-
"id": "116452824309856782163",
|
719
|
-
"name": "Bob Aman",
|
720
|
-
"given_name": "Bob",
|
721
|
-
"family_name": "Aman",
|
722
|
-
"link": "https://plus.google.com/116452824309856782163"
|
723
|
-
}
|
724
|
-
JSON
|
725
|
-
stubs.verify_stubbed_calls
|
726
|
-
end
|
727
|
-
|
728
|
-
it "should correctly send the realm in the Authorization header" do
|
729
|
-
@client.client_id = "client-12345"
|
730
|
-
@client.client_secret = "secret-12345"
|
731
|
-
@client.access_token = "12345"
|
732
|
-
connection = Faraday.new url: "https://www.googleapis.com" do |builder|
|
733
|
-
builder.adapter :test
|
734
|
-
end
|
735
|
-
request = @client.generate_authenticated_request(
|
736
|
-
connection: connection,
|
737
|
-
realm: "Example",
|
738
|
-
request: conn.build_request(:get) do |req|
|
739
|
-
req.url "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"
|
740
|
-
end
|
741
|
-
)
|
742
|
-
expect(request.headers["Authorization"]).to eq 'Bearer 12345, realm="Example"'
|
743
|
-
end
|
744
|
-
|
745
|
-
it "should correctly send the realm in the Authorization header" do
|
746
|
-
@client.client_id = "client-12345"
|
747
|
-
@client.client_secret = "secret-12345"
|
748
|
-
@client.access_token = "12345"
|
749
|
-
connection = Faraday.new url: "https://www.googleapis.com" do |builder|
|
750
|
-
builder.adapter :test
|
751
|
-
end
|
752
|
-
request = @client.generate_authenticated_request(
|
753
|
-
connection: connection,
|
754
|
-
realm: "Example",
|
755
|
-
request: [
|
756
|
-
"GET",
|
757
|
-
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
|
758
|
-
{},
|
759
|
-
[""]
|
760
|
-
]
|
761
|
-
)
|
762
|
-
expect(request.headers["Authorization"]).to eq 'Bearer 12345, realm="Example"'
|
763
|
-
end
|
764
|
-
|
765
|
-
it "should not raise an error if a request is " \
|
766
|
-
"provided without a connection" do
|
767
|
-
@client.client_id = "client-12345"
|
768
|
-
@client.client_secret = "secret-12345"
|
769
|
-
@client.access_token = "12345"
|
770
|
-
request = @client.generate_authenticated_request(
|
771
|
-
realm: "Example",
|
772
|
-
request: conn.build_request(:get) do |req|
|
773
|
-
req.url "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"
|
774
|
-
end
|
775
|
-
)
|
776
|
-
end
|
777
|
-
|
778
|
-
it "should raise an error if not enough information " \
|
779
|
-
"is supplied to create a request" do
|
780
|
-
@client.client_id = "client-12345"
|
781
|
-
@client.client_secret = "secret-12345"
|
782
|
-
@client.access_token = "12345"
|
783
|
-
expect(lambda do
|
784
|
-
@client.generate_authenticated_request(
|
785
|
-
realm: "Example",
|
786
|
-
method: "POST"
|
787
|
-
)
|
788
|
-
end).to raise_error(ArgumentError)
|
789
|
-
end
|
790
|
-
|
791
|
-
it "should raise an error if the client does not have an access token" do
|
792
|
-
@client.client_id = "client-12345"
|
793
|
-
@client.client_secret = "secret-12345"
|
794
|
-
expect(lambda do
|
795
|
-
@client.fetch_protected_resource
|
796
|
-
end).to raise_error(ArgumentError)
|
797
|
-
end
|
798
|
-
|
799
|
-
it "should not raise an error if the API server gives an error status" do
|
800
|
-
@client.client_id = "client-12345"
|
801
|
-
@client.client_secret = "secret-12345"
|
802
|
-
@client.access_token = "12345"
|
803
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
804
|
-
stub.get "/oauth2/v1/userinfo?alt=json" do
|
805
|
-
[509, {}, "Rate limit hit or something."]
|
806
|
-
end
|
807
|
-
end
|
808
|
-
connection = Faraday.new url: "https://www.googleapis.com" do |builder|
|
809
|
-
builder.adapter :test, stubs
|
810
|
-
end
|
811
|
-
response = @client.fetch_protected_resource(
|
812
|
-
connection: connection,
|
813
|
-
uri: "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"
|
814
|
-
)
|
815
|
-
expect(response.status).to eq 509
|
816
|
-
expect(response.body).to eq "Rate limit hit or something."
|
817
|
-
stubs.verify_stubbed_calls
|
818
|
-
end
|
819
|
-
|
820
|
-
it "should only raise an error if the API server " \
|
821
|
-
"gives an authorization failed status" do
|
822
|
-
@client.client_id = "client-12345"
|
823
|
-
@client.client_secret = "secret-12345"
|
824
|
-
@client.access_token = "12345"
|
825
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
826
|
-
stub.get "/oauth2/v1/userinfo?alt=json" do
|
827
|
-
[401, {}, "User authorization failed or something."]
|
828
|
-
end
|
829
|
-
end
|
830
|
-
expect(lambda do
|
831
|
-
connection = Faraday.new(
|
832
|
-
url: "https://www.googleapis.com"
|
833
|
-
) do |builder|
|
834
|
-
builder.adapter :test, stubs
|
835
|
-
end
|
836
|
-
@client.fetch_protected_resource(
|
837
|
-
connection: connection,
|
838
|
-
uri: "https://www.googleapis.com/oauth2/v1/userinfo?alt=json"
|
839
|
-
)
|
840
|
-
end).to raise_error(Signet::AuthorizationError)
|
841
|
-
stubs.verify_stubbed_calls
|
842
|
-
end
|
843
|
-
|
844
|
-
it "should correctly handle an ID token" do
|
845
|
-
@client.client_id = "client-12345"
|
846
|
-
@client.client_secret = "secret-12345"
|
847
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
848
|
-
stub.post "/token" do
|
849
|
-
build_json_response(
|
850
|
-
"access_token" => "12345",
|
851
|
-
"refresh_token" => "54321",
|
852
|
-
"expires_in" => "3600",
|
853
|
-
"id_token" => (
|
854
|
-
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl9oYXNoIjoidGdoRD" \
|
855
|
-
"lKN244VjBOMnZjdzZlTWlqZyIsImF1ZCI6ImNsaWVudC0xMjM0NSIsImlkIjoiM" \
|
856
|
-
"TIzNDUiLCJpYXQiOjEzMjA2NzA5NzgsImV4cCI6MTMyMDY3NDg3OCwiY2lkIjoi" \
|
857
|
-
"Y2xpZW50LTEyMzQ1IiwiaXNzIjoiZXhhbXBsZS5jb20ifQ.tsF3srlBaAh6pV3U" \
|
858
|
-
"wfRrHSA3-jwnvOw6MMsQ6sO4kjc"
|
859
|
-
)
|
860
|
-
)
|
861
|
-
end
|
862
|
-
end
|
863
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
864
|
-
builder.adapter :test, stubs
|
865
|
-
end
|
866
|
-
@client.fetch_access_token!(
|
867
|
-
connection: connection
|
868
|
-
)
|
869
|
-
expect(@client.access_token).to eq "12345"
|
870
|
-
expect(@client.refresh_token).to eq "54321"
|
871
|
-
expect(@client.decoded_id_token(nil, verify_expiration: false)).to eq ({
|
872
|
-
"token_hash" => "tghD9J7n8V0N2vcw6eMijg",
|
873
|
-
"id" => "12345",
|
874
|
-
"aud" => "client-12345",
|
875
|
-
"iat" => 1_320_670_978,
|
876
|
-
"exp" => 1_320_674_878,
|
877
|
-
"cid" => "client-12345",
|
878
|
-
"iss" => "example.com"
|
879
|
-
})
|
880
|
-
expect(@client.expires_in).to eq 3600
|
881
|
-
stubs.verify_stubbed_calls
|
882
|
-
end
|
883
|
-
|
884
|
-
it "should correctly handle an ID token with `aud` array" do
|
885
|
-
@client.client_id = "client-12345"
|
886
|
-
@client.client_secret = "secret-12345"
|
887
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
888
|
-
stub.post "/token" do
|
889
|
-
build_json_response(
|
890
|
-
"access_token" => "12345",
|
891
|
-
"refresh_token" => "54321",
|
892
|
-
"expires_in" => "3600",
|
893
|
-
"id_token" => (
|
894
|
-
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl9oYXNoIjoidGdoRD" \
|
895
|
-
"lKN244VjBOMnZjdzZlTWlqZyIsImF1ZCI6WyJjbGllbnQtMTIzNDUiXSwiaWQiO" \
|
896
|
-
"iIxMjM0NSIsImlhdCI6MTMyMDY3MDk3OCwiZXhwIjoxMzIwNjc0ODc4LCJjaWQi" \
|
897
|
-
"OiJjbGllbnQtMTIzNDUiLCJpc3MiOiJleGFtcGxlLmNvbSJ9.rSaY-M9YlB4pcU" \
|
898
|
-
"uNf21FeEtOM9pBGr_a7xe9fZrpWWU"
|
899
|
-
)
|
900
|
-
)
|
901
|
-
end
|
902
|
-
end
|
903
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
904
|
-
builder.adapter :test, stubs
|
905
|
-
end
|
906
|
-
@client.fetch_access_token!(
|
907
|
-
connection: connection
|
908
|
-
)
|
909
|
-
expect(@client.access_token).to eq "12345"
|
910
|
-
expect(@client.refresh_token).to eq "54321"
|
911
|
-
expect(@client.decoded_id_token(nil, verify_expiration: false)).to eq ({
|
912
|
-
"token_hash" => "tghD9J7n8V0N2vcw6eMijg",
|
913
|
-
"id" => "12345",
|
914
|
-
"aud" => ["client-12345"],
|
915
|
-
"iat" => 1_320_670_978,
|
916
|
-
"exp" => 1_320_674_878,
|
917
|
-
"cid" => "client-12345",
|
918
|
-
"iss" => "example.com"
|
919
|
-
})
|
920
|
-
expect(@client.expires_in).to eq 3600
|
921
|
-
stubs.verify_stubbed_calls
|
922
|
-
end
|
923
|
-
|
924
|
-
it "should raise an error decoding an ID token if " \
|
925
|
-
"audience does not match client ID" do
|
926
|
-
@client.client_id = "client-54321"
|
927
|
-
@client.client_secret = "secret-12345"
|
928
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
929
|
-
stub.post "/token" do
|
930
|
-
build_json_response(
|
931
|
-
"access_token" => "12345",
|
932
|
-
"refresh_token" => "54321",
|
933
|
-
"expires_in" => "3600",
|
934
|
-
"id_token" => (
|
935
|
-
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl9oYXNoIjoidGdoRD" \
|
936
|
-
"lKN244VjBOMnZjdzZlTWlqZyIsImF1ZCI6ImNsaWVudC0xMjM0NSIsImlkIjoiM" \
|
937
|
-
"TIzNDUiLCJpYXQiOjEzMjA2NzA5NzgsImV4cCI6MTMyMDY3NDg3OCwiY2lkIjoi" \
|
938
|
-
"Y2xpZW50LTEyMzQ1IiwiaXNzIjoiZXhhbXBsZS5jb20ifQ.tsF3srlBaAh6pV3U" \
|
939
|
-
"wfRrHSA3-jwnvOw6MMsQ6sO4kjc"
|
940
|
-
)
|
941
|
-
)
|
942
|
-
end
|
943
|
-
end
|
944
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
945
|
-
builder.adapter :test, stubs
|
946
|
-
end
|
947
|
-
@client.fetch_access_token!(
|
948
|
-
connection: connection
|
949
|
-
)
|
950
|
-
expect(@client.access_token).to eq "12345"
|
951
|
-
expect(@client.refresh_token).to eq "54321"
|
952
|
-
expect(@client.expires_in).to eq 3600
|
953
|
-
expect(lambda do
|
954
|
-
@client.decoded_id_token nil, verify_expiration: false
|
955
|
-
end).to raise_error(Signet::UnsafeOperationError)
|
956
|
-
stubs.verify_stubbed_calls
|
957
|
-
end
|
958
|
-
|
959
|
-
it "should raise an error decoding an ID token if " \
|
960
|
-
"audience is missing" do
|
961
|
-
@client.client_id = "client-12345"
|
962
|
-
@client.client_secret = "secret-12345"
|
963
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
964
|
-
stub.post "/token" do
|
965
|
-
build_json_response(
|
966
|
-
"access_token" => "12345",
|
967
|
-
"refresh_token" => "54321",
|
968
|
-
"expires_in" => "3600",
|
969
|
-
"id_token" => (
|
970
|
-
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl9oYXNoIjoidGdoRD" \
|
971
|
-
"lKN244VjBOMnZjdzZlTWlqZyIsImlkIjoiMTIzNDUiLCJpYXQiOjEzMjA2NzA5N" \
|
972
|
-
"zgsImV4cCI6MTMyMDY3NDg3OCwiY2lkIjoiY2xpZW50LTEyMzQ1IiwiaXNzIjoi" \
|
973
|
-
"ZXhhbXBsZS5jb20ifQ.7qj85CKbQyVdDe5y2ScdJAZNkEeKMPW9LIonLxG1vu8"
|
974
|
-
)
|
975
|
-
)
|
976
|
-
end
|
977
|
-
end
|
978
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
979
|
-
builder.adapter :test, stubs
|
980
|
-
end
|
981
|
-
@client.fetch_access_token!(
|
982
|
-
connection: connection
|
983
|
-
)
|
984
|
-
expect(@client.access_token).to eq "12345"
|
985
|
-
expect(@client.refresh_token).to eq "54321"
|
986
|
-
expect(@client.expires_in).to eq 3600
|
987
|
-
expect(lambda do
|
988
|
-
@client.decoded_id_token nil, verify_expiration: false
|
989
|
-
end).to raise_error(Signet::UnsafeOperationError)
|
990
|
-
stubs.verify_stubbed_calls
|
991
|
-
end
|
992
|
-
|
993
|
-
it "should raise an error if the id token cannot be verified" do
|
994
|
-
pending "Need to set test data"
|
995
|
-
@client.client_id = "client-12345"
|
996
|
-
@client.client_secret = "secret-12345"
|
997
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
998
|
-
stub.post "/token" do
|
999
|
-
build_json_response(
|
1000
|
-
"access_token" => "12345",
|
1001
|
-
"refresh_token" => "54321",
|
1002
|
-
"expires_in" => "3600",
|
1003
|
-
"id_token" => (
|
1004
|
-
"eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiY" \
|
1005
|
-
"XVkIjoiMTA2MDM1Nzg5MTY4OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSI" \
|
1006
|
-
"sImNpZCI6IjEwNjAzNTc4OTE2ODguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb" \
|
1007
|
-
"20iLCJpZCI6IjExNjQ1MjgyNDMwOTg1Njc4MjE2MyIsInRva2VuX2hhc2giOiJ" \
|
1008
|
-
"0Z2hEOUo4bjhWME4ydmN3NmVNaWpnIiwiaWF0IjoxMzIwNjcwOTc4LCJleHAiO" \
|
1009
|
-
"jEzMjA2NzQ4Nzh9.D8x_wirkxDElqKdJBcsIws3Ogesk38okz6MN7zqC7nEAA7" \
|
1010
|
-
"wcy1PxsROY1fmBvXSer0IQesAqOW-rPOCNReSn-eY8d53ph1x2HAF-AzEi3GOl" \
|
1011
|
-
"6hFycH8wj7Su6JqqyEbIVLxE7q7DkAZGaMPkxbTHs1EhSd5_oaKQ6O4xO3ZnnT4"
|
1012
|
-
)
|
1013
|
-
)
|
1014
|
-
end
|
1015
|
-
end
|
1016
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
1017
|
-
builder.adapter :test, stubs
|
1018
|
-
end
|
1019
|
-
@client.fetch_access_token!(
|
1020
|
-
connection: connection
|
1021
|
-
)
|
1022
|
-
expect(@client.access_token).to eq "12345"
|
1023
|
-
expect(@client.refresh_token).to eq "54321"
|
1024
|
-
expect(@client.expires_in).to eq 3600
|
1025
|
-
expect(lambda do
|
1026
|
-
pubkey = OpenSSL::PKey::RSA.new <<~PUBKEY
|
1027
|
-
-----BEGIN PUBLIC KEY-----
|
1028
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCaY7425h964bjaoLeUm
|
1029
|
-
SlZ8sK7VtVk9zHbGmZh2ygGYwfuUf2bmMye2Ofv99yDE/rd4loVIAcu7RVvDRgHq
|
1030
|
-
3/CZTnIrSvHsiJQsHBNa3d+F1ihPfzURzf1M5k7CFReBj2SBXhDXd57oRfBQj12w
|
1031
|
-
CVhhwP6kGTAWuoppbIIIBfNF2lE/Nvm7lVVYQqL9xOrP/AQ4xRbpQlB8Ll9sO9Or
|
1032
|
-
SvbWhCDa/LMOWxHdmrcJi6XoSg1vnOyCoKbyAoauTt/XqdkHbkDdQ6HFbJieu9il
|
1033
|
-
LDZZNliPhfENuKeC2MCGVXTEu8Cqhy1w6e4axavLlXoYf4laJIZ/e7au8SqDbY0B
|
1034
|
-
xwIDAQAB
|
1035
|
-
-----END PUBLIC KEY-----
|
1036
|
-
PUBKEY
|
1037
|
-
@client.decoded_id_token pubkey
|
1038
|
-
end).to raise_error(JWT::ExpiredSignature)
|
1039
|
-
stubs.verify_stubbed_calls
|
1040
|
-
end
|
1041
|
-
end
|
1042
|
-
|
1043
|
-
describe Signet::OAuth2::Client, "authorization_uri" do
|
1044
|
-
before do
|
1045
|
-
@client = Signet::OAuth2::Client.new(
|
1046
|
-
client_id: "s6BhdRkqt3",
|
1047
|
-
redirect_uri: "https://example.client.com/callback",
|
1048
|
-
authorization_uri: "https://example.com/authorize"
|
1049
|
-
)
|
1050
|
-
end
|
1051
|
-
|
1052
|
-
it "should set access_type to offline by default" do
|
1053
|
-
expect(@client.authorization_uri.query_values["access_type"]).to eq "offline"
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
it "should set response_type to code by default" do
|
1057
|
-
expect(@client.authorization_uri.query_values["response_type"]).to eq "code"
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
it "should raise an error when setting both prompt and approval_prompt" do
|
1061
|
-
expect(lambda do
|
1062
|
-
@client.authorization_uri approval_prompt: "force", prompt: "consent"
|
1063
|
-
end).to raise_error(ArgumentError)
|
1064
|
-
end
|
1065
|
-
end
|
1066
|
-
|
1067
|
-
describe Signet::OAuth2::Client, "configured with custom parameters" do
|
1068
|
-
before do
|
1069
|
-
@client = Signet::OAuth2::Client.new(
|
1070
|
-
client_id: "s6BhdRkqt3",
|
1071
|
-
redirect_uri: "https://example.client.com/callback",
|
1072
|
-
authorization_uri: "https://example.com/authorize",
|
1073
|
-
token_credential_uri: "https://example.com/token",
|
1074
|
-
additional_parameters: { "type" => "web_server" }
|
1075
|
-
)
|
1076
|
-
end
|
1077
|
-
|
1078
|
-
# Normalizing to symbols - good test case example here for changes to normalized input.
|
1079
|
-
# Also tests Addressable's output.
|
1080
|
-
# Note: The only changes made here are to testing the **INTERNAL** representation of options.
|
1081
|
-
it "should allow custom parameters to be set on init" do
|
1082
|
-
expect(@client.additional_parameters).to eq({ type: "web_server" })
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
it "should allow custom parameters to be updated" do
|
1086
|
-
@client.update! additional_parameters: { type: "new_type" }
|
1087
|
-
expect(@client.additional_parameters).to eq ({ type: "new_type" })
|
1088
|
-
end
|
1089
|
-
|
1090
|
-
it "should use custom parameters when generating authorization_uri" do
|
1091
|
-
expect(@client.authorization_uri.query_values).to eq ({
|
1092
|
-
"access_type" => "offline",
|
1093
|
-
"client_id" => "s6BhdRkqt3",
|
1094
|
-
"redirect_uri" => "https://example.client.com/callback",
|
1095
|
-
"response_type" => "code",
|
1096
|
-
"type" => "web_server"
|
1097
|
-
})
|
1098
|
-
end
|
1099
|
-
|
1100
|
-
it "should merge new authorization_uri custom parameters" do
|
1101
|
-
expect(@client.authorization_uri(additional_parameters: { "type" => "new_type", "new_param" => "new_val" }).query_values).to eql({ "access_type" => "offline", "client_id" => "s6BhdRkqt3", "new_param" => "new_val", "response_type" => "code", "redirect_uri" => "https://example.client.com/callback", "type" => "new_type" })
|
1102
|
-
end
|
1103
|
-
|
1104
|
-
it "should merge new generate_access_token_request custom parameters" do
|
1105
|
-
@client.update! code: "12345"
|
1106
|
-
params = @client.generate_access_token_request additional_parameters: { "type" => "new_type", "new_param" => "new_val" }
|
1107
|
-
expect(params).to include("type" => "new_type")
|
1108
|
-
expect(params).to include("new_param" => "new_val")
|
1109
|
-
end
|
1110
|
-
end
|
1111
|
-
|
1112
|
-
describe Signet::OAuth2::Client, "configured with custom parameters" do
|
1113
|
-
before do
|
1114
|
-
@client = Signet::OAuth2::Client.new(
|
1115
|
-
"client_id" => "s6BhdRkqt3",
|
1116
|
-
"redirect_uri" => "https://example.client.com/callback",
|
1117
|
-
"authorization_uri" => "https://example.com/authorize",
|
1118
|
-
"token_credential_uri" => "https://example.com/token",
|
1119
|
-
"additional_parameters" => { "type" => "web_server" }
|
1120
|
-
)
|
1121
|
-
end
|
1122
|
-
|
1123
|
-
# Normalizing to symbols - good test case example here for changes to normalized input.
|
1124
|
-
# Also tests Addressable's output.
|
1125
|
-
# Note: The only changes made here are to testing the **INTERNAL** representation of options.
|
1126
|
-
it "should allow custom parameters to be set on init" do
|
1127
|
-
expect(@client.additional_parameters).to eq ({ type: "web_server" })
|
1128
|
-
end
|
1129
|
-
|
1130
|
-
it "should allow custom parameters to be updated" do
|
1131
|
-
@client.update! additional_parameters: { "type" => "new_type" }
|
1132
|
-
expect(@client.additional_parameters).to eql ({ type: "new_type" })
|
1133
|
-
end
|
1134
|
-
|
1135
|
-
it "should use custom parameters when generating authorization_uri" do
|
1136
|
-
expect(@client.authorization_uri.query_values).to eq ({ "access_type" => "offline", "client_id" => "s6BhdRkqt3", "redirect_uri" => "https://example.client.com/callback", "response_type" => "code", "type" => "web_server" })
|
1137
|
-
end
|
1138
|
-
|
1139
|
-
it "should have the correct authorization_uri" do
|
1140
|
-
expect(@client.authorization_uri.host).to eq "example.com"
|
1141
|
-
expect(@client.authorization_uri.path).to eq "/authorize"
|
1142
|
-
end
|
1143
|
-
|
1144
|
-
it "should merge new authorization_uri custom parameters" do
|
1145
|
-
expect(@client.authorization_uri(additional_parameters: { "type" => "new_type", "new_param" => "new_val" }).query_values).to eq ({ "access_type" => "offline", "client_id" => "s6BhdRkqt3", "new_param" => "new_val", "response_type" => "code", "redirect_uri" => "https://example.client.com/callback", "type" => "new_type" })
|
1146
|
-
end
|
1147
|
-
|
1148
|
-
it "should not have access_type parameter in authorization_uri when we set it to nil in client" do
|
1149
|
-
@client.update! access_type: nil
|
1150
|
-
expect(@client.authorization_uri.query_values).to eq ({ "client_id" => "s6BhdRkqt3", "response_type" => "code", "redirect_uri" => "https://example.client.com/callback" })
|
1151
|
-
end
|
1152
|
-
|
1153
|
-
it "should use new access_type parameter as default for authorization_uri" do
|
1154
|
-
@client.update! access_type: :online
|
1155
|
-
expect(@client.authorization_uri.query_values).to eq ({ "access_type" => "online", "client_id" => "s6BhdRkqt3", "response_type" => "code", "redirect_uri" => "https://example.client.com/callback" })
|
1156
|
-
end
|
1157
|
-
|
1158
|
-
it "should merge new generate_access_token_request custom parameters" do
|
1159
|
-
@client.update! code: "12345"
|
1160
|
-
params = @client.generate_access_token_request additional_parameters: { "type" => "new_type", "new_param" => "new_val" }
|
1161
|
-
expect(params).to include("type" => "new_type")
|
1162
|
-
expect(params).to include("new_param" => "new_val")
|
1163
|
-
end
|
1164
|
-
end
|
1165
|
-
|
1166
|
-
describe Signet::OAuth2::Client, "configured with custom parameters a la JSON.load(credentials_file)" do
|
1167
|
-
before do
|
1168
|
-
@client = Signet::OAuth2::Client.new(
|
1169
|
-
"client_id" => "s6BhdRkqt3",
|
1170
|
-
"redirect_uri" => "https://example.client.com/callback",
|
1171
|
-
"authorization_uri" => { "scheme" => "https", "user" => nil, "password" => nil, "host" => "accounts.google.com", "port" => nil, "path" => "/o/oauth2/auth", "query" => nil, "fragment" => nil },
|
1172
|
-
"token_credential_uri" => "https://example.com/token",
|
1173
|
-
"additional_parameters" => { "type" => "web_server" }
|
1174
|
-
)
|
1175
|
-
end
|
1176
|
-
|
1177
|
-
it "should allow custom parameters to be set on init" do
|
1178
|
-
expect(@client.additional_parameters).to eq ({ type: "web_server" })
|
1179
|
-
end
|
1180
|
-
|
1181
|
-
it "should allow custom parameters to be updated" do
|
1182
|
-
@client.update! additional_parameters: { "type" => "new_type" }
|
1183
|
-
expect(@client.additional_parameters).to eql ({ type: "new_type" })
|
1184
|
-
end
|
1185
|
-
|
1186
|
-
it "should have correct authorization_uri hash options" do
|
1187
|
-
expect(@client.authorization_uri.host).to eq "accounts.google.com"
|
1188
|
-
expect(@client.authorization_uri.path).to eq "/o/oauth2/auth"
|
1189
|
-
end
|
1190
|
-
|
1191
|
-
it "should use custom parameters when generating authorization_uri" do
|
1192
|
-
expect(@client.authorization_uri.query_values).to eq ({ "access_type" => "offline", "client_id" => "s6BhdRkqt3", "redirect_uri" => "https://example.client.com/callback", "response_type" => "code", "type" => "web_server" })
|
1193
|
-
end
|
1194
|
-
|
1195
|
-
# , "path" => "/o/oauth2/oauth", "host" => "accounts.google.com"
|
1196
|
-
|
1197
|
-
it "should merge new authorization_uri custom parameters" do
|
1198
|
-
expect(@client.authorization_uri(additional_parameters: { "type" => "new_type", "new_param" => "new_val" }).query_values).to eq ({
|
1199
|
-
"access_type" => "offline",
|
1200
|
-
"client_id" => "s6BhdRkqt3",
|
1201
|
-
"new_param" => "new_val",
|
1202
|
-
"response_type" => "code",
|
1203
|
-
"redirect_uri" => "https://example.client.com/callback",
|
1204
|
-
"type" => "new_type"
|
1205
|
-
})
|
1206
|
-
end
|
1207
|
-
|
1208
|
-
it "should merge new generate_access_token_request custom parameters" do
|
1209
|
-
@client.update! code: "12345"
|
1210
|
-
params = @client.generate_access_token_request additional_parameters: { "type" => "new_type", "new_param" => "new_val" }
|
1211
|
-
expect(params).to include("type" => "new_type")
|
1212
|
-
expect(params).to include("new_param" => "new_val")
|
1213
|
-
end
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
describe Signet::OAuth2::Client, "configured for id tokens" do
|
1217
|
-
before do
|
1218
|
-
@key = OpenSSL::PKey::RSA.new 2048
|
1219
|
-
@client = Signet::OAuth2::Client.new(
|
1220
|
-
token_credential_uri: "https://oauth2.googleapis.com/token",
|
1221
|
-
target_audience: "https://api.example.com",
|
1222
|
-
issuer: "app@example.com",
|
1223
|
-
audience: "https://hello.googleapis.com",
|
1224
|
-
signing_key: @key
|
1225
|
-
)
|
1226
|
-
end
|
1227
|
-
|
1228
|
-
it "should set target_audience" do
|
1229
|
-
expect(@client.target_audience).to eq "https://api.example.com"
|
1230
|
-
end
|
1231
|
-
|
1232
|
-
it "should send a valid id token request" do
|
1233
|
-
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
|
1234
|
-
stub.post "/token" do |env|
|
1235
|
-
params = Addressable::URI.form_unencode env[:body]
|
1236
|
-
claim, header = JWT.decode params.assoc("assertion").last, @key.public_key, true, algorithm: "RS256"
|
1237
|
-
expect(params.assoc("grant_type")).to eq ["grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"]
|
1238
|
-
expect(claim["target_audience"]).to eq "https://api.example.com"
|
1239
|
-
expect(claim["iss"]).to eq "app@example.com"
|
1240
|
-
expect(claim["aud"]).to eq "https://hello.googleapis.com"
|
1241
|
-
build_json_response(
|
1242
|
-
"id_token" => "12345id",
|
1243
|
-
"refresh_token" => "54321refresh",
|
1244
|
-
"expires_in" => "3600"
|
1245
|
-
)
|
1246
|
-
end
|
1247
|
-
end
|
1248
|
-
connection = Faraday.new url: "https://www.google.com" do |builder|
|
1249
|
-
builder.adapter :test, stubs
|
1250
|
-
end
|
1251
|
-
@client.fetch_access_token! connection: connection
|
1252
|
-
expect(@client.id_token).to eq "12345id"
|
1253
|
-
end
|
1254
|
-
end
|