@valbuild/next 0.120.0 → 0.120.3
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.
|
@@ -150,6 +150,10 @@ function initValServer(valModules, config, nextConfig) {
|
|
|
150
150
|
* - **Nothing is read from the payload before the signature verifies.** Claims
|
|
151
151
|
* from an unverified token are attacker input.
|
|
152
152
|
* - **Keys come only from the configured issuer's JWKS**, never from the token.
|
|
153
|
+
* The key set is cached, but a token naming a `kid` the cache does not hold
|
|
154
|
+
* provokes one rate-limited refetch rather than a refusal — see
|
|
155
|
+
* {@link UNKNOWN_KID_REFETCH_INTERVAL_MS}. Without that, this server's own
|
|
156
|
+
* cache turns any key rotation into an outage lasting the rest of the TTL.
|
|
153
157
|
* - **ECDSA JWS signatures are raw `r||s`** (RFC 7518), not DER, which is what
|
|
154
158
|
* `dsaEncoding: "ieee-p1363"` below is for. Omit it and every valid signature
|
|
155
159
|
* is rejected — or worse, a future change makes it accept the wrong thing.
|
|
@@ -166,6 +170,21 @@ var JWKS_TTL_MS = 5 * 60 * 1000;
|
|
|
166
170
|
* it.
|
|
167
171
|
*/
|
|
168
172
|
var JWKS_ERROR_TTL_MS = 30 * 1000;
|
|
173
|
+
/**
|
|
174
|
+
* The floor between two refetches provoked by an unknown `kid`.
|
|
175
|
+
*
|
|
176
|
+
* A token naming a key this process has not seen is the one case where the TTL
|
|
177
|
+
* is the wrong answer: the issuer may have just rotated, and refusing for the
|
|
178
|
+
* rest of the five minutes turns a rotation into an outage. So an unknown `kid`
|
|
179
|
+
* bypasses the TTL — but only this often, because the `kid` comes from the
|
|
180
|
+
* token and the token comes from whoever is calling. Without a floor, a stream
|
|
181
|
+
* of random `kid`s would be a way to make this server hammer its own issuer.
|
|
182
|
+
*
|
|
183
|
+
* Note what the floor costs when it bites: a refusal, for a token that would
|
|
184
|
+
* have verified, for at most this long. That is the same failure the TTL used
|
|
185
|
+
* to guarantee for five minutes, so the trade only ever improves.
|
|
186
|
+
*/
|
|
187
|
+
var UNKNOWN_KID_REFETCH_INTERVAL_MS = 30 * 1000;
|
|
169
188
|
/**
|
|
170
189
|
* One cache per issuer, and it has to outlive the request or it is not a cache:
|
|
171
190
|
* a fetch per tool call would put a network round trip in front of every read.
|
|
@@ -173,6 +192,15 @@ var JWKS_ERROR_TTL_MS = 30 * 1000;
|
|
|
173
192
|
var jwksCache = new Map();
|
|
174
193
|
/** Concurrent misses share one fetch rather than starting several. */
|
|
175
194
|
var inFlight = new Map();
|
|
195
|
+
/**
|
|
196
|
+
* When an unknown `kid` last made us go back to the issuer, per issuer.
|
|
197
|
+
*
|
|
198
|
+
* Separate from the cache because it is a rate limit rather than a cache: it
|
|
199
|
+
* records an *attempt*, so a refetch that found nothing new still spends the
|
|
200
|
+
* window. Keyed by issuer, not by `kid`, or an attacker would simply use a new
|
|
201
|
+
* one each time.
|
|
202
|
+
*/
|
|
203
|
+
var unknownKidRefetchAtMs = new Map();
|
|
176
204
|
function jwksUrl(issuer) {
|
|
177
205
|
// Not discovered from the issuer's metadata document, deliberately:
|
|
178
206
|
// discovery would mean one more request on the hot path and one more thing
|
|
@@ -183,105 +211,211 @@ function jwksUrl(issuer) {
|
|
|
183
211
|
function loadJwks(_x, _x2) {
|
|
184
212
|
return _loadJwks.apply(this, arguments);
|
|
185
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Go back to the issuer because the token named a key we do not have.
|
|
216
|
+
*
|
|
217
|
+
* Rate-limited, and the limit is the whole reason this is not just a call to
|
|
218
|
+
* {@link fetchJwks}: the `kid` that triggers it is attacker-controlled. Returns
|
|
219
|
+
* `null` when the window has not elapsed, which the caller reads as "nothing
|
|
220
|
+
* new to try" rather than as a failure.
|
|
221
|
+
*
|
|
222
|
+
* The limit is on *starting* a fetch, not on benefiting from one. A fetch
|
|
223
|
+
* already in flight is joined whatever the window says, because joining it
|
|
224
|
+
* costs the issuer nothing — and the case that matters is precisely a burst:
|
|
225
|
+
* at a rotation, many requests arrive at once carrying the same new `kid`, and
|
|
226
|
+
* refusing all but the first would be the outage this whole path exists to
|
|
227
|
+
* prevent, merely shortened from five minutes to thirty seconds.
|
|
228
|
+
*
|
|
229
|
+
* Only ever called with a successfully-fetched key set in hand. An error entry
|
|
230
|
+
* has its own, shorter TTL and its own recovery, and letting an unknown `kid`
|
|
231
|
+
* shortcut it would hand an unreachable issuer a retry storm.
|
|
232
|
+
*/
|
|
186
233
|
function _loadJwks() {
|
|
187
|
-
_loadJwks = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
188
|
-
var
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
while (1) switch (_context2.p = _context2.n) {
|
|
234
|
+
_loadJwks = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(config, nowMs) {
|
|
235
|
+
var url, cached, age, ttl, _t;
|
|
236
|
+
return _regenerator().w(function (_context) {
|
|
237
|
+
while (1) switch (_context.n) {
|
|
192
238
|
case 0:
|
|
193
239
|
url = jwksUrl(config.issuer);
|
|
194
240
|
cached = jwksCache.get(url);
|
|
195
241
|
if (!cached) {
|
|
196
|
-
|
|
242
|
+
_context.n = 1;
|
|
197
243
|
break;
|
|
198
244
|
}
|
|
199
245
|
age = cached.status === "keys" ? nowMs - cached.fetchedAtMs : nowMs - cached.failedAtMs;
|
|
200
246
|
ttl = cached.status === "keys" ? JWKS_TTL_MS : JWKS_ERROR_TTL_MS;
|
|
201
247
|
if (!(age < ttl)) {
|
|
202
|
-
|
|
248
|
+
_context.n = 1;
|
|
203
249
|
break;
|
|
204
250
|
}
|
|
205
|
-
return
|
|
251
|
+
return _context.a(2, {
|
|
252
|
+
entry: cached,
|
|
253
|
+
fromCache: true
|
|
254
|
+
});
|
|
206
255
|
case 1:
|
|
256
|
+
_context.n = 2;
|
|
257
|
+
return fetchJwks(config, nowMs);
|
|
258
|
+
case 2:
|
|
259
|
+
_t = _context.v;
|
|
260
|
+
return _context.a(2, {
|
|
261
|
+
entry: _t,
|
|
262
|
+
fromCache: false
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}, _callee);
|
|
266
|
+
}));
|
|
267
|
+
return _loadJwks.apply(this, arguments);
|
|
268
|
+
}
|
|
269
|
+
function refetchForUnknownKid(_x3, _x4) {
|
|
270
|
+
return _refetchForUnknownKid.apply(this, arguments);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Fetch the key set, ignoring whatever is cached, and cache the result.
|
|
274
|
+
*
|
|
275
|
+
* Shares {@link inFlight} with every other caller, so a forced refetch that
|
|
276
|
+
* lands during an ordinary miss joins it rather than opening a second request.
|
|
277
|
+
* Only the caller that *starts* a fetch writes the cache — a joiner returns the
|
|
278
|
+
* shared promise above — so `keepCacheOnError` is a property of the fetch, not a
|
|
279
|
+
* race between callers.
|
|
280
|
+
*/
|
|
281
|
+
function _refetchForUnknownKid() {
|
|
282
|
+
_refetchForUnknownKid = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(config, nowMs) {
|
|
283
|
+
var url, existing, lastAttemptMs;
|
|
284
|
+
return _regenerator().w(function (_context2) {
|
|
285
|
+
while (1) switch (_context2.n) {
|
|
286
|
+
case 0:
|
|
287
|
+
url = jwksUrl(config.issuer);
|
|
207
288
|
existing = inFlight.get(url);
|
|
208
289
|
if (!existing) {
|
|
209
|
-
_context2.n =
|
|
290
|
+
_context2.n = 1;
|
|
210
291
|
break;
|
|
211
292
|
}
|
|
212
293
|
return _context2.a(2, existing);
|
|
294
|
+
case 1:
|
|
295
|
+
lastAttemptMs = unknownKidRefetchAtMs.get(url);
|
|
296
|
+
if (!(lastAttemptMs !== undefined && nowMs - lastAttemptMs < UNKNOWN_KID_REFETCH_INTERVAL_MS)) {
|
|
297
|
+
_context2.n = 2;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
return _context2.a(2, null);
|
|
213
301
|
case 2:
|
|
302
|
+
// Recorded before the await, so that once this fetch has finished the window
|
|
303
|
+
// is already closed against the next unknown `kid`.
|
|
304
|
+
unknownKidRefetchAtMs.set(url, nowMs);
|
|
305
|
+
return _context2.a(2, fetchJwks(config, nowMs, {
|
|
306
|
+
keepCacheOnError: true
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
}, _callee2);
|
|
310
|
+
}));
|
|
311
|
+
return _refetchForUnknownKid.apply(this, arguments);
|
|
312
|
+
}
|
|
313
|
+
function fetchJwks(_x5, _x6) {
|
|
314
|
+
return _fetchJwks.apply(this, arguments);
|
|
315
|
+
}
|
|
316
|
+
function _fetchJwks() {
|
|
317
|
+
_fetchJwks = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(config, nowMs) {
|
|
318
|
+
var _config$fetchImpl;
|
|
319
|
+
var _ref,
|
|
320
|
+
_ref$keepCacheOnError,
|
|
321
|
+
keepCacheOnError,
|
|
322
|
+
url,
|
|
323
|
+
existing,
|
|
324
|
+
fetchImpl,
|
|
325
|
+
pending,
|
|
326
|
+
entry,
|
|
327
|
+
cached,
|
|
328
|
+
_args4 = arguments;
|
|
329
|
+
return _regenerator().w(function (_context4) {
|
|
330
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
331
|
+
case 0:
|
|
332
|
+
_ref = _args4.length > 2 && _args4[2] !== undefined ? _args4[2] : {}, _ref$keepCacheOnError = _ref.keepCacheOnError, keepCacheOnError = _ref$keepCacheOnError === void 0 ? false : _ref$keepCacheOnError;
|
|
333
|
+
url = jwksUrl(config.issuer);
|
|
334
|
+
existing = inFlight.get(url);
|
|
335
|
+
if (!existing) {
|
|
336
|
+
_context4.n = 1;
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
return _context4.a(2, existing);
|
|
340
|
+
case 1:
|
|
214
341
|
fetchImpl = (_config$fetchImpl = config.fetchImpl) !== null && _config$fetchImpl !== void 0 ? _config$fetchImpl : fetch;
|
|
215
|
-
pending = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
342
|
+
pending = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
216
343
|
var res, body, keys;
|
|
217
|
-
return _regenerator().w(function (
|
|
218
|
-
while (1) switch (
|
|
344
|
+
return _regenerator().w(function (_context3) {
|
|
345
|
+
while (1) switch (_context3.p = _context3.n) {
|
|
219
346
|
case 0:
|
|
220
|
-
|
|
221
|
-
|
|
347
|
+
_context3.p = 0;
|
|
348
|
+
_context3.n = 1;
|
|
222
349
|
return fetchImpl(url, {
|
|
223
350
|
headers: {
|
|
224
351
|
accept: "application/json"
|
|
225
352
|
}
|
|
226
353
|
});
|
|
227
354
|
case 1:
|
|
228
|
-
res =
|
|
355
|
+
res = _context3.v;
|
|
229
356
|
if (res.ok) {
|
|
230
|
-
|
|
357
|
+
_context3.n = 2;
|
|
231
358
|
break;
|
|
232
359
|
}
|
|
233
|
-
return
|
|
360
|
+
return _context3.a(2, {
|
|
234
361
|
status: "error",
|
|
235
362
|
failedAtMs: nowMs
|
|
236
363
|
});
|
|
237
364
|
case 2:
|
|
238
|
-
|
|
365
|
+
_context3.n = 3;
|
|
239
366
|
return res.json();
|
|
240
367
|
case 3:
|
|
241
|
-
body =
|
|
368
|
+
body = _context3.v;
|
|
242
369
|
keys = readKeys(body);
|
|
243
370
|
if (!(keys === null)) {
|
|
244
|
-
|
|
371
|
+
_context3.n = 4;
|
|
245
372
|
break;
|
|
246
373
|
}
|
|
247
|
-
return
|
|
374
|
+
return _context3.a(2, {
|
|
248
375
|
status: "error",
|
|
249
376
|
failedAtMs: nowMs
|
|
250
377
|
});
|
|
251
378
|
case 4:
|
|
252
|
-
return
|
|
379
|
+
return _context3.a(2, {
|
|
253
380
|
status: "keys",
|
|
254
381
|
keys: keys,
|
|
255
382
|
fetchedAtMs: nowMs
|
|
256
383
|
});
|
|
257
384
|
case 5:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return
|
|
385
|
+
_context3.p = 5;
|
|
386
|
+
_context3.v;
|
|
387
|
+
return _context3.a(2, {
|
|
261
388
|
status: "error",
|
|
262
389
|
failedAtMs: nowMs
|
|
263
390
|
});
|
|
264
391
|
}
|
|
265
|
-
},
|
|
392
|
+
}, _callee3, null, [[0, 5]]);
|
|
266
393
|
}))();
|
|
267
394
|
inFlight.set(url, pending);
|
|
268
|
-
|
|
269
|
-
|
|
395
|
+
_context4.p = 2;
|
|
396
|
+
_context4.n = 3;
|
|
270
397
|
return pending;
|
|
398
|
+
case 3:
|
|
399
|
+
entry = _context4.v;
|
|
400
|
+
cached = jwksCache.get(url);
|
|
401
|
+
if (!(entry.status === "error" && keepCacheOnError && (cached === null || cached === void 0 ? void 0 : cached.status) === "keys")) {
|
|
402
|
+
_context4.n = 4;
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
return _context4.a(2, entry);
|
|
271
406
|
case 4:
|
|
272
|
-
entry = _context2.v;
|
|
273
407
|
jwksCache.set(url, entry);
|
|
274
|
-
return
|
|
408
|
+
return _context4.a(2, entry);
|
|
275
409
|
case 5:
|
|
276
|
-
|
|
410
|
+
_context4.p = 5;
|
|
277
411
|
inFlight["delete"](url);
|
|
278
|
-
return
|
|
412
|
+
return _context4.f(5);
|
|
279
413
|
case 6:
|
|
280
|
-
return
|
|
414
|
+
return _context4.a(2);
|
|
281
415
|
}
|
|
282
|
-
},
|
|
416
|
+
}, _callee4, null, [[2,, 5, 6]]);
|
|
283
417
|
}));
|
|
284
|
-
return
|
|
418
|
+
return _fetchJwks.apply(this, arguments);
|
|
285
419
|
}
|
|
286
420
|
function readKeys(body) {
|
|
287
421
|
if (_typeof(body) !== "object" || body === null || !("keys" in body)) {
|
|
@@ -316,22 +450,22 @@ function readBearerToken(request) {
|
|
|
316
450
|
var token = match === null || match === void 0 || (_match$ = match[1]) === null || _match$ === void 0 ? void 0 : _match$.trim();
|
|
317
451
|
return token ? token : null;
|
|
318
452
|
}
|
|
319
|
-
function verifyValAccessToken(
|
|
453
|
+
function verifyValAccessToken(_x7, _x8) {
|
|
320
454
|
return _verifyValAccessToken.apply(this, arguments);
|
|
321
455
|
}
|
|
322
456
|
function _verifyValAccessToken() {
|
|
323
|
-
_verifyValAccessToken = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
457
|
+
_verifyValAccessToken = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(request, config) {
|
|
324
458
|
var _config$clockToleranc;
|
|
325
|
-
var token, parts, _parts, encodedHeader, encodedPayload, encodedSignature, header, kid, nowMs,
|
|
326
|
-
return _regenerator().w(function (
|
|
327
|
-
while (1) switch (
|
|
459
|
+
var token, parts, _parts, encodedHeader, encodedPayload, encodedSignature, header, kid, nowMs, loaded, candidates, refetched, signature, signedData, verified, payload, tolerance, nowSeconds, subject, scopes;
|
|
460
|
+
return _regenerator().w(function (_context5) {
|
|
461
|
+
while (1) switch (_context5.n) {
|
|
328
462
|
case 0:
|
|
329
463
|
token = readBearerToken(request);
|
|
330
464
|
if (!(token === null)) {
|
|
331
|
-
|
|
465
|
+
_context5.n = 1;
|
|
332
466
|
break;
|
|
333
467
|
}
|
|
334
|
-
return
|
|
468
|
+
return _context5.a(2, {
|
|
335
469
|
status: "refused",
|
|
336
470
|
error: "invalid_request",
|
|
337
471
|
description: "This Val MCP endpoint needs an access token. Authorize with the Val authorization server and present it as `Authorization: Bearer`."
|
|
@@ -339,125 +473,148 @@ function _verifyValAccessToken() {
|
|
|
339
473
|
case 1:
|
|
340
474
|
parts = token.split(".");
|
|
341
475
|
if (!(parts.length !== 3)) {
|
|
342
|
-
|
|
476
|
+
_context5.n = 2;
|
|
343
477
|
break;
|
|
344
478
|
}
|
|
345
|
-
return
|
|
479
|
+
return _context5.a(2, invalidToken("The access token is not a JWS."));
|
|
346
480
|
case 2:
|
|
347
481
|
_parts = _slicedToArray(parts, 3), encodedHeader = _parts[0], encodedPayload = _parts[1], encodedSignature = _parts[2];
|
|
348
482
|
header = decodeJsonSegment(encodedHeader);
|
|
349
483
|
if (!(header === null)) {
|
|
350
|
-
|
|
484
|
+
_context5.n = 3;
|
|
351
485
|
break;
|
|
352
486
|
}
|
|
353
|
-
return
|
|
487
|
+
return _context5.a(2, invalidToken("The access token's header could not be read."));
|
|
354
488
|
case 3:
|
|
355
489
|
if (!(header.alg !== "ES256")) {
|
|
356
|
-
|
|
490
|
+
_context5.n = 4;
|
|
357
491
|
break;
|
|
358
492
|
}
|
|
359
|
-
return
|
|
493
|
+
return _context5.a(2, invalidToken("The access token is not signed with ES256, which is the only algorithm this server accepts."));
|
|
360
494
|
case 4:
|
|
361
495
|
kid = typeof header.kid === "string" ? header.kid : null;
|
|
362
496
|
nowMs = Date.now();
|
|
363
|
-
|
|
497
|
+
_context5.n = 5;
|
|
364
498
|
return loadJwks(config, nowMs);
|
|
365
499
|
case 5:
|
|
366
|
-
|
|
367
|
-
if (!(
|
|
368
|
-
|
|
500
|
+
loaded = _context5.v;
|
|
501
|
+
if (!(loaded.entry.status === "error")) {
|
|
502
|
+
_context5.n = 6;
|
|
369
503
|
break;
|
|
370
504
|
}
|
|
371
|
-
return
|
|
505
|
+
return _context5.a(2, invalidToken("The access token could not be verified because the Val authorization server's keys could not be fetched. This may be temporary."));
|
|
372
506
|
case 6:
|
|
373
|
-
candidates =
|
|
507
|
+
candidates = loaded.entry.keys.filter(function (key) {
|
|
374
508
|
return isVerifyingP256Key(key, kid);
|
|
375
509
|
});
|
|
376
|
-
if (!(candidates.length === 0)) {
|
|
377
|
-
|
|
510
|
+
if (!(candidates.length === 0 && kid !== null && loaded.fromCache)) {
|
|
511
|
+
_context5.n = 9;
|
|
378
512
|
break;
|
|
379
513
|
}
|
|
380
|
-
|
|
514
|
+
_context5.n = 7;
|
|
515
|
+
return refetchForUnknownKid(config, nowMs);
|
|
381
516
|
case 7:
|
|
517
|
+
refetched = _context5.v;
|
|
518
|
+
if (!(refetched !== null)) {
|
|
519
|
+
_context5.n = 9;
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
if (!(refetched.status === "error")) {
|
|
523
|
+
_context5.n = 8;
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
return _context5.a(2, invalidToken("The access token could not be verified because the Val authorization server's keys could not be fetched. This may be temporary."));
|
|
527
|
+
case 8:
|
|
528
|
+
candidates = refetched.keys.filter(function (key) {
|
|
529
|
+
return isVerifyingP256Key(key, kid);
|
|
530
|
+
});
|
|
531
|
+
case 9:
|
|
532
|
+
if (!(candidates.length === 0)) {
|
|
533
|
+
_context5.n = 10;
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
return _context5.a(2, invalidToken("The access token was signed with a key the Val authorization server does not publish."));
|
|
537
|
+
case 10:
|
|
382
538
|
signature = decodeBase64Url(encodedSignature);
|
|
383
539
|
if (!(signature === null)) {
|
|
384
|
-
|
|
540
|
+
_context5.n = 11;
|
|
385
541
|
break;
|
|
386
542
|
}
|
|
387
|
-
return
|
|
388
|
-
case
|
|
543
|
+
return _context5.a(2, invalidToken("The access token's signature could not be read."));
|
|
544
|
+
case 11:
|
|
389
545
|
signedData = Buffer.from("".concat(encodedHeader, ".").concat(encodedPayload), "ascii"); // Every published key is tried when the token names no `kid`, so a rotation
|
|
390
546
|
// that has not yet propagated to clients still verifies. With a `kid` the
|
|
391
|
-
// filter above leaves one
|
|
547
|
+
// filter above leaves one — or, if this process had not yet seen that key,
|
|
548
|
+
// the one the refetch just found.
|
|
392
549
|
verified = candidates.some(function (key) {
|
|
393
550
|
return verifyWithJwk(key, signedData, signature);
|
|
394
551
|
});
|
|
395
552
|
if (verified) {
|
|
396
|
-
|
|
553
|
+
_context5.n = 12;
|
|
397
554
|
break;
|
|
398
555
|
}
|
|
399
|
-
return
|
|
400
|
-
case
|
|
556
|
+
return _context5.a(2, invalidToken("The access token's signature could not be verified."));
|
|
557
|
+
case 12:
|
|
401
558
|
// Only now: everything below reads the payload, and before this line it was
|
|
402
559
|
// attacker input.
|
|
403
560
|
payload = decodeJsonSegment(encodedPayload);
|
|
404
561
|
if (!(payload === null)) {
|
|
405
|
-
|
|
562
|
+
_context5.n = 13;
|
|
406
563
|
break;
|
|
407
564
|
}
|
|
408
|
-
return
|
|
409
|
-
case
|
|
565
|
+
return _context5.a(2, invalidToken("The access token's payload could not be read."));
|
|
566
|
+
case 13:
|
|
410
567
|
tolerance = (_config$clockToleranc = config.clockToleranceSeconds) !== null && _config$clockToleranc !== void 0 ? _config$clockToleranc : DEFAULT_CLOCK_TOLERANCE_SECONDS;
|
|
411
568
|
nowSeconds = Math.floor(nowMs / 1000);
|
|
412
569
|
if (!(typeof payload.exp !== "number")) {
|
|
413
|
-
|
|
570
|
+
_context5.n = 14;
|
|
414
571
|
break;
|
|
415
572
|
}
|
|
416
|
-
return
|
|
417
|
-
case
|
|
573
|
+
return _context5.a(2, invalidToken("The access token has no expiry."));
|
|
574
|
+
case 14:
|
|
418
575
|
if (!(payload.exp + tolerance <= nowSeconds)) {
|
|
419
|
-
|
|
576
|
+
_context5.n = 15;
|
|
420
577
|
break;
|
|
421
578
|
}
|
|
422
|
-
return
|
|
423
|
-
case
|
|
579
|
+
return _context5.a(2, invalidToken("The access token has expired. Refresh it and try again."));
|
|
580
|
+
case 15:
|
|
424
581
|
if (!(typeof payload.nbf === "number" && payload.nbf - tolerance > nowSeconds)) {
|
|
425
|
-
|
|
582
|
+
_context5.n = 16;
|
|
426
583
|
break;
|
|
427
584
|
}
|
|
428
|
-
return
|
|
429
|
-
case
|
|
585
|
+
return _context5.a(2, invalidToken("The access token is not valid yet."));
|
|
586
|
+
case 16:
|
|
430
587
|
if (!(payload.iss !== config.issuer)) {
|
|
431
|
-
|
|
588
|
+
_context5.n = 17;
|
|
432
589
|
break;
|
|
433
590
|
}
|
|
434
|
-
return
|
|
435
|
-
case
|
|
591
|
+
return _context5.a(2, invalidToken("The access token was not issued by this server's authorization server (iss claim)."));
|
|
592
|
+
case 17:
|
|
436
593
|
if (audienceMatches(payload.aud, config.resource)) {
|
|
437
|
-
|
|
594
|
+
_context5.n = 18;
|
|
438
595
|
break;
|
|
439
596
|
}
|
|
440
|
-
return
|
|
441
|
-
case
|
|
597
|
+
return _context5.a(2, invalidToken("The access token is not valid for this server (aud claim)."));
|
|
598
|
+
case 18:
|
|
442
599
|
subject = payload.sub;
|
|
443
600
|
if (!(typeof subject !== "string" || subject.length === 0)) {
|
|
444
|
-
|
|
601
|
+
_context5.n = 19;
|
|
445
602
|
break;
|
|
446
603
|
}
|
|
447
|
-
return
|
|
448
|
-
case
|
|
604
|
+
return _context5.a(2, invalidToken("The access token has no subject."));
|
|
605
|
+
case 19:
|
|
449
606
|
scopes = readScopes(payload.scope);
|
|
450
607
|
if (scopes.includes(VAL_SCOPE_READ)) {
|
|
451
|
-
|
|
608
|
+
_context5.n = 20;
|
|
452
609
|
break;
|
|
453
610
|
}
|
|
454
|
-
return
|
|
611
|
+
return _context5.a(2, {
|
|
455
612
|
status: "refused",
|
|
456
613
|
error: "insufficient_scope",
|
|
457
614
|
description: "The access token does not have the ".concat(VAL_SCOPE_READ, " scope, so it cannot read any content.")
|
|
458
615
|
});
|
|
459
|
-
case
|
|
460
|
-
return
|
|
616
|
+
case 20:
|
|
617
|
+
return _context5.a(2, {
|
|
461
618
|
status: "ok",
|
|
462
619
|
auth: {
|
|
463
620
|
type: "verified-profile",
|
|
@@ -466,7 +623,7 @@ function _verifyValAccessToken() {
|
|
|
466
623
|
}
|
|
467
624
|
});
|
|
468
625
|
}
|
|
469
|
-
},
|
|
626
|
+
}, _callee5);
|
|
470
627
|
}));
|
|
471
628
|
return _verifyValAccessToken.apply(this, arguments);
|
|
472
629
|
}
|