@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.
@@ -202,3 +202,4 @@ declare type DispatchedActions = {
202
202
  };
203
203
  export declare type LoginActions = DispatchedActions;
204
204
  export { loginState, reducers as loginReducers, actions as loginActions };
205
+ export { getRedirectUrl } from './utils';
@@ -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>;
@@ -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 url = new URL((_window = window) == null ? void 0 : _window.location.href);
67
- let redirectUrl = authenticatedUrl;
68
- if (url.searchParams.get('redirectUrl')) {
69
- var _url$searchParams$get;
70
- redirectUrl = (_url$searchParams$get = url.searchParams.get('redirectUrl')) != null ? _url$searchParams$get : authenticatedUrl;
71
- } else if (includeQueryParam) {
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 _window2;
414
- const url = new URL((_window2 = window) == null ? void 0 : _window2.location.href);
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 _window3;
513
- return ((_window3 = window) != null ? _window3 : document).location.pathname;
512
+ var _window2;
513
+ return ((_window2 = window) != null ? _window2 : document).location.pathname;
514
514
  } else {
515
- var _window4;
516
- const uri = (((_window4 = window) != null ? _window4 : document).location.hash || '#').substring(1);
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
@@ -1,4 +1,4 @@
1
- /** @license Frontegg v6.78.0
1
+ /** @license Frontegg v6.79.0-alpha.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.
@@ -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 url = new URL((_window = window) == null ? void 0 : _window.location.href);
83
- let redirectUrl = authenticatedUrl;
84
- if (url.searchParams.get('redirectUrl')) {
85
- var _url$searchParams$get;
86
- redirectUrl = (_url$searchParams$get = url.searchParams.get('redirectUrl')) != null ? _url$searchParams$get : authenticatedUrl;
87
- } else if (includeQueryParam) {
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 _window2;
431
- const url = new URL((_window2 = window) == null ? void 0 : _window2.location.href);
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 _window3;
530
- return ((_window3 = window) != null ? _window3 : document).location.pathname;
529
+ var _window2;
530
+ return ((_window2 = window) != null ? _window2 : document).location.pathname;
531
531
  } else {
532
- var _window4;
533
- const uri = (((_window4 = window) != null ? _window4 : document).location.hash || '#').substring(1);
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
@@ -1,4 +1,4 @@
1
- /** @license Frontegg v6.78.0
1
+ /** @license Frontegg v6.79.0-alpha.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontegg/redux-store",
3
- "version": "6.78.0",
3
+ "version": "6.79.0-alpha.0",
4
4
  "main": "./node/index.js",
5
5
  "license": "MIT",
6
6
  "author": "Frontegg LTD",