@frontegg/redux-store 7.123.0-alpha.2 → 7.123.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.
@@ -212,7 +212,7 @@ export default ((store, api, sharedActions) => {
212
212
  */
213
213
 
214
214
  const afterAuthNavigation = async payload => {
215
- var _window4, _payload$preventRedir;
215
+ var _store$auth$tenantSel2;
216
216
  // Once the choose-tenant step starts a switch the chooser owns navigation. Every re-entry here
217
217
  // (the switch's token refresh, and — critically — a late or timed-out switch completing AFTER the
218
218
  // user hit the escape hatch) must be a no-op, so navigation can't run twice or jump into the wrong
@@ -239,52 +239,73 @@ export default ((store, api, sharedActions) => {
239
239
  }); // consume: later re-entries stay suppressed
240
240
  }
241
241
 
242
- const {
243
- customLoginAuthenticatedUrl,
244
- stepUpUrl
245
- } = store.auth.routes;
246
-
247
- // Step-up on the CURRENT tenant resolves before the org chooser: a user who needs both
248
- // authenticates + steps up first, then picks an org. switchTenant handles any MFA the chosen
249
- // org requires on its own, and the isSteppedUp guard below means an already-stepped-up user is
250
- // never re-prompted.
251
- // login with magic code, try to step up, no other mfa, invalid max age, force_enroll -> logout, login with first factor, not-stepped up jwt -> navigate to step up
252
- const shouldStepUp = (_window4 = window) == null ? void 0 : _window4.localStorage.getItem(SHOULD_STEP_UP_KEY);
253
- const user = store.auth.user;
254
- if (shouldStepUp) {
255
- var _window5;
256
- (_window5 = window) == null ? void 0 : _window5.localStorage.removeItem(SHOULD_STEP_UP_KEY);
257
- }
258
- if (stepUpUrl && shouldStepUp && !isSteppedUp(user)) {
259
- return afterAuthNavigationUtil(actions.resetLoginState, {
260
- forceStepUpUrl: stepUpUrl
261
- });
262
- }
263
- if (await shouldRouteToChooseTenant()) {
242
+ // Callers expose the authenticated user in the store BEFORE this function's async gates resolve,
243
+ // so a host app that redirects on `user != null` (e.g. the hosted-login postlogin) would complete
244
+ // the flow before the choose-organization step can render. Raise `tenantChoicePending` in the same
245
+ // synchronous block (same store batch as the user set) so such hosts can hold, and always lower it
246
+ // once the gate has decided: by then either `step` is chooseTenant (the chooser now covers the
247
+ // hold) or the flow finalized. Written only when the integrator opted into tenant selection.
248
+ const tenantSelectionEnabled = ((_store$auth$tenantSel2 = store.auth.tenantSelection) == null ? void 0 : _store$auth$tenantSel2.enabled) === true;
249
+ if (tenantSelectionEnabled) {
264
250
  actions.setLoginState({
265
- step: LoginStep.chooseTenant,
266
- loading: false
267
- });
268
- // Mirror the other post-auth interstitials (e.g. promptPasskeys): navigate to the login URL
269
- // so the ChooseTenant step actually renders even when afterAuthNavigation is invoked from an
270
- // OAuth/social callback route.
271
- store.auth.onRedirectTo(store.auth.routes.loginUrl, {
272
- preserveQueryParams: true
251
+ tenantChoicePending: true
273
252
  });
274
- return; // do NOT finalize; ChooseTenant confirm re-enters afterAuthNavigation
275
253
  }
254
+ try {
255
+ var _window4, _payload$preventRedir;
256
+ const {
257
+ customLoginAuthenticatedUrl,
258
+ stepUpUrl
259
+ } = store.auth.routes;
260
+
261
+ // Step-up on the CURRENT tenant resolves before the org chooser: a user who needs both
262
+ // authenticates + steps up first, then picks an org. switchTenant handles any MFA the chosen
263
+ // org requires on its own, and the isSteppedUp guard below means an already-stepped-up user is
264
+ // never re-prompted.
265
+ // login with magic code, try to step up, no other mfa, invalid max age, force_enroll -> logout, login with first factor, not-stepped up jwt -> navigate to step up
266
+ const shouldStepUp = (_window4 = window) == null ? void 0 : _window4.localStorage.getItem(SHOULD_STEP_UP_KEY);
267
+ const user = store.auth.user;
268
+ if (shouldStepUp) {
269
+ var _window5;
270
+ (_window5 = window) == null ? void 0 : _window5.localStorage.removeItem(SHOULD_STEP_UP_KEY);
271
+ }
272
+ if (stepUpUrl && shouldStepUp && !isSteppedUp(user)) {
273
+ return await afterAuthNavigationUtil(actions.resetLoginState, {
274
+ forceStepUpUrl: stepUpUrl
275
+ });
276
+ }
277
+ if (await shouldRouteToChooseTenant()) {
278
+ actions.setLoginState({
279
+ step: LoginStep.chooseTenant,
280
+ loading: false
281
+ });
282
+ // Mirror the other post-auth interstitials (e.g. promptPasskeys): navigate to the login URL
283
+ // so the ChooseTenant step actually renders even when afterAuthNavigation is invoked from an
284
+ // OAuth/social callback route.
285
+ store.auth.onRedirectTo(store.auth.routes.loginUrl, {
286
+ preserveQueryParams: true
287
+ });
288
+ return; // do NOT finalize; ChooseTenant confirm re-enters afterAuthNavigation
289
+ }
276
290
 
277
- let customLoginURL = customLoginAuthenticatedUrl;
278
- if (!customLoginAuthenticatedUrl) {
279
- var _store$auth$routes;
280
- await actions.loadCustomLoginRoutes();
281
- customLoginURL = (_store$auth$routes = store.auth.routes) == null ? void 0 : _store$auth$routes.customLoginAuthenticatedUrl;
291
+ let customLoginURL = customLoginAuthenticatedUrl;
292
+ if (!customLoginAuthenticatedUrl) {
293
+ var _store$auth$routes;
294
+ await actions.loadCustomLoginRoutes();
295
+ customLoginURL = (_store$auth$routes = store.auth.routes) == null ? void 0 : _store$auth$routes.customLoginAuthenticatedUrl;
296
+ }
297
+ return await afterAuthNavigationUtil(actions.resetLoginState, {
298
+ customLoginAuthenticatedUrl: customLoginURL,
299
+ shouldStepUpDuringLogin: !!shouldStepUp,
300
+ preventRedirectUrlOriginCleaning: (_payload$preventRedir = payload == null ? void 0 : payload.preventRedirectUrlOriginCleaning) != null ? _payload$preventRedir : false
301
+ });
302
+ } finally {
303
+ if (tenantSelectionEnabled) {
304
+ actions.setLoginState({
305
+ tenantChoicePending: false
306
+ });
307
+ }
282
308
  }
283
- return afterAuthNavigationUtil(actions.resetLoginState, {
284
- customLoginAuthenticatedUrl: customLoginURL,
285
- shouldStepUpDuringLogin: !!shouldStepUp,
286
- preventRedirectUrlOriginCleaning: (_payload$preventRedir = payload == null ? void 0 : payload.preventRedirectUrlOriginCleaning) != null ? _payload$preventRedir : false
287
- });
288
309
  };
289
310
 
290
311
  /**
@@ -63,6 +63,13 @@ export interface LoginState {
63
63
  * so re-entry into afterAuthNavigation finalizes without re-prompting.
64
64
  */
65
65
  tenantChoiceResolved: boolean;
66
+ /**
67
+ * True from afterAuthNavigation entry until the choose-organization gate decides (choose-organization
68
+ * feature, only when `tenantSelection.enabled`). The authenticated user is exposed in the store BEFORE
69
+ * the gate's async work resolves, so host apps that redirect on `user != null` (e.g. the hosted-login
70
+ * postlogin) must hold while this is set or they complete the flow before the chooser can render.
71
+ */
72
+ tenantChoicePending?: boolean;
66
73
  /**
67
74
  * True while the choose-organization step is performing switchTenant + showing its success
68
75
  * interstitial. switchTenant refreshes the token, which re-enters afterAuthNavigation; this flag
@@ -7,6 +7,7 @@ export const initialState = {
7
7
  email: '',
8
8
  tenants: [],
9
9
  tenantChoiceResolved: false,
10
+ tenantChoicePending: false,
10
11
  chooseTenantSwitching: false,
11
12
  chooseTenantFinalizing: false
12
13
  };
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license Frontegg v7.123.0-alpha.2
1
+ /** @license Frontegg v7.123.0
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
@@ -219,7 +219,7 @@ var _default = (store, api, sharedActions) => {
219
219
  */
220
220
 
221
221
  const afterAuthNavigation = async payload => {
222
- var _window4, _payload$preventRedir;
222
+ var _store$auth$tenantSel2;
223
223
  // Once the choose-tenant step starts a switch the chooser owns navigation. Every re-entry here
224
224
  // (the switch's token refresh, and — critically — a late or timed-out switch completing AFTER the
225
225
  // user hit the escape hatch) must be a no-op, so navigation can't run twice or jump into the wrong
@@ -246,52 +246,73 @@ var _default = (store, api, sharedActions) => {
246
246
  }); // consume: later re-entries stay suppressed
247
247
  }
248
248
 
249
- const {
250
- customLoginAuthenticatedUrl,
251
- stepUpUrl
252
- } = store.auth.routes;
253
-
254
- // Step-up on the CURRENT tenant resolves before the org chooser: a user who needs both
255
- // authenticates + steps up first, then picks an org. switchTenant handles any MFA the chosen
256
- // org requires on its own, and the isSteppedUp guard below means an already-stepped-up user is
257
- // never re-prompted.
258
- // login with magic code, try to step up, no other mfa, invalid max age, force_enroll -> logout, login with first factor, not-stepped up jwt -> navigate to step up
259
- const shouldStepUp = (_window4 = window) == null ? void 0 : _window4.localStorage.getItem(_consts.SHOULD_STEP_UP_KEY);
260
- const user = store.auth.user;
261
- if (shouldStepUp) {
262
- var _window5;
263
- (_window5 = window) == null ? void 0 : _window5.localStorage.removeItem(_consts.SHOULD_STEP_UP_KEY);
264
- }
265
- if (stepUpUrl && shouldStepUp && !(0, _helpers3.isSteppedUp)(user)) {
266
- return afterAuthNavigationUtil(actions.resetLoginState, {
267
- forceStepUpUrl: stepUpUrl
268
- });
269
- }
270
- if (await shouldRouteToChooseTenant()) {
249
+ // Callers expose the authenticated user in the store BEFORE this function's async gates resolve,
250
+ // so a host app that redirects on `user != null` (e.g. the hosted-login postlogin) would complete
251
+ // the flow before the choose-organization step can render. Raise `tenantChoicePending` in the same
252
+ // synchronous block (same store batch as the user set) so such hosts can hold, and always lower it
253
+ // once the gate has decided: by then either `step` is chooseTenant (the chooser now covers the
254
+ // hold) or the flow finalized. Written only when the integrator opted into tenant selection.
255
+ const tenantSelectionEnabled = ((_store$auth$tenantSel2 = store.auth.tenantSelection) == null ? void 0 : _store$auth$tenantSel2.enabled) === true;
256
+ if (tenantSelectionEnabled) {
271
257
  actions.setLoginState({
272
- step: _interfaces.LoginStep.chooseTenant,
273
- loading: false
274
- });
275
- // Mirror the other post-auth interstitials (e.g. promptPasskeys): navigate to the login URL
276
- // so the ChooseTenant step actually renders even when afterAuthNavigation is invoked from an
277
- // OAuth/social callback route.
278
- store.auth.onRedirectTo(store.auth.routes.loginUrl, {
279
- preserveQueryParams: true
258
+ tenantChoicePending: true
280
259
  });
281
- return; // do NOT finalize; ChooseTenant confirm re-enters afterAuthNavigation
282
260
  }
261
+ try {
262
+ var _window4, _payload$preventRedir;
263
+ const {
264
+ customLoginAuthenticatedUrl,
265
+ stepUpUrl
266
+ } = store.auth.routes;
267
+
268
+ // Step-up on the CURRENT tenant resolves before the org chooser: a user who needs both
269
+ // authenticates + steps up first, then picks an org. switchTenant handles any MFA the chosen
270
+ // org requires on its own, and the isSteppedUp guard below means an already-stepped-up user is
271
+ // never re-prompted.
272
+ // login with magic code, try to step up, no other mfa, invalid max age, force_enroll -> logout, login with first factor, not-stepped up jwt -> navigate to step up
273
+ const shouldStepUp = (_window4 = window) == null ? void 0 : _window4.localStorage.getItem(_consts.SHOULD_STEP_UP_KEY);
274
+ const user = store.auth.user;
275
+ if (shouldStepUp) {
276
+ var _window5;
277
+ (_window5 = window) == null ? void 0 : _window5.localStorage.removeItem(_consts.SHOULD_STEP_UP_KEY);
278
+ }
279
+ if (stepUpUrl && shouldStepUp && !(0, _helpers3.isSteppedUp)(user)) {
280
+ return await afterAuthNavigationUtil(actions.resetLoginState, {
281
+ forceStepUpUrl: stepUpUrl
282
+ });
283
+ }
284
+ if (await shouldRouteToChooseTenant()) {
285
+ actions.setLoginState({
286
+ step: _interfaces.LoginStep.chooseTenant,
287
+ loading: false
288
+ });
289
+ // Mirror the other post-auth interstitials (e.g. promptPasskeys): navigate to the login URL
290
+ // so the ChooseTenant step actually renders even when afterAuthNavigation is invoked from an
291
+ // OAuth/social callback route.
292
+ store.auth.onRedirectTo(store.auth.routes.loginUrl, {
293
+ preserveQueryParams: true
294
+ });
295
+ return; // do NOT finalize; ChooseTenant confirm re-enters afterAuthNavigation
296
+ }
283
297
 
284
- let customLoginURL = customLoginAuthenticatedUrl;
285
- if (!customLoginAuthenticatedUrl) {
286
- var _store$auth$routes;
287
- await actions.loadCustomLoginRoutes();
288
- customLoginURL = (_store$auth$routes = store.auth.routes) == null ? void 0 : _store$auth$routes.customLoginAuthenticatedUrl;
298
+ let customLoginURL = customLoginAuthenticatedUrl;
299
+ if (!customLoginAuthenticatedUrl) {
300
+ var _store$auth$routes;
301
+ await actions.loadCustomLoginRoutes();
302
+ customLoginURL = (_store$auth$routes = store.auth.routes) == null ? void 0 : _store$auth$routes.customLoginAuthenticatedUrl;
303
+ }
304
+ return await afterAuthNavigationUtil(actions.resetLoginState, {
305
+ customLoginAuthenticatedUrl: customLoginURL,
306
+ shouldStepUpDuringLogin: !!shouldStepUp,
307
+ preventRedirectUrlOriginCleaning: (_payload$preventRedir = payload == null ? void 0 : payload.preventRedirectUrlOriginCleaning) != null ? _payload$preventRedir : false
308
+ });
309
+ } finally {
310
+ if (tenantSelectionEnabled) {
311
+ actions.setLoginState({
312
+ tenantChoicePending: false
313
+ });
314
+ }
289
315
  }
290
- return afterAuthNavigationUtil(actions.resetLoginState, {
291
- customLoginAuthenticatedUrl: customLoginURL,
292
- shouldStepUpDuringLogin: !!shouldStepUp,
293
- preventRedirectUrlOriginCleaning: (_payload$preventRedir = payload == null ? void 0 : payload.preventRedirectUrlOriginCleaning) != null ? _payload$preventRedir : false
294
- });
295
316
  };
296
317
 
297
318
  /**
@@ -13,6 +13,7 @@ const initialState = {
13
13
  email: '',
14
14
  tenants: [],
15
15
  tenantChoiceResolved: false,
16
+ tenantChoicePending: false,
16
17
  chooseTenantSwitching: false,
17
18
  chooseTenantFinalizing: false
18
19
  };
package/node/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license Frontegg v7.123.0-alpha.2
1
+ /** @license Frontegg v7.123.0
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@frontegg/redux-store",
3
- "version": "7.123.0-alpha.2",
3
+ "version": "7.123.0",
4
4
  "main": "./node/index.js",
5
5
  "license": "MIT",
6
6
  "author": "Frontegg LTD",
7
7
  "dependencies": {
8
8
  "@babel/runtime": "^7.18.6",
9
9
  "@frontegg/entitlements-javascript-commons": "1.1.2",
10
- "@frontegg/rest-api": "7.123.0-alpha.2",
10
+ "@frontegg/rest-api": "7.123.0",
11
11
  "fast-deep-equal": "3.1.3",
12
12
  "get-value": "^3.0.1",
13
13
  "proxy-compare": "^3.0.0",