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