oidc-spa 8.2.1 → 8.2.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.
Files changed (94) hide show
  1. package/core/AuthResponse.d.ts +0 -5
  2. package/core/AuthResponse.js +0 -25
  3. package/core/AuthResponse.js.map +1 -1
  4. package/core/createOidc.d.ts +49 -16
  5. package/core/createOidc.js +97 -122
  6. package/core/createOidc.js.map +1 -1
  7. package/core/desiredPostLoginRedirectUrl.d.ts +4 -0
  8. package/core/desiredPostLoginRedirectUrl.js +12 -0
  9. package/core/desiredPostLoginRedirectUrl.js.map +1 -0
  10. package/core/diagnostic.d.ts +1 -1
  11. package/core/diagnostic.js +3 -3
  12. package/core/diagnostic.js.map +1 -1
  13. package/core/instancesThatCantUseIframes.d.ts +2 -0
  14. package/core/instancesThatCantUseIframes.js +20 -0
  15. package/core/instancesThatCantUseIframes.js.map +1 -0
  16. package/core/loginOrGoToAuthServer.d.ts +1 -0
  17. package/core/loginOrGoToAuthServer.js +3 -0
  18. package/core/loginOrGoToAuthServer.js.map +1 -1
  19. package/core/persistedAuthState.d.ts +1 -0
  20. package/core/persistedAuthState.js +14 -4
  21. package/core/persistedAuthState.js.map +1 -1
  22. package/esm/angular.d.ts +27 -4
  23. package/esm/angular.js +28 -6
  24. package/esm/angular.js.map +1 -1
  25. package/esm/core/AuthResponse.d.ts +0 -5
  26. package/esm/core/AuthResponse.js +0 -23
  27. package/esm/core/AuthResponse.js.map +1 -1
  28. package/esm/core/createOidc.d.ts +49 -16
  29. package/esm/core/createOidc.js +98 -123
  30. package/esm/core/createOidc.js.map +1 -1
  31. package/esm/core/desiredPostLoginRedirectUrl.d.ts +4 -0
  32. package/esm/core/desiredPostLoginRedirectUrl.js +8 -0
  33. package/esm/core/desiredPostLoginRedirectUrl.js.map +1 -0
  34. package/esm/core/diagnostic.d.ts +1 -1
  35. package/esm/core/diagnostic.js +3 -3
  36. package/esm/core/diagnostic.js.map +1 -1
  37. package/esm/core/instancesThatCantUseIframes.d.ts +2 -0
  38. package/esm/core/instancesThatCantUseIframes.js +16 -0
  39. package/esm/core/instancesThatCantUseIframes.js.map +1 -0
  40. package/esm/core/loginOrGoToAuthServer.d.ts +1 -0
  41. package/esm/core/loginOrGoToAuthServer.js +3 -0
  42. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  43. package/esm/core/persistedAuthState.d.ts +1 -0
  44. package/esm/core/persistedAuthState.js +14 -4
  45. package/esm/core/persistedAuthState.js.map +1 -1
  46. package/esm/keycloak/keycloak-js/Keycloak.d.ts +40 -0
  47. package/esm/keycloak/keycloak-js/Keycloak.js +2 -1
  48. package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
  49. package/esm/react/react.js +24 -2
  50. package/esm/react/react.js.map +1 -1
  51. package/esm/react-spa/createOidcSpaApi.js +26 -4
  52. package/esm/react-spa/createOidcSpaApi.js.map +1 -1
  53. package/esm/react-spa/types.d.ts +26 -3
  54. package/esm/tanstack-start/react/createOidcSpaApi.js +25 -3
  55. package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -1
  56. package/esm/tanstack-start/react/types.d.ts +26 -3
  57. package/esm/tools/{EphemeralSessionStorage.d.ts → lazySessionStorage.d.ts} +4 -4
  58. package/esm/tools/lazySessionStorage.js +83 -0
  59. package/esm/tools/lazySessionStorage.js.map +1 -0
  60. package/keycloak/keycloak-js/Keycloak.d.ts +40 -0
  61. package/keycloak/keycloak-js/Keycloak.js +2 -1
  62. package/keycloak/keycloak-js/Keycloak.js.map +1 -1
  63. package/package.json +5 -1
  64. package/react/react.js +24 -2
  65. package/react/react.js.map +1 -1
  66. package/react-spa/createOidcSpaApi.js +26 -4
  67. package/react-spa/createOidcSpaApi.js.map +1 -1
  68. package/react-spa/types.d.ts +26 -3
  69. package/src/angular.ts +72 -18
  70. package/src/core/AuthResponse.ts +0 -36
  71. package/src/core/createOidc.ts +160 -173
  72. package/src/core/desiredPostLoginRedirectUrl.ts +9 -0
  73. package/src/core/diagnostic.ts +4 -4
  74. package/src/core/instancesThatCantUseIframes.ts +24 -0
  75. package/src/core/loginOrGoToAuthServer.ts +5 -0
  76. package/src/core/persistedAuthState.ts +27 -5
  77. package/src/keycloak/keycloak-js/Keycloak.ts +43 -1
  78. package/src/react/react.tsx +32 -3
  79. package/src/react-spa/createOidcSpaApi.tsx +34 -5
  80. package/src/react-spa/types.tsx +26 -3
  81. package/src/tanstack-start/react/createOidcSpaApi.tsx +33 -4
  82. package/src/tanstack-start/react/types.tsx +26 -3
  83. package/src/tools/lazySessionStorage.ts +123 -0
  84. package/src/vite-plugin/manageOptimizedDeps.ts +4 -1
  85. package/tools/{EphemeralSessionStorage.d.ts → lazySessionStorage.d.ts} +4 -4
  86. package/tools/lazySessionStorage.js +86 -0
  87. package/tools/lazySessionStorage.js.map +1 -0
  88. package/vite-plugin/manageOptimizedDeps.js +3 -1
  89. package/vite-plugin/manageOptimizedDeps.js.map +1 -1
  90. package/esm/tools/EphemeralSessionStorage.js +0 -143
  91. package/esm/tools/EphemeralSessionStorage.js.map +0 -1
  92. package/src/tools/EphemeralSessionStorage.ts +0 -225
  93. package/tools/EphemeralSessionStorage.js +0 -146
  94. package/tools/EphemeralSessionStorage.js.map +0 -1
@@ -1,5 +1,4 @@
1
1
  import { addOrUpdateSearchParam } from "../tools/urlSearchParams";
2
- import { createEphemeralSessionStorage } from "../tools/EphemeralSessionStorage";
3
2
  export function authResponseToUrl(authResponse) {
4
3
  let authResponseUrl = "https://dummy.com";
5
4
  for (const [name, value] of Object.entries(authResponse)) {
@@ -16,26 +15,4 @@ export function authResponseToUrl(authResponse) {
16
15
  authResponseUrl = `${authResponseUrl}#${authResponseUrl.split("?")[1]}`;
17
16
  return authResponseUrl;
18
17
  }
19
- export const { setPersistedRedirectAuthResponses, getPersistedRedirectAuthResponses } = (() => {
20
- const { getEphemeralSessionStorage } = (() => {
21
- let cache = undefined;
22
- const getEphemeralSessionStorage = () => (cache ?? (cache = createEphemeralSessionStorage({
23
- sessionStorageTtlMs: 30000
24
- })));
25
- return { getEphemeralSessionStorage };
26
- })();
27
- const KEY = "oidc-spa:persisted-redirect-auth-response";
28
- function setPersistedRedirectAuthResponses(params) {
29
- const { authResponses } = params;
30
- const storage = getEphemeralSessionStorage();
31
- storage.persistCurrentStateAndSubsequentChanges();
32
- storage.setItem(KEY, JSON.stringify(authResponses));
33
- }
34
- function getPersistedRedirectAuthResponses() {
35
- const value = getEphemeralSessionStorage().getItem(KEY);
36
- const authResponses = value === null ? [] : JSON.parse(value);
37
- return { authResponses };
38
- }
39
- return { setPersistedRedirectAuthResponses, getPersistedRedirectAuthResponses };
40
- })();
41
18
  //# sourceMappingURL=AuthResponse.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthResponse.js","sourceRoot":"","sources":["../../src/core/AuthResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACH,6BAA6B,EAEhC,MAAM,kCAAkC,CAAC;AAO1C,MAAM,UAAU,iBAAiB,CAAC,YAA0B;IACxD,IAAI,eAAe,GAAG,mBAAmB,CAAC;IAE1C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,SAAS;QACb,CAAC;QACD,eAAe,GAAG,sBAAsB,CAAC;YACrC,GAAG,EAAE,eAAe;YACpB,IAAI;YACJ,KAAK;YACL,YAAY,EAAE,UAAU;SAC3B,CAAC,CAAC;IACP,CAAC;IAED,eAAe,GAAG,GAAG,eAAe,IAAI,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAExE,OAAO,eAAe,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,MAAM,EAAE,iCAAiC,EAAE,iCAAiC,EAAE,GAAG,CAAC,GAAG,EAAE;IAC1F,MAAM,EAAE,0BAA0B,EAAE,GAAG,CAAC,GAAG,EAAE;QACzC,IAAI,KAAK,GAAwC,SAAS,CAAC;QAC3D,MAAM,0BAA0B,GAAG,GAAG,EAAE,CACpC,CAAC,KAAK,KAAL,KAAK,GAAK,6BAA6B,CAAC;YACrC,mBAAmB,EAAE,KAAM;SAC9B,CAAC,EAAC,CAAC;QACR,OAAO,EAAE,0BAA0B,EAAE,CAAC;IAC1C,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,GAAG,GAAG,2CAA2C,CAAC;IAExD,SAAS,iCAAiC,CAAC,MAAyC;QAChF,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;QAEjC,MAAM,OAAO,GAAG,0BAA0B,EAAE,CAAC;QAC7C,OAAO,CAAC,uCAAuC,EAAE,CAAC;QAElD,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,iCAAiC;QACtC,MAAM,KAAK,GAAG,0BAA0B,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAExD,MAAM,aAAa,GAAmB,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAE9E,OAAO,EAAE,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,iCAAiC,EAAE,iCAAiC,EAAE,CAAC;AACpF,CAAC,CAAC,EAAE,CAAC"}
1
+ {"version":3,"file":"AuthResponse.js","sourceRoot":"","sources":["../../src/core/AuthResponse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,MAAM,UAAU,iBAAiB,CAAC,YAA0B;IACxD,IAAI,eAAe,GAAG,mBAAmB,CAAC;IAE1C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACvD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,SAAS;QACb,CAAC;QACD,eAAe,GAAG,sBAAsB,CAAC;YACrC,GAAG,EAAE,eAAe;YACpB,IAAI;YACJ,KAAK;YACL,YAAY,EAAE,UAAU;SAC3B,CAAC,CAAC;IACP,CAAC;IAED,eAAe,GAAG,GAAG,eAAe,IAAI,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAExE,OAAO,eAAe,CAAC;AAC3B,CAAC"}
@@ -49,19 +49,6 @@ export type ParamsOfCreateOidc<DecodedIdToken extends Record<string, unknown> =
49
49
  * extraTokenParams: { selectedCustomer: "xxx" }
50
50
  */
51
51
  extraTokenParams?: Record<string, string | undefined> | (() => Record<string, string | undefined>);
52
- /**
53
- * Usage discouraged, it's here because we don't want to assume too much on your
54
- * usecase but I can't think of a scenario where you would want anything
55
- * other than the current page.
56
- *
57
- * Where to redirect after successful login.
58
- * Default: window.location.href (here)
59
- *
60
- * It does not need to include the origin, eg: "/dashboard"
61
- *
62
- * This parameter can also be passed to login() directly as `redirectUrl`.
63
- */
64
- postLoginRedirectUrl?: string;
65
52
  decodedIdTokenSchema?: {
66
53
  parse: (decodedIdToken_original: Oidc.Tokens.DecodedIdToken_OidcCoreSpec) => DecodedIdToken;
67
54
  };
@@ -87,9 +74,42 @@ export type ParamsOfCreateOidc<DecodedIdToken extends Record<string, unknown> =
87
74
  autoLogoutParams?: Parameters<Oidc.LoggedIn<any>["logout"]>[0];
88
75
  autoLogin?: AutoLogin;
89
76
  /**
77
+ * Determines how session restoration is handled.
78
+ * Session restoration allows users to stay logged in between visits
79
+ * without needing to explicitly sign in each time.
80
+ *
81
+ * Options:
82
+ *
83
+ * - **"auto" (default)**:
84
+ * Automatically selects the best method.
85
+ * If the app’s domain shares a common parent domain with the authorization endpoint,
86
+ * an iframe is used for silent session restoration.
87
+ * Otherwise, a full-page redirect is used.
88
+ *
89
+ * - **"full page redirect"**:
90
+ * Forces full-page reloads for session restoration.
91
+ * Use this if your application is served with a restrictive CSP
92
+ * (e.g., `Content-Security-Policy: frame-ancestors "none"`)
93
+ * or `X-Frame-Options: DENY`, and you cannot modify those headers.
94
+ * This mode provides a slightly less seamless UX and will lead oidc-spa to
95
+ * store tokens in `localStorage` if multiple OIDC clients are used
96
+ * (e.g., your app communicates with several APIs).
97
+ *
98
+ * - **"iframe"**:
99
+ * Forces iframe-based session restoration.
100
+ * In development, if you go in your browser setting and allow your auth server’s domain
101
+ * to set third-party cookies this value will let you test your app
102
+ * with the local dev server as it will behave in production.
103
+ *
104
+ * See: https://docs.oidc-spa.dev/v/v8/resources/third-party-cookies-and-session-restoration
105
+ */
106
+ sessionRestorationMethod?: "iframe" | "full page redirect" | "auto";
107
+ /**
108
+ * @deprecated Use `sessionRestorationMethod: "full page redirect"` instead.
109
+ *
90
110
  * Default: false
91
111
  *
92
- * See: https://docs.oidc-spa.dev/v/v8/resources/iframe-related-issues
112
+ * See: https://docs.oidc-spa.dev/v/v8/resources/third-party-cookies-and-session-restoration
93
113
  */
94
114
  noIframe?: boolean;
95
115
  debugLogs?: boolean;
@@ -136,13 +156,26 @@ export type ParamsOfCreateOidc<DecodedIdToken extends Record<string, unknown> =
136
156
  BASE_URL?: string;
137
157
  /** @deprecated: Use BASE_URL (same thing, just renamed). */
138
158
  homeUrl?: string;
159
+ /**
160
+ * This parameter is irrelevant in most usecases.
161
+ * It tells where to redirect after a successful login or autoLogin.
162
+ *
163
+ * If you are not in autoLogin mode there is absolutely no reason to use
164
+ * this parameter since you can pass `login({ redirectUrl: "..." })`.
165
+ *
166
+ * It can only be useful in some edge case with `autoLogin: true`
167
+ * When you want to precisely redirect somewhere after login.
168
+ *
169
+ * This can make sense if you have multiple clients to talk with different
170
+ * API and no iframe capabilities.
171
+ */
172
+ postLoginRedirectUrl?: string;
139
173
  };
140
174
  /** @see: https://docs.oidc-spa.dev/v/v8/usage */
141
175
  export declare function createOidc<DecodedIdToken extends Record<string, unknown> = Oidc.Tokens.DecodedIdToken_OidcCoreSpec, AutoLogin extends boolean = false>(params: ParamsOfCreateOidc<DecodedIdToken, AutoLogin>): Promise<AutoLogin extends true ? Oidc.LoggedIn<DecodedIdToken> : Oidc<DecodedIdToken>>;
142
- export declare function createOidc_nonMemoized<DecodedIdToken extends Record<string, unknown>, AutoLogin extends boolean>(params: Omit<ParamsOfCreateOidc<DecodedIdToken, AutoLogin>, "issuerUri" | "clientId" | "scopes" | "debugLogs">, preProcessedParams: {
176
+ export declare function createOidc_nonMemoized<DecodedIdToken extends Record<string, unknown>, AutoLogin extends boolean>(params: Omit<ParamsOfCreateOidc<DecodedIdToken, AutoLogin>, "issuerUri" | "clientId" | "debugLogs">, preProcessedParams: {
143
177
  issuerUri: string;
144
178
  clientId: string;
145
- scopes: string[];
146
179
  configId: string;
147
180
  log: typeof console.log | undefined;
148
181
  }): Promise<AutoLogin extends true ? Oidc.LoggedIn<DecodedIdToken> : Oidc<DecodedIdToken>>;
@@ -15,13 +15,13 @@ import { notifyOtherTabsOfLogin, getPrOtherTabLogin } from "./loginPropagationTo
15
15
  import { getConfigId } from "./configId";
16
16
  import { oidcClientTsUserToTokens } from "./oidcClientTsUserToTokens";
17
17
  import { loginSilent } from "./loginSilent";
18
- import { authResponseToUrl, getPersistedRedirectAuthResponses, setPersistedRedirectAuthResponses } from "./AuthResponse";
18
+ import { authResponseToUrl } from "./AuthResponse";
19
19
  import { getRootRelativeOriginalLocationHref, getRedirectAuthResponse } from "./earlyInit";
20
20
  import { getPersistedAuthState, persistAuthState } from "./persistedAuthState";
21
21
  import { createEvt } from "../tools/Evt";
22
22
  import { getHaveSharedParentDomain } from "../tools/haveSharedParentDomain";
23
23
  import { createLoginOrGoToAuthServer, getPrSafelyRestoredFromBfCacheAfterLoginBackNavigationOrInitializationError } from "./loginOrGoToAuthServer";
24
- import { createEphemeralSessionStorage } from "../tools/EphemeralSessionStorage";
24
+ import { createLazySessionStorage } from "../tools/lazySessionStorage";
25
25
  import { startLoginOrRefreshProcess, waitForAllOtherOngoingLoginOrRefreshProcessesToComplete } from "./ongoingLoginOrRefreshProcesses";
26
26
  import { createGetIsNewBrowserSession } from "./isNewBrowserSession";
27
27
  import { getIsOnline } from "../tools/getIsOnline";
@@ -31,23 +31,14 @@ import { prShouldLoadApp } from "./prShouldLoadApp";
31
31
  import { getBASE_URL } from "./BASE_URL";
32
32
  import { getIsLikelyDevServer } from "../tools/isLikelyDevServer";
33
33
  import { createObjectThatThrowsIfAccessed } from "../tools/createObjectThatThrowsIfAccessed";
34
+ import { evtIsThereMoreThanOneInstanceThatCantUserIframes, notifyNewInstanceThatCantUseIframes } from "./instancesThatCantUseIframes";
35
+ import { getDesiredPostLoginRedirectUrl } from "./desiredPostLoginRedirectUrl";
34
36
  // NOTE: Replaced at build time
35
- const VERSION = "8.2.1";
37
+ const VERSION = "8.2.3";
36
38
  const globalContext = {
37
39
  prOidcByConfigId: new Map(),
38
- hasLogoutBeenCalled: id(false),
39
- evtRequestToPersistTokens: createEvt()
40
+ hasLogoutBeenCalled: id(false)
40
41
  };
41
- globalContext.evtRequestToPersistTokens.subscribe(() => {
42
- const { authResponse } = getRedirectAuthResponse();
43
- if (authResponse === undefined) {
44
- return;
45
- }
46
- const { authResponses } = getPersistedRedirectAuthResponses();
47
- setPersistedRedirectAuthResponses({
48
- authResponses: [...authResponses, authResponse]
49
- });
50
- });
51
42
  /** @see: https://docs.oidc-spa.dev/v/v8/usage */
52
43
  export async function createOidc(params) {
53
44
  for (const name of ["issuerUri", "clientId"]) {
@@ -56,7 +47,7 @@ export async function createOidc(params) {
56
47
  throw new Error(`The parameter "${name}" is required, you provided: ${value}. (Forgot a .env variable?)`);
57
48
  }
58
49
  }
59
- const { issuerUri: issuerUri_params, clientId, scopes = ["profile"], debugLogs, ...rest } = params;
50
+ const { issuerUri: issuerUri_params, clientId, debugLogs, ...rest } = params;
60
51
  const issuerUri = toFullyQualifiedUrl({
61
52
  urlish: issuerUri_params,
62
53
  doAssertNoQueryParams: true,
@@ -98,7 +89,6 @@ export async function createOidc(params) {
98
89
  const oidc = await createOidc_nonMemoized(rest, {
99
90
  issuerUri,
100
91
  clientId,
101
- scopes,
102
92
  configId,
103
93
  log
104
94
  });
@@ -121,9 +111,9 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
121
111
  return new Promise(() => { });
122
112
  }
123
113
  }
124
- const { transformUrlBeforeRedirect, extraQueryParams: extraQueryParamsOrGetter, extraTokenParams: extraTokenParamsOrGetter, decodedIdTokenSchema, idleSessionLifetimeInSeconds, autoLogoutParams = { redirectTo: "current page" }, autoLogin = false, postLoginRedirectUrl: postLoginRedirectUrl_default, __unsafe_clientSecret, __unsafe_useIdTokenAsAccessToken = false, __metadata, noIframe = false } = params;
114
+ const { transformUrlBeforeRedirect, extraQueryParams: extraQueryParamsOrGetter, extraTokenParams: extraTokenParamsOrGetter, decodedIdTokenSchema, idleSessionLifetimeInSeconds, autoLogoutParams = { redirectTo: "current page" }, autoLogin = false, postLoginRedirectUrl: postLoginRedirectUrl_default, __unsafe_clientSecret, __unsafe_useIdTokenAsAccessToken = false, __metadata, scopes = ["openid", "profile"], sessionRestorationMethod = params.autoLogin === true ? "full page redirect" : "auto" } = params;
125
115
  const BASE_URL_params = params.BASE_URL ?? params.homeUrl;
126
- const { issuerUri, clientId, scopes, configId, log } = preProcessedParams;
116
+ const { issuerUri, clientId, configId, log } = preProcessedParams;
127
117
  const getExtraQueryParams = (() => {
128
118
  if (extraQueryParamsOrGetter === undefined) {
129
119
  return undefined;
@@ -168,14 +158,20 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
168
158
  issuerUri,
169
159
  clientId,
170
160
  scopes,
171
- configId,
172
- homeUrlAndRedirectUri
161
+ oidcRedirectUri: homeUrlAndRedirectUri
173
162
  }, null, 2)}`);
174
163
  const stateUrlParamValue_instance = generateStateUrlParamValue();
175
164
  const oidcMetadata = __metadata ?? (await fetchOidcMetadata({ issuerUri }));
176
165
  const canUseIframe = (() => {
177
- if (noIframe) {
178
- return false;
166
+ switch (sessionRestorationMethod) {
167
+ case "auto":
168
+ break;
169
+ case "full page redirect":
170
+ return false;
171
+ case "iframe":
172
+ return true;
173
+ default:
174
+ assert;
179
175
  }
180
176
  third_party_cookies: {
181
177
  if (oidcMetadata === undefined) {
@@ -230,7 +226,7 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
230
226
  if (isLikelyDevServer) {
231
227
  log?.([
232
228
  "Detected localhost environment.",
233
- "\nWhen reloading while logged in, you may briefly see",
229
+ "\nWhen reloading while logged in, you will briefly see",
234
230
  "some URL params appear in the address bar.",
235
231
  "\nThis happens because session restore via iframe is disabled,",
236
232
  "the browser treats your auth server as a third party.",
@@ -257,7 +253,7 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
257
253
  ];
258
254
  })(),
259
255
  "\n\nMore info:",
260
- "https://docs.oidc-spa.dev/v/v8/resources/end-of-third-party-cookies#when-are-cookies-considered-third-party"
256
+ "https://docs.oidc-spa.dev/v/v8/resources/third-party-cookies-and-session-restoration"
261
257
  ].join(" "));
262
258
  }
263
259
  else {
@@ -284,14 +280,20 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
284
280
  ];
285
281
  })(),
286
282
  "\nMore info:",
287
- "https://docs.oidc-spa.dev/v/v8/resources/end-of-third-party-cookies#when-are-cookies-considered-third-party"
283
+ "https://docs.oidc-spa.dev/v/v8/resources/third-party-cookies-and-session-restoration"
288
284
  ].join(" "));
289
285
  }
290
286
  return false;
291
287
  }
292
288
  return true;
293
289
  })();
294
- let isUserStoreInMemoryOnly = undefined;
290
+ notifyNewInstanceThatCantUseIframes();
291
+ if (evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
292
+ log?.([
293
+ "More than one oidc instance can't use iframe",
294
+ "falling back to persisting tokens in session storage"
295
+ ].join(" "));
296
+ }
295
297
  const oidcClientTsUserManager = oidcMetadata === undefined
296
298
  ? createObjectThatThrowsIfAccessed({
297
299
  debugMessage: "oidc-spa: Wrong assertion 43943"
@@ -310,20 +312,17 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
310
312
  userStore: new WebStorageStateStore({
311
313
  store: (() => {
312
314
  if (canUseIframe) {
313
- isUserStoreInMemoryOnly = true;
314
315
  return new InMemoryWebStorage();
315
316
  }
316
- isUserStoreInMemoryOnly = false;
317
- const storage = createEphemeralSessionStorage({
318
- sessionStorageTtlMs: 3 * 60000
319
- });
320
- const { evtRequestToPersistTokens } = globalContext;
321
- evtRequestToPersistTokens.subscribe(({ configIdOfInstancePostingTheRequest }) => {
322
- if (configIdOfInstancePostingTheRequest === configId) {
323
- return;
324
- }
317
+ const storage = createLazySessionStorage({ storageId: configId });
318
+ if (evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
325
319
  storage.persistCurrentStateAndSubsequentChanges();
326
- });
320
+ }
321
+ else {
322
+ evtIsThereMoreThanOneInstanceThatCantUserIframes.subscribe(() => {
323
+ storage.persistCurrentStateAndSubsequentChanges();
324
+ });
325
+ }
327
326
  return storage;
328
327
  })()
329
328
  }),
@@ -356,54 +355,52 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
356
355
  issuerUri
357
356
  });
358
357
  }
358
+ restore_from_session_storage: {
359
+ if (canUseIframe) {
360
+ break restore_from_session_storage;
361
+ }
362
+ if (!evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
363
+ break restore_from_session_storage;
364
+ }
365
+ let oidcClientTsUser;
366
+ try {
367
+ oidcClientTsUser = await oidcClientTsUserManager.getUser();
368
+ }
369
+ catch {
370
+ // NOTE: Not sure if it can throw, but let's be safe.
371
+ oidcClientTsUser = null;
372
+ try {
373
+ await oidcClientTsUserManager.removeUser();
374
+ }
375
+ catch { }
376
+ }
377
+ if (oidcClientTsUser === null) {
378
+ break restore_from_session_storage;
379
+ }
380
+ log?.("Session was restored from session storage");
381
+ return {
382
+ oidcClientTsUser,
383
+ backFromAuthServer: undefined
384
+ };
385
+ }
359
386
  handle_redirect_auth_response: {
360
387
  let stateDataAndAuthResponse = undefined;
361
- get_stateData_and_authResponse: {
362
- from_memory: {
363
- const { authResponse, clearAuthResponse } = getRedirectAuthResponse();
364
- if (authResponse === undefined) {
365
- break from_memory;
366
- }
367
- const stateData = getStateData({ stateUrlParamValue: authResponse.state });
368
- if (stateData === undefined) {
369
- clearAuthResponse();
370
- break from_memory;
371
- }
372
- if (stateData.configId !== configId) {
373
- break from_memory;
374
- }
375
- assert(stateData.context === "redirect", "3229492");
388
+ {
389
+ const { authResponse, clearAuthResponse } = getRedirectAuthResponse();
390
+ if (authResponse === undefined) {
391
+ break handle_redirect_auth_response;
392
+ }
393
+ const stateData = getStateData({ stateUrlParamValue: authResponse.state });
394
+ if (stateData === undefined) {
376
395
  clearAuthResponse();
377
- stateDataAndAuthResponse = { stateData, authResponse };
378
- break get_stateData_and_authResponse;
396
+ break handle_redirect_auth_response;
379
397
  }
380
- // from storage, this is for race condition in multiple instance
381
- // setup where one instance would need to redirect before
382
- // the authResponse in memory had the chance to be processed.
383
- // This can only happen if:
384
- // 1) There are multiple oidc instances in the App.
385
- // 2) They are instantiated in a non deterministic order.
386
- // 3) We can't use iframe
387
- // We practically never persist the auth response and do it only in session
388
- // an ephemeral session storage, when we know it's gonna be required.
389
- {
390
- const { authResponses } = getPersistedRedirectAuthResponses();
391
- for (const authResponse of authResponses) {
392
- const stateData = getStateData({ stateUrlParamValue: authResponse.state });
393
- if (stateData === undefined) {
394
- continue;
395
- }
396
- if (stateData.configId !== configId) {
397
- continue;
398
- }
399
- assert(stateData.context === "redirect", "35935591");
400
- setPersistedRedirectAuthResponses({
401
- authResponses: authResponses.filter(authResponse_i => authResponse_i !== authResponse)
402
- });
403
- stateDataAndAuthResponse = { stateData, authResponse };
404
- break get_stateData_and_authResponse;
405
- }
398
+ if (stateData.configId !== configId) {
399
+ break handle_redirect_auth_response;
406
400
  }
401
+ assert(stateData.context === "redirect", "3229492");
402
+ clearAuthResponse();
403
+ stateDataAndAuthResponse = { stateData, authResponse };
407
404
  }
408
405
  if (stateDataAndAuthResponse === undefined) {
409
406
  break handle_redirect_auth_response;
@@ -482,34 +479,6 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
482
479
  assert(false);
483
480
  }
484
481
  }
485
- // NOTE: We almost never persist tokens, we have to only to support edge case
486
- // of multiple oidc instance in a single App with no iframe support.
487
- restore_from_session_storage: {
488
- assert(isUserStoreInMemoryOnly !== undefined, "3392204");
489
- if (isUserStoreInMemoryOnly) {
490
- break restore_from_session_storage;
491
- }
492
- let oidcClientTsUser;
493
- try {
494
- oidcClientTsUser = await oidcClientTsUserManager.getUser();
495
- }
496
- catch {
497
- // NOTE: Not sure if it can throw, but let's be safe.
498
- oidcClientTsUser = null;
499
- try {
500
- await oidcClientTsUserManager.removeUser();
501
- }
502
- catch { }
503
- }
504
- if (oidcClientTsUser === null) {
505
- break restore_from_session_storage;
506
- }
507
- log?.("Restored the auth from ephemeral session storage");
508
- return {
509
- oidcClientTsUser,
510
- backFromAuthServer: undefined
511
- };
512
- }
513
482
  silent_login_if_possible_and_auto_login: {
514
483
  const persistedAuthState = getPersistedAuthState({ configId });
515
484
  if (persistedAuthState === "explicitly logged out" && !autoLogin) {
@@ -562,7 +531,7 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
562
531
  redirectUri: homeUrlAndRedirectUri,
563
532
  clientId,
564
533
  issuerUri,
565
- noIframe
534
+ canUseIframe
566
535
  });
567
536
  }
568
537
  assert();
@@ -594,7 +563,6 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
594
563
  authResponse_error === "consent_required" ||
595
564
  authResponse_error === "account_selection_required"))) {
596
565
  log?.("Performing auto login with redirect");
597
- persistAuthState({ configId, state: undefined });
598
566
  completeLoginOrRefreshProcess();
599
567
  if (autoLogin && persistedAuthState !== "logged in") {
600
568
  evtInitializationOutcomeUserNotLoggedIn.post();
@@ -602,15 +570,18 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
602
570
  await waitForAllOtherOngoingLoginOrRefreshProcessesToComplete({
603
571
  prUnlock: getPrSafelyRestoredFromBfCacheAfterLoginBackNavigationOrInitializationError()
604
572
  });
605
- if (persistedAuthState === "logged in") {
606
- globalContext.evtRequestToPersistTokens.post({
607
- configIdOfInstancePostingTheRequest: configId
608
- });
609
- }
610
573
  await loginOrGoToAuthServer({
611
574
  action: "login",
612
575
  doForceReloadOnBfCache: true,
613
- redirectUrl: getRootRelativeOriginalLocationHref(),
576
+ redirectUrl: (() => {
577
+ if (postLoginRedirectUrl_default) {
578
+ return postLoginRedirectUrl_default;
579
+ }
580
+ if (!evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
581
+ return getRootRelativeOriginalLocationHref();
582
+ }
583
+ return getDesiredPostLoginRedirectUrl() ?? window.location.href;
584
+ })(),
614
585
  // NOTE: Wether or not it's the preferred behavior, pushing to history
615
586
  // only works on user interaction so it have to be false
616
587
  doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
@@ -624,7 +595,10 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
624
595
  return "directly redirect if active session show login otherwise";
625
596
  }
626
597
  return "ensure no interaction";
627
- })()
598
+ })(),
599
+ preRedirectHook: () => {
600
+ persistAuthState({ configId, state: undefined });
601
+ }
628
602
  });
629
603
  }
630
604
  if (authResponse_error !== undefined) {
@@ -711,7 +685,8 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
711
685
  transformUrlBeforeRedirect_local: transformUrlBeforeRedirect,
712
686
  interaction: getPersistedAuthState({ configId }) === "explicitly logged out"
713
687
  ? "ensure interaction"
714
- : "directly redirect if active session show login otherwise"
688
+ : "directly redirect if active session show login otherwise",
689
+ preRedirectHook: undefined
715
690
  });
716
691
  },
717
692
  initializationError: undefined
@@ -768,6 +743,7 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
768
743
  state: {
769
744
  stateDescription: "logged in",
770
745
  refreshTokenExpirationTime: currentTokens.refreshTokenExpirationTime,
746
+ serverDateNow: currentTokens.getServerDateNow(),
771
747
  idleSessionLifetimeInSeconds
772
748
  }
773
749
  });
@@ -885,9 +861,6 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
885
861
  await waitForAllOtherOngoingLoginOrRefreshProcessesToComplete({
886
862
  prUnlock: new Promise(() => { })
887
863
  });
888
- globalContext.evtRequestToPersistTokens.post({
889
- configIdOfInstancePostingTheRequest: configId
890
- });
891
864
  await loginOrGoToAuthServer({
892
865
  action: "login",
893
866
  redirectUrl: window.location.href,
@@ -895,7 +868,8 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
895
868
  extraQueryParams_local: undefined,
896
869
  transformUrlBeforeRedirect_local: undefined,
897
870
  doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
898
- interaction: "directly redirect if active session show login otherwise"
871
+ interaction: "directly redirect if active session show login otherwise",
872
+ preRedirectHook: undefined
899
873
  });
900
874
  assert(false, "136134");
901
875
  };
@@ -987,6 +961,7 @@ export async function createOidc_nonMemoized(params, preProcessedParams) {
987
961
  state: {
988
962
  stateDescription: "logged in",
989
963
  refreshTokenExpirationTime: currentTokens.refreshTokenExpirationTime,
964
+ serverDateNow: currentTokens.getServerDateNow(),
990
965
  idleSessionLifetimeInSeconds
991
966
  }
992
967
  });