@frontegg/redux-store 7.128.0 → 7.129.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.
- package/auth/LoginState/actions/afterAuthNavigation.actions.js +6 -2
- package/auth/LoginState/actions/index.js +37 -10
- package/auth/LoginState/consts.d.ts +1 -0
- package/auth/LoginState/consts.js +1 -0
- package/auth/index.js +2 -2
- package/index.js +1 -1
- package/node/auth/LoginState/actions/afterAuthNavigation.actions.js +6 -2
- package/node/auth/LoginState/actions/index.js +36 -9
- package/node/auth/LoginState/consts.js +3 -1
- package/node/auth/index.js +1 -1
- package/node/index.js +1 -1
- package/package.json +2 -2
|
@@ -80,15 +80,19 @@ export default ((store, api, sharedActions) => {
|
|
|
80
80
|
logoutUrl,
|
|
81
81
|
socialLoginCallbackUrl,
|
|
82
82
|
activateUrl,
|
|
83
|
-
activateWithOTCUrl
|
|
83
|
+
activateWithOTCUrl,
|
|
84
|
+
oidcRedirectUrl
|
|
84
85
|
} = routes;
|
|
85
86
|
let finalUrl = urlFromLocalStorage;
|
|
86
87
|
if (!finalUrl || [loginUrl, logoutUrl, socialLoginCallbackUrl, activateUrl, activateWithOTCUrl].includes(finalUrl)) {
|
|
87
88
|
finalUrl = authenticatedUrl;
|
|
88
89
|
}
|
|
90
|
+
|
|
91
|
+
// The OIDC callback's query is the IdP's code and state; the user's own query was saved with the URL.
|
|
92
|
+
const isOidcCallback = !!oidcRedirectUrl && window.location.pathname.endsWith(oidcRedirectUrl);
|
|
89
93
|
const redirectUrl = getRedirectUrl({
|
|
90
94
|
authenticatedUrl: finalUrl,
|
|
91
|
-
includeQueryParam,
|
|
95
|
+
includeQueryParam: includeQueryParam && !isOidcCallback,
|
|
92
96
|
enforceRedirectToSameSite,
|
|
93
97
|
allowedRedirectOrigins
|
|
94
98
|
});
|
|
@@ -32,11 +32,13 @@ import { clearHostedOAuthState } from '../oauthStorage';
|
|
|
32
32
|
import { SHOULD_STEP_UP_KEY } from '../../StepUpState/consts';
|
|
33
33
|
import { FronteggNativeModule, isEntitlementsDeeplyEqual } from '../../../toolkit';
|
|
34
34
|
import { REQUEST_NAME, UserVerifiedOriginTypes } from '../../interfaces';
|
|
35
|
-
import { authStrategyLoginStepMap } from '../consts';
|
|
35
|
+
import { authStrategyLoginStepMap, defaultOnRedirectTo } from '../consts';
|
|
36
36
|
import { isMfaRequired, isResetPasswordRequired } from '../../helpers';
|
|
37
37
|
import { MFAStep } from '../../MfaState/interfaces';
|
|
38
38
|
import { SamlVendors } from '../../SSOState/interfaces';
|
|
39
39
|
import { DEFAULT_RETRY_CONFIG } from '../../../constants';
|
|
40
|
+
const SSO_REDIRECT_DELAY_MS = 2000;
|
|
41
|
+
const isUsableRedirect = onRedirectTo => typeof onRedirectTo === 'function' && onRedirectTo !== defaultOnRedirectTo;
|
|
40
42
|
export default ((store, api, sharedActions) => {
|
|
41
43
|
const actions = sharedActions;
|
|
42
44
|
const contextHolder = ContextHolder.for(store.root.appName);
|
|
@@ -387,6 +389,29 @@ export default ((store, api, sharedActions) => {
|
|
|
387
389
|
callback == null ? void 0 : callback();
|
|
388
390
|
}
|
|
389
391
|
};
|
|
392
|
+
|
|
393
|
+
// v6 parity (takeLeading): a preLogin called while another is in flight is dropped.
|
|
394
|
+
let preLoginInFlight = false;
|
|
395
|
+
let latestPreLoginAttempt = 0;
|
|
396
|
+
|
|
397
|
+
// Read on use: the login box installs onRedirectTo lazily, logout() clears it and the store default is a no-op.
|
|
398
|
+
const redirectToFullPage = url => {
|
|
399
|
+
const onRedirectTo = [store.auth.onRedirectTo, contextHolder.onRedirectTo].find(isUsableRedirect);
|
|
400
|
+
if (onRedirectTo) {
|
|
401
|
+
onRedirectTo(url, {
|
|
402
|
+
refresh: true
|
|
403
|
+
});
|
|
404
|
+
} else {
|
|
405
|
+
window.location.href = url;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
const scheduleSsoRedirect = (ssoRedirectUrl, attempt) => {
|
|
409
|
+
setTimeout(() => {
|
|
410
|
+
if (attempt === latestPreLoginAttempt && store.auth.loginState.step === LoginStep.redirectToSSO) {
|
|
411
|
+
redirectToFullPage(ssoRedirectUrl);
|
|
412
|
+
}
|
|
413
|
+
}, SSO_REDIRECT_DELAY_MS);
|
|
414
|
+
};
|
|
390
415
|
const preLogin = async payload => {
|
|
391
416
|
const {
|
|
392
417
|
email,
|
|
@@ -395,11 +420,17 @@ export default ((store, api, sharedActions) => {
|
|
|
395
420
|
invitationToken,
|
|
396
421
|
callback
|
|
397
422
|
} = payload;
|
|
423
|
+
if (preLoginInFlight) {
|
|
424
|
+
callback == null ? void 0 : callback();
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
preLoginInFlight = true;
|
|
428
|
+
latestPreLoginAttempt += 1;
|
|
429
|
+
const attempt = latestPreLoginAttempt;
|
|
398
430
|
setLoginState({
|
|
399
431
|
loading: true
|
|
400
432
|
});
|
|
401
433
|
try {
|
|
402
|
-
const onRedirectTo = store.auth.onRedirectTo;
|
|
403
434
|
const tenantId = getSearchParam(TENANT_ID_PARAM_KEY);
|
|
404
435
|
const preLoginResult = await api.auth.preLoginV2(_extends({}, email ? {
|
|
405
436
|
email
|
|
@@ -420,9 +451,7 @@ export default ((store, api, sharedActions) => {
|
|
|
420
451
|
setLoginState({
|
|
421
452
|
loading: false
|
|
422
453
|
});
|
|
423
|
-
|
|
424
|
-
refresh: true
|
|
425
|
-
});
|
|
454
|
+
redirectToFullPage(address);
|
|
426
455
|
return;
|
|
427
456
|
}
|
|
428
457
|
let ssoRedirectUrl = address;
|
|
@@ -445,11 +474,7 @@ export default ((store, api, sharedActions) => {
|
|
|
445
474
|
loading: false,
|
|
446
475
|
ssoRedirectUrl
|
|
447
476
|
});
|
|
448
|
-
|
|
449
|
-
onRedirectTo(ssoRedirectUrl, {
|
|
450
|
-
refresh: true
|
|
451
|
-
});
|
|
452
|
-
}, 2000);
|
|
477
|
+
scheduleSsoRedirect(ssoRedirectUrl, attempt);
|
|
453
478
|
}
|
|
454
479
|
} else {
|
|
455
480
|
await ssoPreloginFailed(_extends({}, username ? {
|
|
@@ -473,6 +498,8 @@ export default ((store, api, sharedActions) => {
|
|
|
473
498
|
invitationToken,
|
|
474
499
|
error: e
|
|
475
500
|
}));
|
|
501
|
+
} finally {
|
|
502
|
+
preLoginInFlight = false;
|
|
476
503
|
}
|
|
477
504
|
};
|
|
478
505
|
const postLogin = async payload => {
|
|
@@ -6,5 +6,6 @@
|
|
|
6
6
|
import { AuthStrategyEnum } from '@frontegg/rest-api';
|
|
7
7
|
import { LoginStep } from './interfaces';
|
|
8
8
|
import { AuthPageRoutes } from '../interfaces';
|
|
9
|
+
export declare const defaultOnRedirectTo: () => undefined;
|
|
9
10
|
export declare const authStrategyLoginStepMap: Record<Exclude<AuthStrategyEnum, AuthStrategyEnum.NoLocalAuthentication | AuthStrategyEnum.WebAuthN>, LoginStep>;
|
|
10
11
|
export declare const defaultFronteggRoutes: AuthPageRoutes;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { AuthStrategyEnum } from '@frontegg/rest-api';
|
|
7
7
|
import { LoginStep } from './interfaces';
|
|
8
|
+
export const defaultOnRedirectTo = () => void 0;
|
|
8
9
|
export const authStrategyLoginStepMap = {
|
|
9
10
|
[AuthStrategyEnum.Code]: LoginStep.loginWithOtc,
|
|
10
11
|
[AuthStrategyEnum.EmailAndPassword]: LoginStep.loginWithPassword,
|
package/auth/index.js
CHANGED
|
@@ -37,7 +37,7 @@ import { buildTeamActions, createTeamState } from './TeamState';
|
|
|
37
37
|
import { buildTenantsActions, createTenantsState } from './TenantsState';
|
|
38
38
|
import { buildUsernamesActions, createUsernamesState } from './UsernamesState';
|
|
39
39
|
import { buildUserEmailPolicyActions, createUserEmailPolicyState } from './UsersEmailsPolicyState';
|
|
40
|
-
import { defaultFronteggRoutes } from './LoginState/consts';
|
|
40
|
+
import { defaultFronteggRoutes, defaultOnRedirectTo } from './LoginState/consts';
|
|
41
41
|
import { deepResetState, isProxy } from '../helpers';
|
|
42
42
|
import { buildEntitlementsActions } from './Entitlements';
|
|
43
43
|
import { createProxy } from '../toolkit/proxy';
|
|
@@ -91,7 +91,7 @@ export const createAuthState = _overrideState => {
|
|
|
91
91
|
overrideState = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
92
92
|
return createProxy(_extends({
|
|
93
93
|
routes: _extends({}, defaultFronteggRoutes, routes),
|
|
94
|
-
onRedirectTo:
|
|
94
|
+
onRedirectTo: defaultOnRedirectTo,
|
|
95
95
|
isAuthenticated: false,
|
|
96
96
|
isLoading: true,
|
|
97
97
|
isSSOAuth: false,
|
package/index.js
CHANGED
|
@@ -87,15 +87,19 @@ var _default = (store, api, sharedActions) => {
|
|
|
87
87
|
logoutUrl,
|
|
88
88
|
socialLoginCallbackUrl,
|
|
89
89
|
activateUrl,
|
|
90
|
-
activateWithOTCUrl
|
|
90
|
+
activateWithOTCUrl,
|
|
91
|
+
oidcRedirectUrl
|
|
91
92
|
} = routes;
|
|
92
93
|
let finalUrl = urlFromLocalStorage;
|
|
93
94
|
if (!finalUrl || [loginUrl, logoutUrl, socialLoginCallbackUrl, activateUrl, activateWithOTCUrl].includes(finalUrl)) {
|
|
94
95
|
finalUrl = authenticatedUrl;
|
|
95
96
|
}
|
|
97
|
+
|
|
98
|
+
// The OIDC callback's query is the IdP's code and state; the user's own query was saved with the URL.
|
|
99
|
+
const isOidcCallback = !!oidcRedirectUrl && window.location.pathname.endsWith(oidcRedirectUrl);
|
|
96
100
|
const redirectUrl = (0, _helpers.getRedirectUrl)({
|
|
97
101
|
authenticatedUrl: finalUrl,
|
|
98
|
-
includeQueryParam,
|
|
102
|
+
includeQueryParam: includeQueryParam && !isOidcCallback,
|
|
99
103
|
enforceRedirectToSameSite,
|
|
100
104
|
allowedRedirectOrigins
|
|
101
105
|
});
|
|
@@ -44,6 +44,8 @@ const _excluded = ["callback", "error"],
|
|
|
44
44
|
_excluded13 = ["callback"],
|
|
45
45
|
_excluded14 = ["callback"],
|
|
46
46
|
_excluded15 = ["callback"];
|
|
47
|
+
const SSO_REDIRECT_DELAY_MS = 2000;
|
|
48
|
+
const isUsableRedirect = onRedirectTo => typeof onRedirectTo === 'function' && onRedirectTo !== _consts2.defaultOnRedirectTo;
|
|
47
49
|
var _default = (store, api, sharedActions) => {
|
|
48
50
|
const actions = sharedActions;
|
|
49
51
|
const contextHolder = _restApi.ContextHolder.for(store.root.appName);
|
|
@@ -394,6 +396,29 @@ var _default = (store, api, sharedActions) => {
|
|
|
394
396
|
callback == null ? void 0 : callback();
|
|
395
397
|
}
|
|
396
398
|
};
|
|
399
|
+
|
|
400
|
+
// v6 parity (takeLeading): a preLogin called while another is in flight is dropped.
|
|
401
|
+
let preLoginInFlight = false;
|
|
402
|
+
let latestPreLoginAttempt = 0;
|
|
403
|
+
|
|
404
|
+
// Read on use: the login box installs onRedirectTo lazily, logout() clears it and the store default is a no-op.
|
|
405
|
+
const redirectToFullPage = url => {
|
|
406
|
+
const onRedirectTo = [store.auth.onRedirectTo, contextHolder.onRedirectTo].find(isUsableRedirect);
|
|
407
|
+
if (onRedirectTo) {
|
|
408
|
+
onRedirectTo(url, {
|
|
409
|
+
refresh: true
|
|
410
|
+
});
|
|
411
|
+
} else {
|
|
412
|
+
window.location.href = url;
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
const scheduleSsoRedirect = (ssoRedirectUrl, attempt) => {
|
|
416
|
+
setTimeout(() => {
|
|
417
|
+
if (attempt === latestPreLoginAttempt && store.auth.loginState.step === _interfaces.LoginStep.redirectToSSO) {
|
|
418
|
+
redirectToFullPage(ssoRedirectUrl);
|
|
419
|
+
}
|
|
420
|
+
}, SSO_REDIRECT_DELAY_MS);
|
|
421
|
+
};
|
|
397
422
|
const preLogin = async payload => {
|
|
398
423
|
const {
|
|
399
424
|
email,
|
|
@@ -402,11 +427,17 @@ var _default = (store, api, sharedActions) => {
|
|
|
402
427
|
invitationToken,
|
|
403
428
|
callback
|
|
404
429
|
} = payload;
|
|
430
|
+
if (preLoginInFlight) {
|
|
431
|
+
callback == null ? void 0 : callback();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
preLoginInFlight = true;
|
|
435
|
+
latestPreLoginAttempt += 1;
|
|
436
|
+
const attempt = latestPreLoginAttempt;
|
|
405
437
|
setLoginState({
|
|
406
438
|
loading: true
|
|
407
439
|
});
|
|
408
440
|
try {
|
|
409
|
-
const onRedirectTo = store.auth.onRedirectTo;
|
|
410
441
|
const tenantId = (0, _helpers2.getSearchParam)(_helpers2.TENANT_ID_PARAM_KEY);
|
|
411
442
|
const preLoginResult = await api.auth.preLoginV2((0, _extends2.default)({}, email ? {
|
|
412
443
|
email
|
|
@@ -427,9 +458,7 @@ var _default = (store, api, sharedActions) => {
|
|
|
427
458
|
setLoginState({
|
|
428
459
|
loading: false
|
|
429
460
|
});
|
|
430
|
-
|
|
431
|
-
refresh: true
|
|
432
|
-
});
|
|
461
|
+
redirectToFullPage(address);
|
|
433
462
|
return;
|
|
434
463
|
}
|
|
435
464
|
let ssoRedirectUrl = address;
|
|
@@ -452,11 +481,7 @@ var _default = (store, api, sharedActions) => {
|
|
|
452
481
|
loading: false,
|
|
453
482
|
ssoRedirectUrl
|
|
454
483
|
});
|
|
455
|
-
|
|
456
|
-
onRedirectTo(ssoRedirectUrl, {
|
|
457
|
-
refresh: true
|
|
458
|
-
});
|
|
459
|
-
}, 2000);
|
|
484
|
+
scheduleSsoRedirect(ssoRedirectUrl, attempt);
|
|
460
485
|
}
|
|
461
486
|
} else {
|
|
462
487
|
await ssoPreloginFailed((0, _extends2.default)({}, username ? {
|
|
@@ -480,6 +505,8 @@ var _default = (store, api, sharedActions) => {
|
|
|
480
505
|
invitationToken,
|
|
481
506
|
error: e
|
|
482
507
|
}));
|
|
508
|
+
} finally {
|
|
509
|
+
preLoginInFlight = false;
|
|
483
510
|
}
|
|
484
511
|
};
|
|
485
512
|
const postLogin = async payload => {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.defaultFronteggRoutes = exports.authStrategyLoginStepMap = void 0;
|
|
6
|
+
exports.defaultOnRedirectTo = exports.defaultFronteggRoutes = exports.authStrategyLoginStepMap = void 0;
|
|
7
7
|
var _restApi = require("@frontegg/rest-api");
|
|
8
8
|
var _interfaces = require("./interfaces");
|
|
9
9
|
/**
|
|
@@ -12,6 +12,8 @@ var _interfaces = require("./interfaces");
|
|
|
12
12
|
* please don't import from redux or from other files that import from redux
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
const defaultOnRedirectTo = () => void 0;
|
|
16
|
+
exports.defaultOnRedirectTo = defaultOnRedirectTo;
|
|
15
17
|
const authStrategyLoginStepMap = {
|
|
16
18
|
[_restApi.AuthStrategyEnum.Code]: _interfaces.LoginStep.loginWithOtc,
|
|
17
19
|
[_restApi.AuthStrategyEnum.EmailAndPassword]: _interfaces.LoginStep.loginWithPassword,
|
package/node/auth/index.js
CHANGED
|
@@ -559,7 +559,7 @@ const createAuthState = _overrideState => {
|
|
|
559
559
|
overrideState = (0, _objectWithoutPropertiesLoose2.default)(_ref, _excluded);
|
|
560
560
|
return (0, _proxy.createProxy)((0, _extends2.default)({
|
|
561
561
|
routes: (0, _extends2.default)({}, _consts.defaultFronteggRoutes, routes),
|
|
562
|
-
onRedirectTo:
|
|
562
|
+
onRedirectTo: _consts.defaultOnRedirectTo,
|
|
563
563
|
isAuthenticated: false,
|
|
564
564
|
isLoading: true,
|
|
565
565
|
isSSOAuth: false,
|
package/node/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontegg/redux-store",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.129.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.
|
|
10
|
+
"@frontegg/rest-api": "7.129.0",
|
|
11
11
|
"fast-deep-equal": "3.1.3",
|
|
12
12
|
"get-value": "^3.0.1",
|
|
13
13
|
"proxy-compare": "^3.0.0",
|