oidc-spa 7.2.4 → 7.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/core/Oidc.d.ts +4 -1
  2. package/core/createOidc.js +69 -19
  3. package/core/createOidc.js.map +1 -1
  4. package/core/handleOidcCallback.js +2 -4
  5. package/core/handleOidcCallback.js.map +1 -1
  6. package/core/loginOrGoToAuthServer.js +8 -2
  7. package/core/loginOrGoToAuthServer.js.map +1 -1
  8. package/core/oidcClientTsUserToTokens.js +7 -2
  9. package/core/oidcClientTsUserToTokens.js.map +1 -1
  10. package/esm/core/Oidc.d.ts +4 -1
  11. package/esm/core/createOidc.js +69 -19
  12. package/esm/core/createOidc.js.map +1 -1
  13. package/esm/core/handleOidcCallback.js +2 -4
  14. package/esm/core/handleOidcCallback.js.map +1 -1
  15. package/esm/core/loginOrGoToAuthServer.js +8 -2
  16. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  17. package/esm/core/oidcClientTsUserToTokens.js +7 -2
  18. package/esm/core/oidcClientTsUserToTokens.js.map +1 -1
  19. package/esm/keycloak/keycloak-js/Keycloak.d.ts +1 -3
  20. package/esm/keycloak/keycloak-js/Keycloak.js +31 -15
  21. package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
  22. package/esm/keycloak/keycloak-js/types.d.ts +1 -3
  23. package/esm/mock/oidc.js +2 -1
  24. package/esm/mock/oidc.js.map +1 -1
  25. package/esm/tools/workerTimers.js +1 -1
  26. package/esm/tools/workerTimers.js.map +1 -1
  27. package/esm/vendor/frontend/oidc-client-ts.js +46 -8
  28. package/keycloak/keycloak-js/Keycloak.d.ts +1 -3
  29. package/keycloak/keycloak-js/Keycloak.js +31 -15
  30. package/keycloak/keycloak-js/Keycloak.js.map +1 -1
  31. package/keycloak/keycloak-js/types.d.ts +1 -3
  32. package/mock/oidc.js +2 -1
  33. package/mock/oidc.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/core/Oidc.ts +5 -1
  36. package/src/core/createOidc.ts +85 -17
  37. package/src/core/handleOidcCallback.ts +2 -5
  38. package/src/core/loginOrGoToAuthServer.ts +9 -2
  39. package/src/core/oidcClientTsUserToTokens.ts +7 -2
  40. package/src/keycloak/keycloak-js/Keycloak.ts +37 -10
  41. package/src/keycloak/keycloak-js/types.ts +1 -4
  42. package/src/mock/oidc.ts +2 -1
  43. package/src/tools/workerTimers.ts +1 -1
  44. package/tools/workerTimers.js +1 -1
  45. package/tools/workerTimers.js.map +1 -1
  46. package/vendor/frontend/oidc-client-ts.js +46 -8
@@ -970,6 +970,8 @@ export async function createOidc_nonMemoized<
970
970
 
971
971
  let wouldHaveAutoLoggedOutIfBrowserWasOnline = false;
972
972
 
973
+ let prOngoingTokenRenewal: Promise<void> | undefined = undefined;
974
+
973
975
  const oidc_loggedIn = id<Oidc.LoggedIn<DecodedIdToken>>({
974
976
  ...oidc_common,
975
977
  isUserLoggedIn: true,
@@ -979,10 +981,19 @@ export async function createOidc_nonMemoized<
979
981
  assert(false);
980
982
  }
981
983
 
984
+ if (prOngoingTokenRenewal === undefined) {
985
+ // NOTE: Give a chance to renewOnLocalTimeShift to do it's job
986
+ await new Promise<void>(resolve => setTimeout(resolve, 0));
987
+ }
988
+
989
+ if (prOngoingTokenRenewal !== undefined) {
990
+ await prOngoingTokenRenewal;
991
+ }
992
+
982
993
  renew_tokens: {
983
994
  {
984
995
  const msBeforeExpirationOfTheAccessToken =
985
- currentTokens.accessTokenExpirationTime - Date.now();
996
+ currentTokens.accessTokenExpirationTime - currentTokens.getServerDateNow();
986
997
 
987
998
  if (msBeforeExpirationOfTheAccessToken > 30_000) {
988
999
  break renew_tokens;
@@ -990,7 +1001,8 @@ export async function createOidc_nonMemoized<
990
1001
  }
991
1002
 
992
1003
  {
993
- const msElapsedSinceCurrentTokenWereIssued = Date.now() - currentTokens.issuedAtTime;
1004
+ const msElapsedSinceCurrentTokenWereIssued =
1005
+ currentTokens.getServerDateNow() - currentTokens.issuedAtTime;
994
1006
 
995
1007
  if (msElapsedSinceCurrentTokenWereIssued < 5_000) {
996
1008
  break renew_tokens;
@@ -1029,7 +1041,10 @@ export async function createOidc_nonMemoized<
1029
1041
  prUnlock: new Promise<never>(() => {})
1030
1042
  });
1031
1043
 
1032
- window.addEventListener("pageshow", () => {
1044
+ window.addEventListener("pageshow", event => {
1045
+ if (!event.persisted) {
1046
+ return;
1047
+ }
1033
1048
  location.reload();
1034
1049
  });
1035
1050
 
@@ -1073,6 +1088,7 @@ export async function createOidc_nonMemoized<
1073
1088
  return new Promise<never>(() => {});
1074
1089
  },
1075
1090
  renewTokens: (() => {
1091
+ // NOTE: Cannot throw (or if it does it's our fault)
1076
1092
  async function renewTokens_nonMutexed(params: {
1077
1093
  extraTokenParams: Record<string, string | undefined>;
1078
1094
  }) {
@@ -1228,12 +1244,12 @@ export async function createOidc_nonMemoized<
1228
1244
  }
1229
1245
  | undefined = undefined;
1230
1246
 
1231
- function handleFinally() {
1247
+ function handleThen() {
1232
1248
  assert(ongoingCall !== undefined, "131276");
1233
1249
 
1234
1250
  const { pr } = ongoingCall;
1235
1251
 
1236
- pr.finally(() => {
1252
+ pr.then(() => {
1237
1253
  assert(ongoingCall !== undefined, "549462");
1238
1254
 
1239
1255
  if (ongoingCall.pr !== pr) {
@@ -1244,8 +1260,10 @@ export async function createOidc_nonMemoized<
1244
1260
  });
1245
1261
  }
1246
1262
 
1247
- return async params => {
1248
- const { extraTokenParams: extraTokenParams_local } = params ?? {};
1263
+ async function renewTokens_mutexed(params: {
1264
+ extraTokenParams?: Record<string, string | undefined>;
1265
+ }) {
1266
+ const { extraTokenParams: extraTokenParams_local } = params;
1249
1267
 
1250
1268
  const extraTokenParams = {
1251
1269
  ...getExtraTokenParams?.(),
@@ -1258,7 +1276,7 @@ export async function createOidc_nonMemoized<
1258
1276
  extraTokenParams
1259
1277
  };
1260
1278
 
1261
- handleFinally();
1279
+ handleThen();
1262
1280
 
1263
1281
  return ongoingCall.pr;
1264
1282
  }
@@ -1269,18 +1287,28 @@ export async function createOidc_nonMemoized<
1269
1287
 
1270
1288
  ongoingCall = {
1271
1289
  pr: (async () => {
1272
- try {
1273
- await ongoingCall.pr;
1274
- } catch {}
1290
+ await ongoingCall.pr;
1275
1291
 
1276
1292
  return renewTokens_nonMutexed({ extraTokenParams });
1277
1293
  })(),
1278
1294
  extraTokenParams
1279
1295
  };
1280
1296
 
1281
- handleFinally();
1297
+ handleThen();
1282
1298
 
1283
1299
  return ongoingCall.pr;
1300
+ }
1301
+
1302
+ return params => {
1303
+ const { extraTokenParams } = params ?? {};
1304
+
1305
+ prOngoingTokenRenewal = renewTokens_mutexed({ extraTokenParams });
1306
+
1307
+ prOngoingTokenRenewal.then(() => {
1308
+ prOngoingTokenRenewal = undefined;
1309
+ });
1310
+
1311
+ return prOngoingTokenRenewal;
1284
1312
  };
1285
1313
  })(),
1286
1314
  subscribeToTokensChange: onTokenChange => {
@@ -1335,6 +1363,50 @@ export async function createOidc_nonMemoized<
1335
1363
  });
1336
1364
  }
1337
1365
 
1366
+ // NOTE: Pessimistic renewal of token on potential clock adjustment.
1367
+ (function renewOnLocalTimeShift() {
1368
+ // NOTE: If we can't confidently silently refresh tokens we won't risk reloading
1369
+ // the page just to cover the local time drift edge case.
1370
+ if (!currentTokens.hasRefreshToken && !canUseIframe) {
1371
+ return;
1372
+ }
1373
+
1374
+ let timer: ReturnType<typeof setTimeout> | undefined = undefined;
1375
+
1376
+ const DELAY = 5_000;
1377
+
1378
+ (async () => {
1379
+ while (true) {
1380
+ const before = Date.now();
1381
+ await new Promise<void>(resolve => {
1382
+ timer = setTimeout(resolve, DELAY);
1383
+ });
1384
+ const after = Date.now();
1385
+
1386
+ const elapsed_measured = after - before;
1387
+ const elapsed_theoretical = DELAY;
1388
+
1389
+ if (Math.abs(elapsed_measured - elapsed_theoretical) > 1_000) {
1390
+ log?.("Renewing token now as local time might have shifted");
1391
+ // NOTE: This **will** happen, even if there is no local time drift.
1392
+ // For example when the computer wakes up after sleep.
1393
+ // But it doesn't matter, we'll just make a token renewal that was probably
1394
+ // not necessary. It's best than risking to deem expired token as valid.
1395
+ oidc_loggedIn.renewTokens();
1396
+ return;
1397
+ }
1398
+ }
1399
+ })();
1400
+
1401
+ const { unsubscribe: tokenChangeUnsubscribe } = oidc_loggedIn.subscribeToTokensChange(() => {
1402
+ if (timer !== undefined) {
1403
+ clearTimeout(timer);
1404
+ }
1405
+ tokenChangeUnsubscribe();
1406
+ renewOnLocalTimeShift();
1407
+ });
1408
+ })();
1409
+
1338
1410
  (function scheduleRenew() {
1339
1411
  if (!currentTokens.hasRefreshToken && !canUseIframe) {
1340
1412
  log?.(
@@ -1348,7 +1420,7 @@ export async function createOidc_nonMemoized<
1348
1420
 
1349
1421
  const msBeforeExpiration =
1350
1422
  (currentTokens.refreshTokenExpirationTime ?? currentTokens.accessTokenExpirationTime) -
1351
- Date.now();
1423
+ currentTokens.getServerDateNow();
1352
1424
 
1353
1425
  const typeOfTheTokenWeGotTheTtlFrom =
1354
1426
  currentTokens.refreshTokenExpirationTime !== undefined ? "refresh" : "access";
@@ -1356,10 +1428,6 @@ export async function createOidc_nonMemoized<
1356
1428
  const RENEW_MS_BEFORE_EXPIRES = 30_000;
1357
1429
 
1358
1430
  if (msBeforeExpiration <= RENEW_MS_BEFORE_EXPIRES) {
1359
- // NOTE: We just got a new token that is about to expire. This means that
1360
- // the refresh token has reached it's max SSO time.
1361
- // ...or that the refresh token have a very short lifespan...
1362
- // anyway, no need to keep alive, it will probably redirect on the next getTokens() or refreshTokens() call
1363
1431
  log?.(
1364
1432
  [
1365
1433
  "Disabling auto renew mechanism. We just got fresh tokens",
@@ -278,11 +278,8 @@ export function retrieveRedirectAuthResponseAndStateData(params: {
278
278
  }
279
279
 
280
280
  function reloadOnBfCacheNavigation() {
281
- const start = Date.now();
282
- window.addEventListener("pageshow", () => {
283
- const elapsed = Date.now() - start;
284
-
285
- if (elapsed < 100) {
281
+ window.addEventListener("pageshow", event => {
282
+ if (!event.persisted) {
286
283
  return;
287
284
  }
288
285
  location.reload();
@@ -124,7 +124,10 @@ export function createLoginOrGoToAuthServer(params: {
124
124
 
125
125
  bf_cache_handling: {
126
126
  if (rest.doForceReloadOnBfCache) {
127
- window.removeEventListener("pageshow", () => {
127
+ window.removeEventListener("pageshow", event => {
128
+ if (!event.persisted) {
129
+ return;
130
+ }
128
131
  location.reload();
129
132
  });
130
133
  break bf_cache_handling;
@@ -132,7 +135,11 @@ export function createLoginOrGoToAuthServer(params: {
132
135
 
133
136
  localStorage.setItem(LOCAL_STORAGE_KEY_TO_CLEAR_WHEN_USER_LOGGED_IN, "true");
134
137
 
135
- const callback = () => {
138
+ const callback = (event: { persisted: boolean }) => {
139
+ if (!event.persisted) {
140
+ return;
141
+ }
142
+
136
143
  window.removeEventListener("pageshow", callback);
137
144
 
138
145
  log?.(
@@ -75,7 +75,8 @@ export function oidcClientTsUserToTokens<DecodedIdToken extends Record<string, u
75
75
 
76
76
  const issuedAtTime = (() => {
77
77
  // NOTE: The id_token is always a JWT as per the protocol.
78
- // We don't use Date.now() due to network latency.
78
+ // We don't use Date.now() due to network latency or if the
79
+ // local clock is inaccurate.
79
80
  const id_token_iat = (() => {
80
81
  let iat: number | undefined;
81
82
 
@@ -159,7 +160,11 @@ export function oidcClientTsUserToTokens<DecodedIdToken extends Record<string, u
159
160
  idToken,
160
161
  decodedIdToken,
161
162
  decodedIdToken_original,
162
- issuedAtTime
163
+ issuedAtTime,
164
+ getServerDateNow: (() => {
165
+ const issuedAtTime_local = oidcClientTsUser.__oidc_spa_localTimeWhenTokenIssued;
166
+ return () => Date.now() + (issuedAtTime - issuedAtTime_local);
167
+ })()
163
168
  };
164
169
 
165
170
  const tokens: Oidc.Tokens<DecodedIdToken> =
@@ -330,7 +330,7 @@ export class Keycloak {
330
330
 
331
331
  if (!oidc.isUserLoggedIn) {
332
332
  console.warn(
333
- "Trying to read keycloak.realAccess when keycloak.realmAccess is false is a logical error in your application"
333
+ "Trying to read keycloak.realAccess when keycloak.authenticated is false is a logical error in your application"
334
334
  );
335
335
  return undefined;
336
336
  }
@@ -389,7 +389,7 @@ export class Keycloak {
389
389
 
390
390
  if (!oidc.isUserLoggedIn) {
391
391
  console.warn(
392
- "Trying to read keycloak.token when keycloak.token is false is a logical error in your application"
392
+ "Trying to read keycloak.token when keycloak.authenticated is false is a logical error in your application"
393
393
  );
394
394
  return undefined;
395
395
  }
@@ -423,7 +423,7 @@ export class Keycloak {
423
423
 
424
424
  if (!oidc.isUserLoggedIn) {
425
425
  console.warn(
426
- "Trying to read keycloak.token when keycloak.tokenParsed is false is a logical error in your application"
426
+ "Trying to read keycloak.tokenParsed when keycloak.authenticated is false is a logical error in your application"
427
427
  );
428
428
  return undefined;
429
429
  }
@@ -451,7 +451,7 @@ export class Keycloak {
451
451
 
452
452
  if (!oidc.isUserLoggedIn) {
453
453
  console.warn(
454
- "Trying to read keycloak.token when keycloak.refreshToken is false is a logical error in your application"
454
+ "Trying to read keycloak.refreshToken when keycloak.authenticated is false is a logical error in your application"
455
455
  );
456
456
  return undefined;
457
457
  }
@@ -485,7 +485,7 @@ export class Keycloak {
485
485
 
486
486
  if (!oidc.isUserLoggedIn) {
487
487
  console.warn(
488
- "Trying to read keycloak.token when keycloak.refreshTokenParsed is false is a logical error in your application"
488
+ "Trying to read keycloak.refreshTokenParsed when keycloak.authenticated is false is a logical error in your application"
489
489
  );
490
490
  return undefined;
491
491
  }
@@ -517,7 +517,7 @@ export class Keycloak {
517
517
 
518
518
  if (!oidc.isUserLoggedIn) {
519
519
  console.warn(
520
- "Trying to read keycloak.token when keycloak.token is false is a logical error in your application"
520
+ "Trying to read keycloak.idToken when keycloak.authenticated is false is a logical error in your application"
521
521
  );
522
522
  return undefined;
523
523
  }
@@ -551,7 +551,7 @@ export class Keycloak {
551
551
 
552
552
  if (!oidc.isUserLoggedIn) {
553
553
  console.warn(
554
- "Trying to read keycloak.token when keycloak.refreshTokenParsed is false is a logical error in your application"
554
+ "Trying to read keycloak.idTokenParsed when keycloak.authenticated is false is a logical error in your application"
555
555
  );
556
556
  return undefined;
557
557
  }
@@ -566,10 +566,37 @@ export class Keycloak {
566
566
  * The estimated time difference between the browser time and the Keycloak
567
567
  * server in seconds. This value is just an estimation, but is accurate
568
568
  * enough when determining if a token is expired or not.
569
- *
570
- * NOTE oidc-spa: Not supported.
571
569
  */
572
- timeSkew = null;
570
+ get timeSkew(): number | null {
571
+ const internalState = internalStateByInstance.get(this);
572
+
573
+ assert(internalState !== undefined);
574
+
575
+ if (!this.didInitialize) {
576
+ const { timeSkew } = internalState.initOptions ?? {};
577
+
578
+ if (timeSkew === undefined) {
579
+ return null;
580
+ }
581
+
582
+ return timeSkew;
583
+ }
584
+
585
+ const { oidc, tokens } = internalState;
586
+
587
+ assert(oidc !== undefined);
588
+
589
+ if (!oidc.isUserLoggedIn) {
590
+ console.warn(
591
+ "Trying to read keycloak.timeSkew when keycloak.authenticated is false is a logical error in your application"
592
+ );
593
+ return null;
594
+ }
595
+
596
+ assert(tokens !== undefined);
597
+
598
+ return Math.ceil((tokens.getServerDateNow() - Date.now()) / 1000);
599
+ }
573
600
 
574
601
  /**
575
602
  * Whether the instance has been initialized by calling `.init()`.
@@ -139,11 +139,8 @@ export interface KeycloakInitOptions {
139
139
  /**
140
140
  * Set an initial value for skew between local time and Keycloak server in
141
141
  * seconds (only together with `token` or `refreshToken`).
142
- *
143
- * NOTE oidc-spa: Not supported
144
142
  */
145
- //timeSkew?: number;
146
- timeSkew?: undefined;
143
+ timeSkew?: number;
147
144
 
148
145
  /**
149
146
  * Set to enable/disable monitoring login state.
package/src/mock/oidc.ts CHANGED
@@ -151,7 +151,8 @@ export async function createMockOidc<
151
151
  "See https://docs.oidc-spa.dev/v/v7/mock"
152
152
  ].join("\n")
153
153
  }),
154
- issuedAtTime: Date.now()
154
+ issuedAtTime: Date.now(),
155
+ getServerDateNow: () => Date.now()
155
156
  };
156
157
 
157
158
  const tokens: Oidc.Tokens<DecodedIdToken> =
@@ -34,7 +34,7 @@ export function setTimeout(callback: () => void, delay: number): TimerHandle {
34
34
 
35
35
  const elapsed = Date.now() - start;
36
36
 
37
- if (elapsed < delay) {
37
+ if (0 <= elapsed && elapsed < delay) {
38
38
  timerHandle_n = workerTimers.setTimeout(callback_actual, delay - elapsed);
39
39
  } else {
40
40
  callback_actual();
@@ -21,7 +21,7 @@ function setTimeout(callback, delay) {
21
21
  const onPageshow = () => {
22
22
  worker_timers_1.workerTimers.clearTimeout(timerHandle_n);
23
23
  const elapsed = Date.now() - start;
24
- if (elapsed < delay) {
24
+ if (0 <= elapsed && elapsed < delay) {
25
25
  timerHandle_n = worker_timers_1.workerTimers.setTimeout(callback_actual, delay - elapsed);
26
26
  }
27
27
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"workerTimers.js","sourceRoot":"","sources":["../src/tools/workerTimers.ts"],"names":[],"mappings":";;AAQA,gCAsCC;AAED,oCAQC;AAxDD,oEAAgE;AAMhE,MAAM,kBAAkB,GAAG,IAAI,OAAO,EAA2B,CAAC;AAElE,SAAgB,UAAU,CAAC,QAAoB,EAAE,KAAa;IAC1D,MAAM,eAAe,GAAG,GAAG,EAAE;QACzB,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAEnD,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvC,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,aAAa,GAAG,4BAAY,CAAC,UAAU,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IAEpE,MAAM,WAAW,GAAgB,EAAS,CAAC;IAE3C,kBAAkB,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE;QACrC,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvC,4BAAY,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAEzC,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,MAAM,UAAU,GAAG,GAAG,EAAE;QACpB,4BAAY,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAEnC,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;YAClB,aAAa,GAAG,4BAAY,CAAC,UAAU,CAAC,eAAe,EAAE,KAAK,GAAG,OAAO,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACJ,eAAe,EAAE,CAAC;QACtB,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAEhD,OAAO,WAAW,CAAC;AACvB,CAAC;AAED,SAAgB,YAAY,CAAC,MAAmB;IAC5C,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE7C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;IACX,CAAC;IAED,KAAK,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"workerTimers.js","sourceRoot":"","sources":["../src/tools/workerTimers.ts"],"names":[],"mappings":";;AAQA,gCAsCC;AAED,oCAQC;AAxDD,oEAAgE;AAMhE,MAAM,kBAAkB,GAAG,IAAI,OAAO,EAA2B,CAAC;AAElE,SAAgB,UAAU,CAAC,QAAoB,EAAE,KAAa;IAC1D,MAAM,eAAe,GAAG,GAAG,EAAE;QACzB,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAEnD,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvC,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,aAAa,GAAG,4BAAY,CAAC,UAAU,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IAEpE,MAAM,WAAW,GAAgB,EAAS,CAAC;IAE3C,kBAAkB,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE;QACrC,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvC,4BAAY,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAEzC,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,MAAM,UAAU,GAAG,GAAG,EAAE;QACpB,4BAAY,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAEnC,IAAI,CAAC,IAAI,OAAO,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;YAClC,aAAa,GAAG,4BAAY,CAAC,UAAU,CAAC,eAAe,EAAE,KAAK,GAAG,OAAO,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACJ,eAAe,EAAE,CAAC;QACtB,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAEhD,OAAO,WAAW,CAAC;AACvB,CAAC;AAED,SAAgB,YAAY,CAAC,MAAmB;IAC5C,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE7C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;IACX,CAAC;IAED,KAAK,EAAE,CAAC;AACZ,CAAC"}
@@ -1182,6 +1182,7 @@ var UserInfoService = class {
1182
1182
  };
1183
1183
 
1184
1184
  // src/TokenClient.ts
1185
+ var localTimeByResponse = /* @__PURE__ */ new WeakMap();
1185
1186
  var TokenClient = class {
1186
1187
  constructor(_settings, _metadataService) {
1187
1188
  this._settings = _settings;
@@ -1240,6 +1241,7 @@ var TokenClient = class {
1240
1241
  }
1241
1242
  const url = await this._metadataService.getTokenEndpoint(false);
1242
1243
  logger2.debug("got token endpoint");
1244
+ const timeBefore = Date.now();
1243
1245
  const response = await this._jsonService.postForm(url, {
1244
1246
  body: params,
1245
1247
  basicAuth,
@@ -1247,6 +1249,8 @@ var TokenClient = class {
1247
1249
  initCredentials: this._settings.fetchRequestCredentials,
1248
1250
  extraHeaders
1249
1251
  });
1252
+ const timeAfter = Date.now();
1253
+ localTimeByResponse.set(response, Math.floor((timeBefore + timeAfter) / 2));
1250
1254
  logger2.debug("got response");
1251
1255
  return response;
1252
1256
  }
@@ -1293,7 +1297,10 @@ var TokenClient = class {
1293
1297
  }
1294
1298
  const url = await this._metadataService.getTokenEndpoint(false);
1295
1299
  logger2.debug("got token endpoint");
1300
+ const timeBefore = Date.now();
1296
1301
  const response = await this._jsonService.postForm(url, { body: params, basicAuth, timeoutInSeconds: this._settings.requestTimeoutInSeconds, initCredentials: this._settings.fetchRequestCredentials });
1302
+ const timeAfter = Date.now();
1303
+ localTimeByResponse.set(response, Math.floor((timeBefore + timeAfter) / 2));
1297
1304
  logger2.debug("got response");
1298
1305
  return response;
1299
1306
  }
@@ -1343,7 +1350,10 @@ var TokenClient = class {
1343
1350
  }
1344
1351
  const url = await this._metadataService.getTokenEndpoint(false);
1345
1352
  logger2.debug("got token endpoint");
1353
+ const timeBefore = Date.now();
1346
1354
  const response = await this._jsonService.postForm(url, { body: params, basicAuth, timeoutInSeconds, initCredentials: this._settings.fetchRequestCredentials, extraHeaders });
1355
+ const timeAfter = Date.now();
1356
+ localTimeByResponse.set(response, Math.floor((timeBefore + timeAfter) / 2));
1347
1357
  logger2.debug("got response");
1348
1358
  return response;
1349
1359
  }
@@ -1498,6 +1508,13 @@ var ResponseValidator = class {
1498
1508
  });
1499
1509
  Object.assign(response, tokenResponse);
1500
1510
  response.__oidc_spa_tokenResponse = tokenResponse;
1511
+ response.__oidc_spa_localTimeWhenTokenIssued = (() => {
1512
+ const time = localTimeByResponse.get(tokenResponse);
1513
+ if (time === void 0) {
1514
+ throw new Error("oidc-spa error in oidc-client-ts");
1515
+ }
1516
+ return time;
1517
+ })();
1501
1518
  } else {
1502
1519
  logger2.debug("No code to process");
1503
1520
  }
@@ -1782,6 +1799,7 @@ var SigninResponse = class {
1782
1799
  this.error_uri = params.get("error_uri");
1783
1800
  this.code = params.get("code");
1784
1801
  this.__oidc_spa_tokenResponse = void 0;
1802
+ this.__oidc_spa_localTimeWhenTokenIssued = void 0;
1785
1803
  }
1786
1804
  get expires_in() {
1787
1805
  if (this.expires_at === void 0) {
@@ -2068,6 +2086,13 @@ var OidcClient = class {
2068
2086
  const signinResponse = new SigninResponse(new URLSearchParams());
2069
2087
  Object.assign(signinResponse, tokenResponse);
2070
2088
  signinResponse.__oidc_spa_tokenResponse = tokenResponse;
2089
+ signinResponse.__oidc_spa_localTimeWhenTokenIssued = (() => {
2090
+ const time = localTimeByResponse.get(tokenResponse);
2091
+ if (time === void 0) {
2092
+ throw new Error("oidc-spa error in oidc-client-ts");
2093
+ }
2094
+ return time;
2095
+ })();
2071
2096
  await this._validator.validateCredentialsResponse(signinResponse, skipUserInfo);
2072
2097
  return signinResponse;
2073
2098
  }
@@ -2125,6 +2150,13 @@ var OidcClient = class {
2125
2150
  const response = new SigninResponse(new URLSearchParams());
2126
2151
  Object.assign(response, result);
2127
2152
  response.__oidc_spa_tokenResponse = result;
2153
+ response.__oidc_spa_localTimeWhenTokenIssued = (() => {
2154
+ const time = localTimeByResponse.get(result);
2155
+ if (time === void 0) {
2156
+ throw new Error("oidc-spa error in oidc-client-ts");
2157
+ }
2158
+ return time;
2159
+ })();
2128
2160
  logger2.debug("validating response", response);
2129
2161
  await this._validator.validateRefreshResponse(response, {
2130
2162
  ...state,
@@ -2356,6 +2388,7 @@ var User = class _User {
2356
2388
  this.state = args.userState;
2357
2389
  this.url_state = args.url_state;
2358
2390
  this.__oidc_spa_tokenResponse = args.__oidc_spa_tokenResponse;
2391
+ this.__oidc_spa_localTimeWhenTokenIssued = args.__oidc_spa_localTimeWhenTokenIssued;
2359
2392
  }
2360
2393
  /** Computed number of seconds the access token has remaining. */
2361
2394
  get expires_in() {
@@ -2393,7 +2426,8 @@ var User = class _User {
2393
2426
  scope: this.scope,
2394
2427
  profile: this.profile,
2395
2428
  expires_at: this.expires_at,
2396
- __oidc_spa_tokenResponse: this.__oidc_spa_tokenResponse
2429
+ __oidc_spa_tokenResponse: this.__oidc_spa_tokenResponse,
2430
+ __oidc_spa_localTimeWhenTokenIssued: this.__oidc_spa_localTimeWhenTokenIssued
2397
2431
  });
2398
2432
  }
2399
2433
  static fromStorageString(storageString) {
@@ -3150,12 +3184,15 @@ var UserManager = class {
3150
3184
  timeoutInSeconds: this.settings.silentRequestTimeoutInSeconds,
3151
3185
  ...args
3152
3186
  });
3153
- if (response.__oidc_spa_tokenResponse === void 0) {
3154
- throw new Error(
3155
- "Wrong Assertion Encountered: Error in oidc-spa mod of oidc-client-ts"
3156
- );
3187
+ if (response.__oidc_spa_tokenResponse === void 0 || response.__oidc_spa_localTimeWhenTokenIssued === void 0) {
3188
+ throw new Error("Wrong Assertion Encountered: Error in oidc-spa mod of oidc-client-ts");
3157
3189
  }
3158
- const user = new User({ ...args.state, ...response, __oidc_spa_tokenResponse: response.__oidc_spa_tokenResponse });
3190
+ const user = new User({
3191
+ ...args.state,
3192
+ ...response,
3193
+ __oidc_spa_tokenResponse: response.__oidc_spa_tokenResponse,
3194
+ __oidc_spa_localTimeWhenTokenIssued: response.__oidc_spa_localTimeWhenTokenIssued
3195
+ });
3159
3196
  await this.storeUser(user);
3160
3197
  await this._events.load(user);
3161
3198
  return user;
@@ -3318,14 +3355,15 @@ var UserManager = class {
3318
3355
  }
3319
3356
  async _buildUser(signinResponse, verifySub) {
3320
3357
  const logger2 = this._logger.create("_buildUser");
3321
- if (signinResponse.__oidc_spa_tokenResponse === void 0) {
3358
+ if (signinResponse.__oidc_spa_tokenResponse === void 0 || signinResponse.__oidc_spa_localTimeWhenTokenIssued === void 0) {
3322
3359
  throw new Error(
3323
3360
  "Wrong Assertion Encountered: Error in oidc-spa mod of oidc-client-ts"
3324
3361
  );
3325
3362
  }
3326
3363
  const user = new User({
3327
3364
  ...signinResponse,
3328
- __oidc_spa_tokenResponse: signinResponse.__oidc_spa_tokenResponse
3365
+ __oidc_spa_tokenResponse: signinResponse.__oidc_spa_tokenResponse,
3366
+ __oidc_spa_localTimeWhenTokenIssued: signinResponse.__oidc_spa_localTimeWhenTokenIssued
3329
3367
  });
3330
3368
  if (verifySub) {
3331
3369
  if (verifySub !== user.profile.sub) {