oidc-spa 6.15.1 → 7.0.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 (39) hide show
  1. package/README.md +12 -13
  2. package/core/Oidc.d.ts +24 -12
  3. package/core/createOidc.d.ts +15 -30
  4. package/core/createOidc.js +131 -123
  5. package/core/createOidc.js.map +1 -1
  6. package/core/handleOidcCallback.js +2 -29
  7. package/core/handleOidcCallback.js.map +1 -1
  8. package/core/loginOrGoToAuthServer.d.ts +1 -2
  9. package/core/loginOrGoToAuthServer.js +10 -10
  10. package/core/loginOrGoToAuthServer.js.map +1 -1
  11. package/core/loginSilent.d.ts +1 -1
  12. package/core/loginSilent.js +4 -4
  13. package/core/loginSilent.js.map +1 -1
  14. package/core/oidcClientTsUserToTokens.d.ts +1 -2
  15. package/core/oidcClientTsUserToTokens.js +93 -58
  16. package/core/oidcClientTsUserToTokens.js.map +1 -1
  17. package/mock/oidc.d.ts +1 -1
  18. package/mock/oidc.js +29 -19
  19. package/mock/oidc.js.map +1 -1
  20. package/package.json +1 -5
  21. package/react/react.d.ts +1 -7
  22. package/react/react.js +8 -59
  23. package/react/react.js.map +1 -1
  24. package/src/core/Oidc.ts +27 -14
  25. package/src/core/createOidc.ts +121 -119
  26. package/src/core/handleOidcCallback.ts +2 -55
  27. package/src/core/loginOrGoToAuthServer.ts +10 -11
  28. package/src/core/loginSilent.ts +4 -4
  29. package/src/core/oidcClientTsUserToTokens.ts +129 -82
  30. package/src/mock/oidc.ts +16 -6
  31. package/src/react/react.tsx +11 -72
  32. package/src/tools/readExpirationTimeInJwt.ts +4 -5
  33. package/tools/readExpirationTimeInJwt.js +4 -4
  34. package/tools/readExpirationTimeInJwt.js.map +1 -1
  35. package/vendor/frontend/oidc-client-ts-and-jwt-decode.js +1 -1
  36. package/core/debug966975.d.ts +0 -7
  37. package/core/debug966975.js +0 -88
  38. package/core/debug966975.js.map +0 -1
  39. package/src/core/debug966975.ts +0 -85
@@ -8,7 +8,6 @@ import type { OidcMetadata } from "./OidcMetadata";
8
8
  import { id, assert, is, type Equals } from "../vendor/frontend/tsafe";
9
9
  import { setTimeout, clearTimeout } from "../tools/workerTimers";
10
10
  import { Deferred } from "../tools/Deferred";
11
- import { decodeJwt } from "../tools/decodeJwt";
12
11
  import { createEvtIsUserActive } from "./evtIsUserActive";
13
12
  import { createStartCountdown } from "../tools/startCountdown";
14
13
  import { toHumanReadableDuration } from "../tools/toHumanReadableDuration";
@@ -23,7 +22,7 @@ import { type StateData, generateStateQueryParamValue, STATE_STORE_KEY_PREFIX }
23
22
  import { notifyOtherTabsOfLogout, getPrOtherTabLogout } from "./logoutPropagationToOtherTabs";
24
23
  import { notifyOtherTabsOfLogin, getPrOtherTabLogin } from "./loginPropagationToOtherTabs";
25
24
  import { getConfigId } from "./configId";
26
- import { oidcClientTsUserToTokens, getMsBeforeExpiration } from "./oidcClientTsUserToTokens";
25
+ import { oidcClientTsUserToTokens } from "./oidcClientTsUserToTokens";
27
26
  import { loginSilent } from "./loginSilent";
28
27
  import { authResponseToUrl } from "./AuthResponse";
29
28
  import { handleOidcCallback, retrieveRedirectAuthResponseAndStateData } from "./handleOidcCallback";
@@ -60,23 +59,14 @@ export type ParamsOfCreateOidc<
60
59
  * (the scope "openid" is added automatically as it's mandatory)
61
60
  **/
62
61
  scopes?: string[];
63
- /**
64
- * Transform the url of the authorization endpoint before redirecting to the login pages.
65
- */
66
- transformUrlBeforeRedirect?: (url: string) => string;
67
62
 
68
63
  /**
69
- * NOTE: Will replace transformUrlBeforeRedirect in the next major version.
70
- *
71
64
  * Transform the url (authorization endpoint) before redirecting to the login pages.
72
65
  *
73
66
  * The isSilent parameter is true when the redirect is initiated in the background iframe for silent signin.
74
67
  * This can be used to omit ui related query parameters (like `ui_locales`).
75
68
  */
76
- transformUrlBeforeRedirect_next?: (params: {
77
- authorizationUrl: string;
78
- isSilent: boolean;
79
- }) => string;
69
+ transformUrlBeforeRedirect?: (params: { authorizationUrl: string; isSilent: boolean }) => string;
80
70
 
81
71
  /**
82
72
  * Extra query params to be added to the authorization endpoint url before redirecting or silent signing in.
@@ -120,30 +110,10 @@ export type ParamsOfCreateOidc<
120
110
  */
121
111
  homeUrl: string;
122
112
 
123
- /**
124
- * WARNING: If you are deploying on the web, you should not set this parameter.
125
- * The callbackUrl is the homeURl.
126
- *
127
- * This is only useful for when you also shipping your app as a Desktop App with Electron.
128
- * NOTE that even in this case, it's not automatic, you still need to handle the response
129
- * in the electron node process.
130
- *
131
- * Example: __callbackUri: "myapp://oidc-callback/"
132
- */
133
- __callbackUri?: string;
113
+ decodedIdTokenSchema?: {
114
+ parse: (decodedIdToken_original: Oidc.Tokens.DecodedIdToken_base) => DecodedIdToken;
115
+ };
134
116
 
135
- decodedIdTokenSchema?: { parse: (data: unknown) => DecodedIdToken };
136
- /**
137
- * @deprecated: Use idleSessionLifetimeInSeconds instead
138
- *
139
- * This parameter defines after how many seconds of inactivity the user should be
140
- * logged out automatically.
141
- *
142
- * WARNING: It should be configured on the identity server side
143
- * as it's the authoritative source for security policies and not the client.
144
- * If you don't provide this parameter it will be inferred from the refresh token expiration time.
145
- * */
146
- __unsafe_ssoSessionIdleSeconds?: number;
147
117
  /**
148
118
  * This parameter defines after how many seconds of inactivity the user should be
149
119
  * logged out automatically.
@@ -154,6 +124,9 @@ export type ParamsOfCreateOidc<
154
124
  * */
155
125
  idleSessionLifetimeInSeconds?: number;
156
126
 
127
+ /**
128
+ * Default: { redirectTo: "current page" }
129
+ */
157
130
  autoLogoutParams?: Parameters<Oidc.LoggedIn<any>["logout"]>[0];
158
131
  autoLogin?: AutoLogin;
159
132
 
@@ -166,6 +139,16 @@ export type ParamsOfCreateOidc<
166
139
 
167
140
  debugLogs?: boolean;
168
141
 
142
+ /**
143
+ * WARNING: This option exists solely as a workaround
144
+ * for limitations in the Google OAuth API.
145
+ * See: https://docs.oidc-spa.dev/providers-configuration/google-oauth
146
+ *
147
+ * Do not use this for other providers.
148
+ * If you think you need a client secret in a SPA, you are likely
149
+ * trying to use a confidential (private) client in the browser,
150
+ * which is insecure and not supported.
151
+ */
169
152
  __unsafe_clientSecret?: string;
170
153
 
171
154
  /**
@@ -195,8 +178,6 @@ const globalContext = {
195
178
  evtRequestToPersistTokens: createEvt<{ configIdOfInstancePostingTheRequest: string }>()
196
179
  };
197
180
 
198
- const MIN_RENEW_BEFORE_EXPIRE_MS = 2_000;
199
-
200
181
  /** @see: https://docs.oidc-spa.dev/v/v6/usage */
201
182
  export async function createOidc<
202
183
  DecodedIdToken extends Record<string, unknown> = Record<string, unknown>,
@@ -296,15 +277,12 @@ export async function createOidc_nonMemoized<
296
277
  }
297
278
  ): Promise<AutoLogin extends true ? Oidc.LoggedIn<DecodedIdToken> : Oidc<DecodedIdToken>> {
298
279
  const {
299
- transformUrlBeforeRedirect_next,
300
280
  transformUrlBeforeRedirect,
301
281
  extraQueryParams: extraQueryParamsOrGetter,
302
282
  extraTokenParams: extraTokenParamsOrGetter,
303
283
  homeUrl: homeUrl_params,
304
- __callbackUri,
305
284
  decodedIdTokenSchema,
306
- __unsafe_ssoSessionIdleSeconds,
307
- idleSessionLifetimeInSeconds = __unsafe_ssoSessionIdleSeconds,
285
+ idleSessionLifetimeInSeconds,
308
286
  autoLogoutParams = { redirectTo: "current page" },
309
287
  autoLogin = false,
310
288
  postLoginRedirectUrl: postLoginRedirectUrl_default,
@@ -347,7 +325,7 @@ export async function createOidc_nonMemoized<
347
325
  });
348
326
 
349
327
  const callbackUri = toFullyQualifiedUrl({
350
- urlish: __callbackUri ?? homeUrl,
328
+ urlish: homeUrl,
351
329
  doAssertNoQueryParams: true,
352
330
  doOutputWithTrailingSlash: true
353
331
  });
@@ -476,7 +454,6 @@ export async function createOidc_nonMemoized<
476
454
  configId,
477
455
  oidcClientTsUserManager,
478
456
  transformUrlBeforeRedirect,
479
- transformUrlBeforeRedirect_next,
480
457
  getExtraQueryParams,
481
458
  getExtraTokenParams,
482
459
  homeUrl,
@@ -675,7 +652,7 @@ export async function createOidc_nonMemoized<
675
652
  oidcClientTsUserManager,
676
653
  stateQueryParamValue_instance,
677
654
  configId,
678
- transformUrlBeforeRedirect_next,
655
+ transformUrlBeforeRedirect,
679
656
  getExtraQueryParams,
680
657
  getExtraTokenParams,
681
658
  autoLogin
@@ -966,18 +943,33 @@ export async function createOidc_nonMemoized<
966
943
 
967
944
  const onTokenChanges = new Set<(tokens: Oidc.Tokens<DecodedIdToken>) => void>();
968
945
 
969
- const { sid: sessionId, sub: subjectId } = decodeJwt<{ sid?: string; sub?: string }>(
970
- currentTokens.idToken
971
- );
946
+ const { sid: sessionId, sub: subjectId } = currentTokens.decodedIdToken_original;
972
947
 
973
948
  assert(subjectId !== undefined, "The 'sub' claim is missing from the id token");
949
+ assert(sessionId === undefined || typeof sessionId === "string");
974
950
 
975
951
  const oidc_loggedIn = id<Oidc.LoggedIn<DecodedIdToken>>({
976
952
  ...oidc_common,
977
953
  isUserLoggedIn: true,
978
- getTokens: () => currentTokens,
979
- getTokens_next: async () => {
980
- if (getMsBeforeExpiration(currentTokens) <= MIN_RENEW_BEFORE_EXPIRE_MS) {
954
+ getTokens: async () => {
955
+ renew_tokens: {
956
+ {
957
+ const msBeforeExpirationOfTheAccessToken =
958
+ currentTokens.accessTokenExpirationTime - Date.now();
959
+
960
+ if (msBeforeExpirationOfTheAccessToken > 30_000) {
961
+ break renew_tokens;
962
+ }
963
+ }
964
+
965
+ {
966
+ const msElapsedSinceCurrentTokenWereIssued = Date.now() - currentTokens.issuedAtTime;
967
+
968
+ if (msElapsedSinceCurrentTokenWereIssued < 5_000) {
969
+ break renew_tokens;
970
+ }
971
+ }
972
+
981
973
  await oidc_loggedIn.renewTokens();
982
974
  }
983
975
 
@@ -1059,17 +1051,42 @@ export async function createOidc_nonMemoized<
1059
1051
  }) {
1060
1052
  const { extraTokenParams } = params;
1061
1053
 
1054
+ const fallbackToFullPageReload = async (): Promise<never> => {
1055
+ persistAuthState({ configId, state: undefined });
1056
+
1057
+ await waitForAllOtherOngoingLoginOrRefreshProcessesToComplete({
1058
+ prUnlock: new Promise<never>(() => {})
1059
+ });
1060
+
1061
+ globalContext.evtRequestToPersistTokens.post({
1062
+ configIdOfInstancePostingTheRequest: configId
1063
+ });
1064
+
1065
+ await loginOrGoToAuthServer({
1066
+ action: "login",
1067
+ redirectUrl: window.location.href,
1068
+ doForceReloadOnBfCache: true,
1069
+ extraQueryParams_local: undefined,
1070
+ transformUrlBeforeRedirect_local: undefined,
1071
+ doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
1072
+ interaction: "directly redirect if active session show login otherwise"
1073
+ });
1074
+ assert(false, "136134");
1075
+ };
1076
+
1062
1077
  if (!currentTokens.hasRefreshToken && !canUseIframe) {
1063
- const message = [
1064
- "Unable to refresh tokens without a full app reload,",
1065
- "because no refresh token is available",
1066
- "and your app setup prevents silent sign-in via iframe.",
1067
- "Your only option to refresh tokens is to call `window.location.reload()`"
1068
- ].join(" ");
1078
+ log?.(
1079
+ [
1080
+ "Unable to refresh tokens without a full app reload,",
1081
+ "because no refresh token is available",
1082
+ "and your app setup prevents silent sign-in via iframe.",
1083
+ "Your only option to refresh tokens is to call `window.location.reload()`"
1084
+ ].join(" ")
1085
+ );
1069
1086
 
1070
- log?.(message);
1087
+ await fallbackToFullPageReload();
1071
1088
 
1072
- throw new Error(message);
1089
+ assert(false, "136135");
1073
1090
  }
1074
1091
 
1075
1092
  log?.("Renewing tokens");
@@ -1080,7 +1097,7 @@ export async function createOidc_nonMemoized<
1080
1097
  oidcClientTsUserManager,
1081
1098
  stateQueryParamValue_instance,
1082
1099
  configId,
1083
- transformUrlBeforeRedirect_next,
1100
+ transformUrlBeforeRedirect,
1084
1101
  getExtraQueryParams,
1085
1102
  getExtraTokenParams: () => extraTokenParams,
1086
1103
  autoLogin
@@ -1088,6 +1105,8 @@ export async function createOidc_nonMemoized<
1088
1105
 
1089
1106
  if (result_loginSilent.outcome === "failure") {
1090
1107
  completeLoginOrRefreshProcess();
1108
+ // NOTE: This is a configuration or network error, okay to throw,
1109
+ // this exception doesn't have to be handle if it fails it fails.
1091
1110
  throw new Error(result_loginSilent.cause);
1092
1111
  }
1093
1112
 
@@ -1120,35 +1139,27 @@ export async function createOidc_nonMemoized<
1120
1139
 
1121
1140
  if (authResponse_error === undefined) {
1122
1141
  completeLoginOrRefreshProcess();
1142
+ // Same here, if it fails it fails.
1123
1143
  throw error;
1124
1144
  }
1125
-
1126
- oidcClientTsUser_scope = undefined;
1127
1145
  }
1128
1146
 
1129
1147
  if (oidcClientTsUser_scope === undefined) {
1130
- persistAuthState({ configId, state: undefined });
1148
+ // NOTE: Here we got a response but it's an error, session might have been
1149
+ // deleted or other edge case.
1131
1150
 
1132
1151
  completeLoginOrRefreshProcess();
1133
1152
 
1134
- await waitForAllOtherOngoingLoginOrRefreshProcessesToComplete({
1135
- prUnlock: new Promise<never>(() => {})
1136
- });
1153
+ log?.(
1154
+ [
1155
+ "The user is probably not logged in anymore,",
1156
+ "need to redirect to login pages"
1157
+ ].join(" ")
1158
+ );
1137
1159
 
1138
- globalContext.evtRequestToPersistTokens.post({
1139
- configIdOfInstancePostingTheRequest: configId
1140
- });
1160
+ await fallbackToFullPageReload();
1141
1161
 
1142
- await loginOrGoToAuthServer({
1143
- action: "login",
1144
- redirectUrl: window.location.href,
1145
- doForceReloadOnBfCache: true,
1146
- extraQueryParams_local: undefined,
1147
- transformUrlBeforeRedirect_local: undefined,
1148
- doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
1149
- interaction: "ensure no interaction"
1150
- });
1151
- assert(false, "136134");
1162
+ assert(false, "136135");
1152
1163
  }
1153
1164
 
1154
1165
  oidcClientTsUser = oidcClientTsUser_scope;
@@ -1298,64 +1309,55 @@ export async function createOidc_nonMemoized<
1298
1309
  }
1299
1310
 
1300
1311
  (function scheduleRenew() {
1301
- const login_dueToExpiration = async () => {
1302
- await waitForAllOtherOngoingLoginOrRefreshProcessesToComplete({
1303
- prUnlock: new Promise<never>(() => {})
1304
- });
1305
-
1306
- persistAuthState({ configId, state: undefined });
1312
+ if (!currentTokens.hasRefreshToken && !canUseIframe) {
1313
+ log?.(
1314
+ "Disabling token auto refresh mechanism because we have no way to do it without reloading the page"
1315
+ );
1316
+ return;
1317
+ }
1307
1318
 
1308
- return loginOrGoToAuthServer({
1309
- action: "login",
1310
- redirectUrl: window.location.href,
1311
- doForceReloadOnBfCache: true,
1312
- extraQueryParams_local: undefined,
1313
- transformUrlBeforeRedirect_local: undefined,
1314
- // NOTE: Wether or not it's the preferred behavior, pushing to history
1315
- // only works on user interaction so it have to be false
1316
- doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
1317
- interaction: "ensure no interaction"
1318
- });
1319
- };
1319
+ const msBeforeExpiration =
1320
+ (currentTokens.refreshTokenExpirationTime ?? currentTokens.accessTokenExpirationTime) -
1321
+ Date.now();
1320
1322
 
1321
- const msBeforeExpiration = getMsBeforeExpiration(currentTokens);
1323
+ const RENEW_MS_BEFORE_EXPIRES = 30_000;
1322
1324
 
1323
- if (msBeforeExpiration <= MIN_RENEW_BEFORE_EXPIRE_MS) {
1325
+ if (msBeforeExpiration <= RENEW_MS_BEFORE_EXPIRES) {
1324
1326
  // NOTE: We just got a new token that is about to expire. This means that
1325
1327
  // the refresh token has reached it's max SSO time.
1326
- login_dueToExpiration();
1328
+ // ...or that the refresh token have a very short lifespan...
1329
+ // anyway, no need to keep alive, it will probably redirect on the next getTokens() or refreshTokens() call
1327
1330
  return;
1328
1331
  }
1329
1332
 
1330
- // NOTE: We refresh the token 25 seconds before it expires.
1331
- // If the token expiration time is less than 25 seconds we refresh the token when
1332
- // only 1/10 of the token time is left.
1333
- const renewMsBeforeExpires = Math.max(
1334
- Math.min(25_000, msBeforeExpiration * 0.1),
1335
- MIN_RENEW_BEFORE_EXPIRE_MS
1336
- );
1337
-
1338
1333
  log?.(
1339
1334
  [
1340
1335
  toHumanReadableDuration(msBeforeExpiration),
1341
1336
  `before expiration of the access token.`,
1342
- `Scheduling renewal ${toHumanReadableDuration(renewMsBeforeExpires)} before expiration`
1337
+ `Scheduling renewal ${toHumanReadableDuration(
1338
+ RENEW_MS_BEFORE_EXPIRES
1339
+ )} before expiration`
1343
1340
  ].join(" ")
1344
1341
  );
1345
1342
 
1346
- const timer = setTimeout(async () => {
1347
- log?.(
1348
- `Renewing the access token now as it will expires in ${toHumanReadableDuration(
1349
- renewMsBeforeExpires
1350
- )}`
1351
- );
1343
+ const timer = setTimeout(
1344
+ async () => {
1345
+ log?.(
1346
+ `Renewing the access token now as it will expires in ${toHumanReadableDuration(
1347
+ RENEW_MS_BEFORE_EXPIRES
1348
+ )}`
1349
+ );
1352
1350
 
1353
- try {
1354
1351
  await oidc_loggedIn.renewTokens();
1355
- } catch {
1356
- await login_dueToExpiration();
1357
- }
1358
- }, msBeforeExpiration - renewMsBeforeExpires);
1352
+ },
1353
+ Math.min(
1354
+ msBeforeExpiration - RENEW_MS_BEFORE_EXPIRES,
1355
+ // NOTE: We want to make sure we do not overflow the setTimeout
1356
+ // that must be a 32 bit unsigned integer.
1357
+ // This can happen if the tokenExpirationTime is more than 24.8 days in the future.
1358
+ Math.pow(2, 31) - 1
1359
+ )
1360
+ );
1359
1361
 
1360
1362
  const { unsubscribe: tokenChangeUnsubscribe } = oidc_loggedIn.subscribeToTokensChange(() => {
1361
1363
  clearTimeout(timer);
@@ -8,7 +8,6 @@ import { assert, id } from "../vendor/frontend/tsafe";
8
8
  import type { AuthResponse } from "./AuthResponse";
9
9
  import { initialLocationHref } from "./initialLocationHref";
10
10
  import { captureFetch } from "./trustedFetch";
11
- import { debug966975 } from "./debug966975";
12
11
 
13
12
  captureFetch();
14
13
 
@@ -16,19 +15,8 @@ const globalContext = {
16
15
  previousCall: id<{ isHandled: boolean } | undefined>(undefined)
17
16
  };
18
17
 
19
- debug966975.log(
20
- `=================== Evaluating the handleOidcCallback file, isInIframe: ${
21
- window.self !== window.top ? "true" : "false"
22
- }, location.href: ${initialLocationHref}`
23
- );
24
-
25
18
  export function handleOidcCallback(): { isHandled: boolean } {
26
19
  if (globalContext.previousCall !== undefined) {
27
- debug966975.log(
28
- `handleOidcCallback() call, it has been called previously ${JSON.stringify(
29
- globalContext.previousCall
30
- )}`
31
- );
32
20
  return globalContext.previousCall;
33
21
  }
34
22
 
@@ -36,20 +24,16 @@ export function handleOidcCallback(): { isHandled: boolean } {
36
24
  }
37
25
 
38
26
  function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
39
- debug966975.log(`In handleOidcCallback_nonMemoized()`);
40
-
41
27
  const location_urlObj = new URL(initialLocationHref);
42
28
 
43
29
  const stateQueryParamValue = (() => {
44
30
  const stateQueryParamValue = location_urlObj.searchParams.get("state");
45
31
 
46
32
  if (stateQueryParamValue === null) {
47
- debug966975.log("No state in url");
48
33
  return undefined;
49
34
  }
50
35
 
51
36
  if (!getIsStatQueryParamValue({ maybeStateQueryParamValue: stateQueryParamValue })) {
52
- debug966975.log(`State query param value ${stateQueryParamValue} is malformed`);
53
37
  return undefined;
54
38
  }
55
39
 
@@ -58,9 +42,6 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
58
42
  location_urlObj.searchParams.get("response_type") !== null &&
59
43
  location_urlObj.searchParams.get("redirect_uri") !== null
60
44
  ) {
61
- debug966975.log(
62
- "NOTE: We are probably in a Keycloakify theme and oidc-spa was loaded by mistake."
63
- );
64
45
  // NOTE: We are probably in a Keycloakify theme and oidc-spa was loaded by mistake.
65
46
  return undefined;
66
47
  }
@@ -68,13 +49,9 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
68
49
  return stateQueryParamValue;
69
50
  })();
70
51
 
71
- debug966975.log(`state query param value ${stateQueryParamValue ?? "undefined"}`);
72
-
73
52
  if (stateQueryParamValue === undefined) {
74
53
  const backForwardTracker = readBackForwardTracker();
75
54
 
76
- debug966975.log(`backForwardTracker: ${JSON.stringify(backForwardTracker)}`);
77
-
78
55
  if (backForwardTracker !== undefined) {
79
56
  writeBackForwardTracker({
80
57
  backForwardTracker: {
@@ -84,8 +61,6 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
84
61
  });
85
62
  }
86
63
 
87
- debug966975.log("returning isHandled false");
88
-
89
64
  return { isHandled: false };
90
65
  }
91
66
 
@@ -98,8 +73,6 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
98
73
 
99
74
  const stateData = getStateData({ stateQueryParamValue });
100
75
 
101
- debug966975.log(`stateData: ${JSON.stringify(stateData)}`);
102
-
103
76
  if (
104
77
  stateData === undefined ||
105
78
  (stateData.context === "redirect" && stateData.hasBeenProcessedByCallback)
@@ -123,8 +96,6 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
123
96
  }
124
97
  })();
125
98
 
126
- debug966975.log(`historyMethod: ${historyMethod}`);
127
-
128
99
  writeBackForwardTracker({
129
100
  backForwardTracker: {
130
101
  previousHistoryMethod: historyMethod,
@@ -133,8 +104,6 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
133
104
  });
134
105
 
135
106
  setTimeout(() => {
136
- debug966975.log(`(callback 0) Calling window.history.${historyMethod}()`);
137
-
138
107
  reloadOnBfCacheNavigation();
139
108
 
140
109
  window.history[historyMethod]();
@@ -149,8 +118,6 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
149
118
  }, 350);
150
119
  }, 0);
151
120
 
152
- debug966975.log(`returning isHandled: ${isHandled ? "true" : "false"}`);
153
-
154
121
  return { isHandled };
155
122
  }
156
123
 
@@ -162,12 +129,9 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
162
129
 
163
130
  assert(authResponse.state !== "", "063965");
164
131
 
165
- debug966975.log(`authResponse: ${JSON.stringify(authResponse)}`);
166
-
167
132
  switch (stateData.context) {
168
133
  case "iframe":
169
134
  setTimeout(() => {
170
- debug966975.log(`(callback 0) posting message to parent`);
171
135
  parent.postMessage(authResponse, location.origin);
172
136
  }, 0);
173
137
  break;
@@ -187,15 +151,11 @@ function handleOidcCallback_nonMemoized(): { isHandled: boolean } {
187
151
  return stateData.redirectUrl;
188
152
  })();
189
153
 
190
- debug966975.log(`(callback 0) location.href = "${href}";`);
191
-
192
154
  location.href = href;
193
155
  }, 0);
194
156
  break;
195
157
  }
196
158
 
197
- debug966975.log(`Returning isHandled: ${isHandled ? "true" : "false"}`);
198
-
199
159
  return { isHandled };
200
160
  }
201
161
 
@@ -229,28 +189,18 @@ export function retrieveRedirectAuthResponseAndStateData(params: {
229
189
  }): { authResponse: AuthResponse; stateData: StateData.Redirect } | undefined {
230
190
  const { configId } = params;
231
191
 
232
- debug966975.log(`>>> In retrieveRedirectAuthResponseAndStateData(${JSON.stringify({ configId })})`);
233
-
234
192
  const authResponses = readRedirectAuthResponses();
235
193
 
236
- debug966975.log(`authResponses: ${JSON.stringify(authResponses)}`);
237
-
238
194
  let authResponseAndStateData:
239
195
  | { authResponse: AuthResponse; stateData: StateData.Redirect }
240
196
  | undefined = undefined;
241
197
 
242
198
  for (const authResponse of [...authResponses]) {
243
- debug966975.log(`authResponse: ${JSON.stringify(authResponse)}`);
244
-
245
199
  const stateData = getStateData({ stateQueryParamValue: authResponse.state });
246
200
 
247
- debug966975.log(`stateDate: ${JSON.stringify(stateData)}`);
248
-
249
- try {
250
- assert(stateData !== undefined, "966975");
251
- } catch {
201
+ if (stateData === undefined) {
202
+ // NOTE: We do not understand how this can happen but it can.
252
203
  authResponses.splice(authResponses.indexOf(authResponse), 1);
253
- debug966975.report();
254
204
  continue;
255
205
  }
256
206
 
@@ -266,12 +216,9 @@ export function retrieveRedirectAuthResponseAndStateData(params: {
266
216
  }
267
217
 
268
218
  if (authResponseAndStateData !== undefined) {
269
- debug966975.log(`writeRedirectAuthResponses(${JSON.stringify({ authResponses })})`);
270
219
  writeRedirectAuthResponses({ authResponses });
271
220
  }
272
221
 
273
- debug966975.log(`Returning ${JSON.stringify({ authResponseAndStateData })} <<<<<<<<<`);
274
-
275
222
  return authResponseAndStateData;
276
223
  }
277
224
 
@@ -51,8 +51,7 @@ export function getPrSafelyRestoredFromBfCacheAfterLoginBackNavigation() {
51
51
  export function createLoginOrGoToAuthServer(params: {
52
52
  configId: string;
53
53
  oidcClientTsUserManager: OidcClientTsUserManager;
54
- transformUrlBeforeRedirect: ((url: string) => string) | undefined;
55
- transformUrlBeforeRedirect_next:
54
+ transformUrlBeforeRedirect:
56
55
  | ((params: { authorizationUrl: string; isSilent: boolean }) => string)
57
56
  | undefined;
58
57
 
@@ -71,7 +70,6 @@ export function createLoginOrGoToAuthServer(params: {
71
70
  oidcClientTsUserManager,
72
71
 
73
72
  transformUrlBeforeRedirect,
74
- transformUrlBeforeRedirect_next,
75
73
  getExtraQueryParams,
76
74
 
77
75
  getExtraTokenParams,
@@ -89,7 +87,7 @@ export function createLoginOrGoToAuthServer(params: {
89
87
  const {
90
88
  redirectUrl: redirectUrl_params,
91
89
  extraQueryParams_local,
92
- transformUrlBeforeRedirect_local: transformUrl,
90
+ transformUrlBeforeRedirect_local,
93
91
  ...rest
94
92
  } = params;
95
93
 
@@ -108,6 +106,8 @@ export function createLoginOrGoToAuthServer(params: {
108
106
  globalContext.evtHasLoginBeenCalled.current = true;
109
107
 
110
108
  if (document.visibilityState !== "visible") {
109
+ rest.interaction === "ensure no interaction";
110
+
111
111
  const dVisible = new Deferred<void>();
112
112
 
113
113
  const onVisible = () => {
@@ -196,20 +196,19 @@ export function createLoginOrGoToAuthServer(params: {
196
196
  (
197
197
  [
198
198
  [
199
- undefined,
200
- transformUrlBeforeRedirect_next === undefined
199
+ getExtraQueryParams,
200
+ transformUrlBeforeRedirect === undefined
201
201
  ? undefined
202
202
  : (url: string) =>
203
- transformUrlBeforeRedirect_next({
203
+ transformUrlBeforeRedirect({
204
204
  isSilent,
205
205
  authorizationUrl: url
206
206
  })
207
207
  ],
208
- [getExtraQueryParams, transformUrlBeforeRedirect],
209
- [extraQueryParams_local, transformUrl]
208
+ [extraQueryParams_local, transformUrlBeforeRedirect_local]
210
209
  ] as const
211
- ).forEach(([extraQueryParamsMaybeGetter, transformUrlBeforeRedirect], i) => {
212
- const url_before = i !== 2 ? undefined : url;
210
+ ).forEach(([extraQueryParamsMaybeGetter, transformUrlBeforeRedirect], i, arr) => {
211
+ const url_before = i !== arr.length - 1 ? undefined : url;
213
212
 
214
213
  add_extra_query_params: {
215
214
  if (extraQueryParamsMaybeGetter === undefined) {