googleauth 0.9.0 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +11 -0
  3. data/CHANGELOG.md +113 -21
  4. data/README.md +13 -15
  5. data/SECURITY.md +7 -0
  6. data/lib/googleauth/application_default.rb +9 -9
  7. data/lib/googleauth/compute_engine.rb +55 -30
  8. data/lib/googleauth/credentials.rb +253 -64
  9. data/lib/googleauth/credentials_loader.rb +15 -16
  10. data/lib/googleauth/iam.rb +1 -1
  11. data/{spec/googleauth/stores/store_examples.rb → lib/googleauth/id_tokens/errors.rb} +36 -23
  12. data/lib/googleauth/id_tokens/key_sources.rb +396 -0
  13. data/lib/googleauth/id_tokens/verifier.rb +142 -0
  14. data/lib/googleauth/id_tokens.rb +233 -0
  15. data/lib/googleauth/json_key_reader.rb +6 -2
  16. data/lib/googleauth/scope_util.rb +1 -1
  17. data/lib/googleauth/service_account.rb +61 -36
  18. data/lib/googleauth/signet.rb +9 -7
  19. data/lib/googleauth/stores/file_token_store.rb +1 -0
  20. data/lib/googleauth/stores/redis_token_store.rb +1 -0
  21. data/lib/googleauth/user_authorizer.rb +8 -3
  22. data/lib/googleauth/user_refresh.rb +1 -1
  23. data/lib/googleauth/version.rb +1 -1
  24. data/lib/googleauth/web_user_authorizer.rb +5 -8
  25. data/lib/googleauth.rb +1 -0
  26. metadata +33 -76
  27. data/.github/CONTRIBUTING.md +0 -74
  28. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -36
  29. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -21
  30. data/.github/ISSUE_TEMPLATE/support_request.md +0 -7
  31. data/.gitignore +0 -36
  32. data/.kokoro/build.bat +0 -16
  33. data/.kokoro/build.sh +0 -4
  34. data/.kokoro/continuous/common.cfg +0 -24
  35. data/.kokoro/continuous/linux.cfg +0 -15
  36. data/.kokoro/continuous/osx.cfg +0 -3
  37. data/.kokoro/continuous/windows.cfg +0 -19
  38. data/.kokoro/osx.sh +0 -4
  39. data/.kokoro/presubmit/common.cfg +0 -24
  40. data/.kokoro/presubmit/linux.cfg +0 -14
  41. data/.kokoro/presubmit/osx.cfg +0 -3
  42. data/.kokoro/presubmit/windows.cfg +0 -19
  43. data/.kokoro/release.cfg +0 -53
  44. data/.kokoro/trampoline.bat +0 -10
  45. data/.kokoro/trampoline.sh +0 -4
  46. data/.rspec +0 -2
  47. data/.rubocop.yml +0 -42
  48. data/Gemfile +0 -25
  49. data/Rakefile +0 -89
  50. data/googleauth.gemspec +0 -35
  51. data/spec/googleauth/apply_auth_examples.rb +0 -148
  52. data/spec/googleauth/client_id_spec.rb +0 -160
  53. data/spec/googleauth/compute_engine_spec.rb +0 -122
  54. data/spec/googleauth/credentials_spec.rb +0 -459
  55. data/spec/googleauth/get_application_default_spec.rb +0 -286
  56. data/spec/googleauth/iam_spec.rb +0 -80
  57. data/spec/googleauth/scope_util_spec.rb +0 -77
  58. data/spec/googleauth/service_account_spec.rb +0 -482
  59. data/spec/googleauth/signet_spec.rb +0 -134
  60. data/spec/googleauth/stores/file_token_store_spec.rb +0 -57
  61. data/spec/googleauth/stores/redis_token_store_spec.rb +0 -50
  62. data/spec/googleauth/user_authorizer_spec.rb +0 -323
  63. data/spec/googleauth/user_refresh_spec.rb +0 -359
  64. data/spec/googleauth/web_user_authorizer_spec.rb +0 -172
  65. data/spec/spec_helper.rb +0 -92
  66. /data/{COPYING → LICENSE} +0 -0
@@ -0,0 +1,396 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 Google LLC
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following disclaimer
13
+ # in the documentation and/or other materials provided with the
14
+ # distribution.
15
+ # * Neither the name of Google Inc. nor the names of its
16
+ # contributors may be used to endorse or promote products derived from
17
+ # this software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require "base64"
32
+ require "json"
33
+ require "monitor"
34
+ require "net/http"
35
+ require "openssl"
36
+
37
+ require "jwt"
38
+
39
+ module Google
40
+ module Auth
41
+ module IDTokens
42
+ ##
43
+ # A public key used for verifying ID tokens.
44
+ #
45
+ # This includes the public key data, ID, and the algorithm used for
46
+ # signature verification. RSA and Elliptical Curve (EC) keys are
47
+ # supported.
48
+ #
49
+ class KeyInfo
50
+ ##
51
+ # Create a public key info structure.
52
+ #
53
+ # @param id [String] The key ID.
54
+ # @param key [OpenSSL::PKey::RSA,OpenSSL::PKey::EC] The key itself.
55
+ # @param algorithm [String] The algorithm (normally `RS256` or `ES256`)
56
+ #
57
+ def initialize id: nil, key: nil, algorithm: nil
58
+ @id = id
59
+ @key = key
60
+ @algorithm = algorithm
61
+ end
62
+
63
+ ##
64
+ # The key ID.
65
+ # @return [String]
66
+ #
67
+ attr_reader :id
68
+
69
+ ##
70
+ # The key itself.
71
+ # @return [OpenSSL::PKey::RSA,OpenSSL::PKey::EC]
72
+ #
73
+ attr_reader :key
74
+
75
+ ##
76
+ # The signature algorithm. (normally `RS256` or `ES256`)
77
+ # @return [String]
78
+ #
79
+ attr_reader :algorithm
80
+
81
+ class << self
82
+ ##
83
+ # Create a KeyInfo from a single JWK, which may be given as either a
84
+ # hash or an unparsed JSON string.
85
+ #
86
+ # @param jwk [Hash,String] The JWK specification.
87
+ # @return [KeyInfo]
88
+ # @raise [KeySourceError] If the key could not be extracted from the
89
+ # JWK.
90
+ #
91
+ def from_jwk jwk
92
+ jwk = symbolize_keys ensure_json_parsed jwk
93
+ key = case jwk[:kty]
94
+ when "RSA"
95
+ extract_rsa_key jwk
96
+ when "EC"
97
+ extract_ec_key jwk
98
+ when nil
99
+ raise KeySourceError, "Key type not found"
100
+ else
101
+ raise KeySourceError, "Cannot use key type #{jwk[:kty]}"
102
+ end
103
+ new id: jwk[:kid], key: key, algorithm: jwk[:alg]
104
+ end
105
+
106
+ ##
107
+ # Create an array of KeyInfo from a JWK Set, which may be given as
108
+ # either a hash or an unparsed JSON string.
109
+ #
110
+ # @param jwk [Hash,String] The JWK Set specification.
111
+ # @return [Array<KeyInfo>]
112
+ # @raise [KeySourceError] If a key could not be extracted from the
113
+ # JWK Set.
114
+ #
115
+ def from_jwk_set jwk_set
116
+ jwk_set = symbolize_keys ensure_json_parsed jwk_set
117
+ jwks = jwk_set[:keys]
118
+ raise KeySourceError, "No keys found in jwk set" unless jwks
119
+ jwks.map { |jwk| from_jwk jwk }
120
+ end
121
+
122
+ private
123
+
124
+ def ensure_json_parsed input
125
+ return input unless input.is_a? String
126
+ JSON.parse input
127
+ rescue JSON::ParserError
128
+ raise KeySourceError, "Unable to parse JSON"
129
+ end
130
+
131
+ def symbolize_keys hash
132
+ result = {}
133
+ hash.each { |key, val| result[key.to_sym] = val }
134
+ result
135
+ end
136
+
137
+ def extract_rsa_key jwk
138
+ begin
139
+ n_data = Base64.urlsafe_decode64 jwk[:n]
140
+ e_data = Base64.urlsafe_decode64 jwk[:e]
141
+ rescue ArgumentError
142
+ raise KeySourceError, "Badly formatted key data"
143
+ end
144
+ n_bn = OpenSSL::BN.new n_data, 2
145
+ e_bn = OpenSSL::BN.new e_data, 2
146
+ rsa_key = OpenSSL::PKey::RSA.new
147
+ if rsa_key.respond_to? :set_key
148
+ rsa_key.set_key n_bn, e_bn, nil
149
+ else
150
+ rsa_key.n = n_bn
151
+ rsa_key.e = e_bn
152
+ end
153
+ rsa_key.public_key
154
+ end
155
+
156
+ # @private
157
+ CURVE_NAME_MAP = {
158
+ "P-256" => "prime256v1",
159
+ "P-384" => "secp384r1",
160
+ "P-521" => "secp521r1",
161
+ "secp256k1" => "secp256k1"
162
+ }.freeze
163
+
164
+ def extract_ec_key jwk
165
+ begin
166
+ x_data = Base64.urlsafe_decode64 jwk[:x]
167
+ y_data = Base64.urlsafe_decode64 jwk[:y]
168
+ rescue ArgumentError
169
+ raise KeySourceError, "Badly formatted key data"
170
+ end
171
+ curve_name = CURVE_NAME_MAP[jwk[:crv]]
172
+ raise KeySourceError, "Unsupported EC curve #{jwk[:crv]}" unless curve_name
173
+ group = OpenSSL::PKey::EC::Group.new curve_name
174
+ x_hex = x_data.unpack1 "H*"
175
+ y_hex = y_data.unpack1 "H*"
176
+ bn = OpenSSL::BN.new ["04#{x_hex}#{y_hex}"].pack("H*"), 2
177
+ key = OpenSSL::PKey::EC.new curve_name
178
+ key.public_key = OpenSSL::PKey::EC::Point.new group, bn
179
+ key
180
+ end
181
+ end
182
+ end
183
+
184
+ ##
185
+ # A key source that contains a static set of keys.
186
+ #
187
+ class StaticKeySource
188
+ ##
189
+ # Create a static key source with the given keys.
190
+ #
191
+ # @param keys [Array<KeyInfo>] The keys
192
+ #
193
+ def initialize keys
194
+ @current_keys = Array(keys)
195
+ end
196
+
197
+ ##
198
+ # Return the current keys. Does not perform any refresh.
199
+ #
200
+ # @return [Array<KeyInfo>]
201
+ #
202
+ attr_reader :current_keys
203
+ alias refresh_keys current_keys
204
+
205
+ class << self
206
+ ##
207
+ # Create a static key source containing a single key parsed from a
208
+ # single JWK, which may be given as either a hash or an unparsed
209
+ # JSON string.
210
+ #
211
+ # @param jwk [Hash,String] The JWK specification.
212
+ # @return [StaticKeySource]
213
+ #
214
+ def from_jwk jwk
215
+ new KeyInfo.from_jwk jwk
216
+ end
217
+
218
+ ##
219
+ # Create a static key source containing multiple keys parsed from a
220
+ # JWK Set, which may be given as either a hash or an unparsed JSON
221
+ # string.
222
+ #
223
+ # @param jwk_set [Hash,String] The JWK Set specification.
224
+ # @return [StaticKeySource]
225
+ #
226
+ def from_jwk_set jwk_set
227
+ new KeyInfo.from_jwk_set jwk_set
228
+ end
229
+ end
230
+ end
231
+
232
+ ##
233
+ # A base key source that downloads keys from a URI. Subclasses should
234
+ # override {HttpKeySource#interpret_json} to parse the response.
235
+ #
236
+ class HttpKeySource
237
+ ##
238
+ # The default interval between retries in seconds (3600s = 1hr).
239
+ #
240
+ # @return [Integer]
241
+ #
242
+ DEFAULT_RETRY_INTERVAL = 3600
243
+
244
+ ##
245
+ # Create an HTTP key source.
246
+ #
247
+ # @param uri [String,URI] The URI from which to download keys.
248
+ # @param retry_interval [Integer,nil] Override the retry interval in
249
+ # seconds. This is the minimum time between retries of failed key
250
+ # downloads.
251
+ #
252
+ def initialize uri, retry_interval: nil
253
+ @uri = URI uri
254
+ @retry_interval = retry_interval || DEFAULT_RETRY_INTERVAL
255
+ @allow_refresh_at = Time.now
256
+ @current_keys = []
257
+ @monitor = Monitor.new
258
+ end
259
+
260
+ ##
261
+ # The URI from which to download keys.
262
+ # @return [Array<KeyInfo>]
263
+ #
264
+ attr_reader :uri
265
+
266
+ ##
267
+ # Return the current keys, without attempting to re-download.
268
+ #
269
+ # @return [Array<KeyInfo>]
270
+ #
271
+ attr_reader :current_keys
272
+
273
+ ##
274
+ # Attempt to re-download keys (if the retry interval has expired) and
275
+ # return the new keys.
276
+ #
277
+ # @return [Array<KeyInfo>]
278
+ # @raise [KeySourceError] if key retrieval failed.
279
+ #
280
+ def refresh_keys
281
+ @monitor.synchronize do
282
+ return @current_keys if Time.now < @allow_refresh_at
283
+ @allow_refresh_at = Time.now + @retry_interval
284
+
285
+ response = Net::HTTP.get_response uri
286
+ raise KeySourceError, "Unable to retrieve data from #{uri}" unless response.is_a? Net::HTTPSuccess
287
+
288
+ data = begin
289
+ JSON.parse response.body
290
+ rescue JSON::ParserError
291
+ raise KeySourceError, "Unable to parse JSON"
292
+ end
293
+
294
+ @current_keys = Array(interpret_json(data))
295
+ end
296
+ end
297
+
298
+ protected
299
+
300
+ def interpret_json _data
301
+ nil
302
+ end
303
+ end
304
+
305
+ ##
306
+ # A key source that downloads X509 certificates.
307
+ # Used by the legacy OAuth V1 public certs endpoint.
308
+ #
309
+ class X509CertHttpKeySource < HttpKeySource
310
+ ##
311
+ # Create a key source that downloads X509 certificates.
312
+ #
313
+ # @param uri [String,URI] The URI from which to download keys.
314
+ # @param algorithm [String] The algorithm to use for signature
315
+ # verification. Defaults to "`RS256`".
316
+ # @param retry_interval [Integer,nil] Override the retry interval in
317
+ # seconds. This is the minimum time between retries of failed key
318
+ # downloads.
319
+ #
320
+ def initialize uri, algorithm: "RS256", retry_interval: nil
321
+ super uri, retry_interval: retry_interval
322
+ @algorithm = algorithm
323
+ end
324
+
325
+ protected
326
+
327
+ def interpret_json data
328
+ data.map do |id, cert_str|
329
+ key = OpenSSL::X509::Certificate.new(cert_str).public_key
330
+ KeyInfo.new id: id, key: key, algorithm: @algorithm
331
+ end
332
+ rescue OpenSSL::X509::CertificateError
333
+ raise KeySourceError, "Unable to parse X509 certificates"
334
+ end
335
+ end
336
+
337
+ ##
338
+ # A key source that downloads a JWK set.
339
+ #
340
+ class JwkHttpKeySource < HttpKeySource
341
+ ##
342
+ # Create a key source that downloads a JWT Set.
343
+ #
344
+ # @param uri [String,URI] The URI from which to download keys.
345
+ # @param retry_interval [Integer,nil] Override the retry interval in
346
+ # seconds. This is the minimum time between retries of failed key
347
+ # downloads.
348
+ #
349
+ def initialize uri, retry_interval: nil
350
+ super uri, retry_interval: retry_interval
351
+ end
352
+
353
+ protected
354
+
355
+ def interpret_json data
356
+ KeyInfo.from_jwk_set data
357
+ end
358
+ end
359
+
360
+ ##
361
+ # A key source that aggregates other key sources. This means it will
362
+ # aggregate the keys provided by its constituent sources. Additionally,
363
+ # when asked to refresh, it will refresh all its constituent sources.
364
+ #
365
+ class AggregateKeySource
366
+ ##
367
+ # Create a key source that aggregates other key sources.
368
+ #
369
+ # @param sources [Array<key source>] The key sources to aggregate.
370
+ #
371
+ def initialize sources
372
+ @sources = Array(sources)
373
+ end
374
+
375
+ ##
376
+ # Return the current keys, without attempting to refresh.
377
+ #
378
+ # @return [Array<KeyInfo>]
379
+ #
380
+ def current_keys
381
+ @sources.flat_map(&:current_keys)
382
+ end
383
+
384
+ ##
385
+ # Attempt to refresh keys and return the new keys.
386
+ #
387
+ # @return [Array<KeyInfo>]
388
+ # @raise [KeySourceError] if key retrieval failed.
389
+ #
390
+ def refresh_keys
391
+ @sources.flat_map(&:refresh_keys)
392
+ end
393
+ end
394
+ end
395
+ end
396
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 Google LLC
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following disclaimer
13
+ # in the documentation and/or other materials provided with the
14
+ # distribution.
15
+ # * Neither the name of Google Inc. nor the names of its
16
+ # contributors may be used to endorse or promote products derived from
17
+ # this software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require "jwt"
32
+
33
+ module Google
34
+ module Auth
35
+ module IDTokens
36
+ ##
37
+ # An object that can verify ID tokens.
38
+ #
39
+ # A verifier maintains a set of default settings, including the key
40
+ # source and fields to verify. However, individual verification calls can
41
+ # override any of these settings.
42
+ #
43
+ class Verifier
44
+ ##
45
+ # Create a verifier.
46
+ #
47
+ # @param key_source [key source] The default key source to use. All
48
+ # verification calls must have a key source, so if no default key
49
+ # source is provided here, then calls to {#verify} _must_ provide
50
+ # a key source.
51
+ # @param aud [String,nil] The default audience (`aud`) check, or `nil`
52
+ # for no check.
53
+ # @param azp [String,nil] The default authorized party (`azp`) check,
54
+ # or `nil` for no check.
55
+ # @param iss [String,nil] The default issuer (`iss`) check, or `nil`
56
+ # for no check.
57
+ #
58
+ def initialize key_source: nil,
59
+ aud: nil,
60
+ azp: nil,
61
+ iss: nil
62
+ @key_source = key_source
63
+ @aud = aud
64
+ @azp = azp
65
+ @iss = iss
66
+ end
67
+
68
+ ##
69
+ # Verify the given token.
70
+ #
71
+ # @param token [String] the ID token to verify.
72
+ # @param key_source [key source] If given, override the key source.
73
+ # @param aud [String,nil] If given, override the `aud` check.
74
+ # @param azp [String,nil] If given, override the `azp` check.
75
+ # @param iss [String,nil] If given, override the `iss` check.
76
+ #
77
+ # @return [Hash] the decoded payload, if verification succeeded.
78
+ # @raise [KeySourceError] if the key source failed to obtain public keys
79
+ # @raise [VerificationError] if the token verification failed.
80
+ # Additional data may be available in the error subclass and message.
81
+ #
82
+ def verify token,
83
+ key_source: :default,
84
+ aud: :default,
85
+ azp: :default,
86
+ iss: :default
87
+ key_source = @key_source if key_source == :default
88
+ aud = @aud if aud == :default
89
+ azp = @azp if azp == :default
90
+ iss = @iss if iss == :default
91
+
92
+ raise KeySourceError, "No key sources" unless key_source
93
+ keys = key_source.current_keys
94
+ payload = decode_token token, keys, aud, azp, iss
95
+ unless payload
96
+ keys = key_source.refresh_keys
97
+ payload = decode_token token, keys, aud, azp, iss
98
+ end
99
+ raise SignatureError, "Token not verified as issued by Google" unless payload
100
+ payload
101
+ end
102
+
103
+ private
104
+
105
+ def decode_token token, keys, aud, azp, iss
106
+ payload = nil
107
+ keys.find do |key|
108
+ options = { algorithms: key.algorithm }
109
+ decoded_token = JWT.decode token, key.key, true, options
110
+ payload = decoded_token.first
111
+ rescue JWT::ExpiredSignature
112
+ raise ExpiredTokenError, "Token signature is expired"
113
+ rescue JWT::DecodeError
114
+ nil # Try the next key
115
+ end
116
+
117
+ normalize_and_verify_payload payload, aud, azp, iss
118
+ end
119
+
120
+ def normalize_and_verify_payload payload, aud, azp, iss
121
+ return nil unless payload
122
+
123
+ # Map the legacy "cid" claim to the canonical "azp"
124
+ payload["azp"] ||= payload["cid"] if payload.key? "cid"
125
+
126
+ # Payload content validation
127
+ if aud && (Array(aud) & Array(payload["aud"])).empty?
128
+ raise AudienceMismatchError, "Token aud mismatch: #{payload['aud']}"
129
+ end
130
+ if azp && (Array(azp) & Array(payload["azp"])).empty?
131
+ raise AuthorizedPartyMismatchError, "Token azp mismatch: #{payload['azp']}"
132
+ end
133
+ if iss && (Array(iss) & Array(payload["iss"])).empty?
134
+ raise IssuerMismatchError, "Token iss mismatch: #{payload['iss']}"
135
+ end
136
+
137
+ payload
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end