@frontegg/redux-store 6.78.0 → 6.79.0-alpha.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/index.d.ts +1 -0
- package/auth/LoginState/index.js +2 -1
- package/auth/LoginState/saga.d.ts +2 -0
- package/auth/LoginState/saga.js +20 -17
- package/auth/LoginState/utils.d.ts +6 -0
- package/auth/LoginState/utils.js +39 -0
- package/index.js +1 -1
- package/node/auth/LoginState/index.js +7 -0
- package/node/auth/LoginState/saga.js +20 -17
- package/node/auth/LoginState/utils.js +46 -0
- package/node/index.js +1 -1
- package/package.json +1 -1
package/auth/LoginState/index.js
CHANGED
|
@@ -126,4 +126,5 @@ const actions = {
|
|
|
126
126
|
* contains the same functions in reducers and actions
|
|
127
127
|
*/
|
|
128
128
|
const Matcher = {};
|
|
129
|
-
export { loginState, reducers as loginReducers, actions as loginActions };
|
|
129
|
+
export { loginState, reducers as loginReducers, actions as loginActions };
|
|
130
|
+
export { getRedirectUrl } from './utils';
|
|
@@ -6,6 +6,8 @@ import { MFAState } from '../MfaState/interfaces';
|
|
|
6
6
|
export declare function afterAuthNavigation(): Generator<Promise<unknown> | import("redux-saga/effects").SelectEffect, void, {
|
|
7
7
|
routes: any;
|
|
8
8
|
includeQueryParam: any;
|
|
9
|
+
enforceRedirectToSameSite?: false | undefined;
|
|
10
|
+
allowedRedirectOrigins?: never[] | undefined;
|
|
9
11
|
}>;
|
|
10
12
|
export declare function refreshMetadata(): Generator<import("redux-saga/effects").PutEffect<{
|
|
11
13
|
payload: Partial<AuthState>;
|
package/auth/LoginState/saga.js
CHANGED
|
@@ -34,6 +34,7 @@ import { ResetPhoneNumberStep } from '../ResetPhoneNumberState/interfaces';
|
|
|
34
34
|
import { base64urlDecode, delay, publicKeyCredentialToJSON } from '../utils';
|
|
35
35
|
import { loadPublicAuthStrategiesPolicy } from '../SecurityPolicyState/saga';
|
|
36
36
|
import { useIsPasskeysEnabled } from '../PasskeysState/helpers';
|
|
37
|
+
import { getRedirectUrl } from './utils';
|
|
37
38
|
const authStrategyLoginStepMap = {
|
|
38
39
|
[AuthStrategyEnum.Code]: LoginStep.loginWithOtc,
|
|
39
40
|
[AuthStrategyEnum.EmailAndPassword]: LoginStep.loginWithPassword,
|
|
@@ -41,11 +42,12 @@ const authStrategyLoginStepMap = {
|
|
|
41
42
|
[AuthStrategyEnum.SmsCode]: LoginStep.loginWithSmsOtc
|
|
42
43
|
};
|
|
43
44
|
export function* afterAuthNavigation() {
|
|
44
|
-
var _window;
|
|
45
45
|
const onRedirectTo = ContextHolder.onRedirectTo;
|
|
46
46
|
const {
|
|
47
47
|
routes,
|
|
48
|
-
includeQueryParam
|
|
48
|
+
includeQueryParam,
|
|
49
|
+
enforceRedirectToSameSite = false,
|
|
50
|
+
allowedRedirectOrigins = []
|
|
49
51
|
} = yield select(state => state.auth);
|
|
50
52
|
const {
|
|
51
53
|
loginUrl,
|
|
@@ -63,14 +65,12 @@ export function* afterAuthNavigation() {
|
|
|
63
65
|
window.localStorage.removeItem(FRONTEGG_AFTER_AUTH_REDIRECT_URL);
|
|
64
66
|
yield delay(200);
|
|
65
67
|
put(actions.resetLoginState());
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
redirectUrl += window.location.search;
|
|
73
|
-
}
|
|
68
|
+
const redirectUrl = getRedirectUrl({
|
|
69
|
+
authenticatedUrl,
|
|
70
|
+
includeQueryParam,
|
|
71
|
+
enforceRedirectToSameSite,
|
|
72
|
+
allowedRedirectOrigins
|
|
73
|
+
});
|
|
74
74
|
onRedirectTo(redirectUrl, {
|
|
75
75
|
refresh: redirectUrl.startsWith('http')
|
|
76
76
|
});
|
|
@@ -410,8 +410,8 @@ function* refreshTokenEmbeddedSocialLogins() {
|
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
412
|
function* handleRedirectRefreshToken(shouldNavigateToRegisterQuickLogin) {
|
|
413
|
-
var
|
|
414
|
-
const url = new URL((
|
|
413
|
+
var _window;
|
|
414
|
+
const url = new URL((_window = window) == null ? void 0 : _window.location.href);
|
|
415
415
|
const onRedirectTo = ContextHolder.onRedirectTo;
|
|
416
416
|
const {
|
|
417
417
|
routes,
|
|
@@ -509,11 +509,11 @@ function* requestAuthorizeSSR({
|
|
|
509
509
|
}
|
|
510
510
|
const getUri = urlStrategy => {
|
|
511
511
|
if (urlStrategy === 'path') {
|
|
512
|
-
var
|
|
513
|
-
return ((
|
|
512
|
+
var _window2;
|
|
513
|
+
return ((_window2 = window) != null ? _window2 : document).location.pathname;
|
|
514
514
|
} else {
|
|
515
|
-
var
|
|
516
|
-
const uri = (((
|
|
515
|
+
var _window3;
|
|
516
|
+
const uri = (((_window3 = window) != null ? _window3 : document).location.hash || '#').substring(1);
|
|
517
517
|
if (uri.indexOf('?') !== -1) {
|
|
518
518
|
return uri.substring(0, uri.indexOf('?'));
|
|
519
519
|
} else {
|
|
@@ -1449,9 +1449,12 @@ function* handleVerifyMFAResponse({
|
|
|
1449
1449
|
if (user.id) {
|
|
1450
1450
|
localStorage.setItem('userId', user.id);
|
|
1451
1451
|
}
|
|
1452
|
+
const {
|
|
1453
|
+
step: mfaStep
|
|
1454
|
+
} = yield select(state => state.auth.mfaState);
|
|
1452
1455
|
if (loginState.flow === LoginFlow.Login) {
|
|
1453
1456
|
const shouldShowPrompt = yield call(shouldShowPromptPasskeys);
|
|
1454
|
-
if (shouldShowPrompt) {
|
|
1457
|
+
if (mfaStep === MFAStep.smsVerifyCode && shouldShowPrompt) {
|
|
1455
1458
|
yield put(actions.setLoginState({
|
|
1456
1459
|
step: LoginStep.promptPasskeys,
|
|
1457
1460
|
loading: false
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const getRedirectUrl: ({ authenticatedUrl, enforceRedirectToSameSite, allowedRedirectOrigins, includeQueryParam, }: {
|
|
2
|
+
authenticatedUrl: string;
|
|
3
|
+
enforceRedirectToSameSite: boolean;
|
|
4
|
+
allowedRedirectOrigins: string[];
|
|
5
|
+
includeQueryParam: boolean;
|
|
6
|
+
}) => string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const isAbsoluteUrl = path => {
|
|
2
|
+
try {
|
|
3
|
+
new URL(path);
|
|
4
|
+
return true;
|
|
5
|
+
} catch (e) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
const isValidRedirectUrl = (redirectUrl, allowedRedirectOrigins) => {
|
|
10
|
+
const currentUrl = new URL(window.location.href);
|
|
11
|
+
const redirectURL = new URL(redirectUrl);
|
|
12
|
+
const isSameSite = redirectURL.origin === currentUrl.origin;
|
|
13
|
+
const isOriginInWhiteList = allowedRedirectOrigins.includes(redirectURL.origin);
|
|
14
|
+
return isOriginInWhiteList || isSameSite;
|
|
15
|
+
};
|
|
16
|
+
export const getRedirectUrl = ({
|
|
17
|
+
authenticatedUrl,
|
|
18
|
+
enforceRedirectToSameSite,
|
|
19
|
+
allowedRedirectOrigins,
|
|
20
|
+
includeQueryParam
|
|
21
|
+
}) => {
|
|
22
|
+
const currentUrl = new URL(window.location.href);
|
|
23
|
+
let redirectUrl = authenticatedUrl;
|
|
24
|
+
const redirectUrlQueryParam = currentUrl.searchParams.get('redirectUrl');
|
|
25
|
+
if (redirectUrlQueryParam) {
|
|
26
|
+
if (!enforceRedirectToSameSite || !isAbsoluteUrl(redirectUrlQueryParam)) {
|
|
27
|
+
redirectUrl = redirectUrlQueryParam;
|
|
28
|
+
} else {
|
|
29
|
+
if (isValidRedirectUrl(redirectUrlQueryParam, allowedRedirectOrigins)) {
|
|
30
|
+
redirectUrl = redirectUrlQueryParam;
|
|
31
|
+
} else {
|
|
32
|
+
console.warn('The redirect url param is not valid, the origin is a different site');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
} else if (includeQueryParam) {
|
|
36
|
+
redirectUrl += window.location.search;
|
|
37
|
+
}
|
|
38
|
+
return redirectUrl;
|
|
39
|
+
};
|
package/index.js
CHANGED
|
@@ -3,11 +3,18 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "getRedirectUrl", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _utils2.getRedirectUrl;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
exports.loginState = exports.loginReducers = exports.loginActions = void 0;
|
|
7
13
|
var _toolkit = require("@reduxjs/toolkit");
|
|
8
14
|
var _interfaces = require("./interfaces");
|
|
9
15
|
var _utils = require("../utils");
|
|
10
16
|
var _constants = require("../../constants");
|
|
17
|
+
var _utils2 = require("./utils");
|
|
11
18
|
const loginState = {
|
|
12
19
|
flow: _interfaces.LoginFlow.Login,
|
|
13
20
|
step: _interfaces.LoginStep.preLogin,
|
|
@@ -32,6 +32,7 @@ var _interfaces5 = require("../ResetPhoneNumberState/interfaces");
|
|
|
32
32
|
var _utils = require("../utils");
|
|
33
33
|
var _saga3 = require("../SecurityPolicyState/saga");
|
|
34
34
|
var _helpers2 = require("../PasskeysState/helpers");
|
|
35
|
+
var _utils2 = require("./utils");
|
|
35
36
|
const _excluded = ["callback"],
|
|
36
37
|
_excluded2 = ["callback"],
|
|
37
38
|
_excluded3 = ["callback"],
|
|
@@ -57,11 +58,12 @@ const authStrategyLoginStepMap = {
|
|
|
57
58
|
[_restApi.AuthStrategyEnum.SmsCode]: _interfaces2.LoginStep.loginWithSmsOtc
|
|
58
59
|
};
|
|
59
60
|
function* afterAuthNavigation() {
|
|
60
|
-
var _window;
|
|
61
61
|
const onRedirectTo = _restApi.ContextHolder.onRedirectTo;
|
|
62
62
|
const {
|
|
63
63
|
routes,
|
|
64
|
-
includeQueryParam
|
|
64
|
+
includeQueryParam,
|
|
65
|
+
enforceRedirectToSameSite = false,
|
|
66
|
+
allowedRedirectOrigins = []
|
|
65
67
|
} = yield (0, _effects.select)(state => state.auth);
|
|
66
68
|
const {
|
|
67
69
|
loginUrl,
|
|
@@ -79,14 +81,12 @@ function* afterAuthNavigation() {
|
|
|
79
81
|
window.localStorage.removeItem(_constants.FRONTEGG_AFTER_AUTH_REDIRECT_URL);
|
|
80
82
|
yield (0, _utils.delay)(200);
|
|
81
83
|
(0, _effects.put)(_reducer.actions.resetLoginState());
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
redirectUrl += window.location.search;
|
|
89
|
-
}
|
|
84
|
+
const redirectUrl = (0, _utils2.getRedirectUrl)({
|
|
85
|
+
authenticatedUrl,
|
|
86
|
+
includeQueryParam,
|
|
87
|
+
enforceRedirectToSameSite,
|
|
88
|
+
allowedRedirectOrigins
|
|
89
|
+
});
|
|
90
90
|
onRedirectTo(redirectUrl, {
|
|
91
91
|
refresh: redirectUrl.startsWith('http')
|
|
92
92
|
});
|
|
@@ -427,8 +427,8 @@ function* refreshTokenEmbeddedSocialLogins() {
|
|
|
427
427
|
}
|
|
428
428
|
}
|
|
429
429
|
function* handleRedirectRefreshToken(shouldNavigateToRegisterQuickLogin) {
|
|
430
|
-
var
|
|
431
|
-
const url = new URL((
|
|
430
|
+
var _window;
|
|
431
|
+
const url = new URL((_window = window) == null ? void 0 : _window.location.href);
|
|
432
432
|
const onRedirectTo = _restApi.ContextHolder.onRedirectTo;
|
|
433
433
|
const {
|
|
434
434
|
routes,
|
|
@@ -526,11 +526,11 @@ function* requestAuthorizeSSR({
|
|
|
526
526
|
}
|
|
527
527
|
const getUri = urlStrategy => {
|
|
528
528
|
if (urlStrategy === 'path') {
|
|
529
|
-
var
|
|
530
|
-
return ((
|
|
529
|
+
var _window2;
|
|
530
|
+
return ((_window2 = window) != null ? _window2 : document).location.pathname;
|
|
531
531
|
} else {
|
|
532
|
-
var
|
|
533
|
-
const uri = (((
|
|
532
|
+
var _window3;
|
|
533
|
+
const uri = (((_window3 = window) != null ? _window3 : document).location.hash || '#').substring(1);
|
|
534
534
|
if (uri.indexOf('?') !== -1) {
|
|
535
535
|
return uri.substring(0, uri.indexOf('?'));
|
|
536
536
|
} else {
|
|
@@ -1466,9 +1466,12 @@ function* handleVerifyMFAResponse({
|
|
|
1466
1466
|
if (user.id) {
|
|
1467
1467
|
localStorage.setItem('userId', user.id);
|
|
1468
1468
|
}
|
|
1469
|
+
const {
|
|
1470
|
+
step: mfaStep
|
|
1471
|
+
} = yield (0, _effects.select)(state => state.auth.mfaState);
|
|
1469
1472
|
if (loginState.flow === _interfaces2.LoginFlow.Login) {
|
|
1470
1473
|
const shouldShowPrompt = yield (0, _effects.call)(shouldShowPromptPasskeys);
|
|
1471
|
-
if (shouldShowPrompt) {
|
|
1474
|
+
if (mfaStep === _interfaces3.MFAStep.smsVerifyCode && shouldShowPrompt) {
|
|
1472
1475
|
yield (0, _effects.put)(_reducer.actions.setLoginState({
|
|
1473
1476
|
step: _interfaces2.LoginStep.promptPasskeys,
|
|
1474
1477
|
loading: false
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getRedirectUrl = void 0;
|
|
7
|
+
const isAbsoluteUrl = path => {
|
|
8
|
+
try {
|
|
9
|
+
new URL(path);
|
|
10
|
+
return true;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const isValidRedirectUrl = (redirectUrl, allowedRedirectOrigins) => {
|
|
16
|
+
const currentUrl = new URL(window.location.href);
|
|
17
|
+
const redirectURL = new URL(redirectUrl);
|
|
18
|
+
const isSameSite = redirectURL.origin === currentUrl.origin;
|
|
19
|
+
const isOriginInWhiteList = allowedRedirectOrigins.includes(redirectURL.origin);
|
|
20
|
+
return isOriginInWhiteList || isSameSite;
|
|
21
|
+
};
|
|
22
|
+
const getRedirectUrl = ({
|
|
23
|
+
authenticatedUrl,
|
|
24
|
+
enforceRedirectToSameSite,
|
|
25
|
+
allowedRedirectOrigins,
|
|
26
|
+
includeQueryParam
|
|
27
|
+
}) => {
|
|
28
|
+
const currentUrl = new URL(window.location.href);
|
|
29
|
+
let redirectUrl = authenticatedUrl;
|
|
30
|
+
const redirectUrlQueryParam = currentUrl.searchParams.get('redirectUrl');
|
|
31
|
+
if (redirectUrlQueryParam) {
|
|
32
|
+
if (!enforceRedirectToSameSite || !isAbsoluteUrl(redirectUrlQueryParam)) {
|
|
33
|
+
redirectUrl = redirectUrlQueryParam;
|
|
34
|
+
} else {
|
|
35
|
+
if (isValidRedirectUrl(redirectUrlQueryParam, allowedRedirectOrigins)) {
|
|
36
|
+
redirectUrl = redirectUrlQueryParam;
|
|
37
|
+
} else {
|
|
38
|
+
console.warn('The redirect url param is not valid, the origin is a different site');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} else if (includeQueryParam) {
|
|
42
|
+
redirectUrl += window.location.search;
|
|
43
|
+
}
|
|
44
|
+
return redirectUrl;
|
|
45
|
+
};
|
|
46
|
+
exports.getRedirectUrl = getRedirectUrl;
|
package/node/index.js
CHANGED