@frontegg/redux-store 7.131.0-alpha.1 → 7.131.0-alpha.2
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/hostedLoginAuthorize.actions.js +5 -1
- package/auth/LoginState/actions/index.d.ts +15 -1
- package/auth/LoginState/actions/index.js +5 -4
- package/auth/StepUpState/actions/generateStepUpSession.actions.js +1 -2
- package/auth/helpers.d.ts +4 -3
- package/auth/helpers.js +12 -7
- package/index.js +1 -1
- package/node/auth/LoginState/actions/hostedLoginAuthorize.actions.js +4 -0
- package/node/auth/LoginState/actions/index.js +4 -3
- package/node/auth/StepUpState/actions/generateStepUpSession.actions.js +1 -2
- package/node/auth/helpers.js +14 -9
- package/node/index.js +1 -1
- package/package.json +2 -2
|
@@ -3,7 +3,7 @@ import { createRandomString, generateCodeChallenge, GTMEventAction, isSsoEnforce
|
|
|
3
3
|
import { HOSTED_LOGIN_VERIFIER_KEY } from '../../../constants';
|
|
4
4
|
import { isEnforceSsoOnTenantAccessEnabled } from '@frontegg/rest-api';
|
|
5
5
|
import { getBaseNameWithoutSlashSuffix, getSearchParam, isOauthCallbackRoute, TENANT_ID_PARAM_KEY } from '../helpers';
|
|
6
|
-
import { getUri, getUrlDerivedStepUp, isSteppedUp, redirectByStepUpUrl, restoreTabTenantUnlessSsoCallback } from '../../helpers';
|
|
6
|
+
import { getUri, getUrlDerivedStepUp, isSteppedUp, isOnLoginCodeCallbackRoute, redirectByStepUpUrl, restoreTabTenantUnlessSsoCallback } from '../../helpers';
|
|
7
7
|
import { SHOULD_STEP_UP_KEY } from '../../StepUpState/consts';
|
|
8
8
|
import { FronteggNativeModule } from '../../../toolkit';
|
|
9
9
|
export default ((store, api, sharedActions) => {
|
|
@@ -27,6 +27,10 @@ export default ((store, api, sharedActions) => {
|
|
|
27
27
|
response = await api.auth.silentOAuthRefreshTokenV2();
|
|
28
28
|
} catch (error) {
|
|
29
29
|
var _store$auth$user, _error$errorContext;
|
|
30
|
+
// on the hosted login callback the page finishes the login with its code: fail as with the flag off
|
|
31
|
+
if (isOnLoginCodeCallbackRoute(store)) {
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
30
34
|
// the tenant requires SSO: hosted login for that tenant, not the plain one the caller falls back to
|
|
31
35
|
if (await actions.__redirectToSsoIfRequired(error)) {
|
|
32
36
|
return;
|
|
@@ -33,7 +33,21 @@ declare const _default: (store: FronteggState, api: RestApi, sharedActions: Shar
|
|
|
33
33
|
requestHostedLoginAuthorize: (additionalParams?: Record<string, string>) => Promise<void>;
|
|
34
34
|
requestHostedLoginAuthorizeV2: (payload?: {
|
|
35
35
|
additionalParams?: Record<string, string>;
|
|
36
|
-
shouldRedirectToLogin
|
|
36
|
+
shouldRedirectToLogin
|
|
37
|
+
/**
|
|
38
|
+
* Handles a hosted (OAuth) token refresh refused because the tenant requires SSO.
|
|
39
|
+
* ssoRequired: true sends the user to SSO, like login. ssoRequired: false renews once more for the tenant of the
|
|
40
|
+
* current token, which keeps the session: OAuth doesn't use up the refresh token on this refusal.
|
|
41
|
+
* @returns true when handled, false when the caller should log out
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
? /**
|
|
45
|
+
* Handles a hosted (OAuth) token refresh refused because the tenant requires SSO.
|
|
46
|
+
* ssoRequired: true sends the user to SSO, like login. ssoRequired: false renews once more for the tenant of the
|
|
47
|
+
* current token, which keeps the session: OAuth doesn't use up the refresh token on this refusal.
|
|
48
|
+
* @returns true when handled, false when the caller should log out
|
|
49
|
+
* @private
|
|
50
|
+
*/: boolean;
|
|
37
51
|
firstTime?: boolean;
|
|
38
52
|
loginDirectAction?: import("../interfaces").LoginDirectAction;
|
|
39
53
|
}) => Promise<void>;
|
|
@@ -33,7 +33,7 @@ import { SHOULD_STEP_UP_KEY } from '../../StepUpState/consts';
|
|
|
33
33
|
import { FronteggNativeModule, isEntitlementsDeeplyEqual } from '../../../toolkit';
|
|
34
34
|
import { REQUEST_NAME, UserVerifiedOriginTypes } from '../../interfaces';
|
|
35
35
|
import { authStrategyLoginStepMap, defaultOnRedirectTo } from '../consts';
|
|
36
|
-
import { isMfaRequired, isOnAuthPageRoute,
|
|
36
|
+
import { isMfaRequired, isOnAuthPageRoute, isOnLoginCodeCallbackRoute, isResetPasswordRequired, restoreTabTenantUnlessSsoCallback, setAfterAuthRedirectUrlForStepUp } from '../../helpers';
|
|
37
37
|
import { MFAStep } from '../../MfaState/interfaces';
|
|
38
38
|
import { SamlVendors } from '../../SSOState/interfaces';
|
|
39
39
|
import { DEFAULT_RETRY_CONFIG } from '../../../constants';
|
|
@@ -129,7 +129,8 @@ export default ((store, api, sharedActions) => {
|
|
|
129
129
|
*/
|
|
130
130
|
const __handleSsoEnforcementRefreshError = async (e, isSsoEnforcementRetry, refreshForTenant) => {
|
|
131
131
|
var _store$auth$user;
|
|
132
|
-
|
|
132
|
+
// on a login callback the page finishes the login with its code: log out as with the flag off, no new SSO trip
|
|
133
|
+
if (!isEnforceSsoOnTenantAccessEnabled(store.root.appName) || !isSsoEnforcementError(e) || isOnLoginCodeCallbackRoute(store)) {
|
|
133
134
|
return false;
|
|
134
135
|
}
|
|
135
136
|
if (await __redirectToSsoIfRequired(e)) {
|
|
@@ -246,8 +247,8 @@ export default ((store, api, sharedActions) => {
|
|
|
246
247
|
}
|
|
247
248
|
} catch (e) {
|
|
248
249
|
// a refused identity refresh has already used up the refresh token: no retry, only the SSO redirect, except on
|
|
249
|
-
//
|
|
250
|
-
if (isEnforceSsoOnTenantAccessEnabled(store.root.appName) && !
|
|
250
|
+
// a login callback, where the page itself completes the login
|
|
251
|
+
if (isEnforceSsoOnTenantAccessEnabled(store.root.appName) && !isOnLoginCodeCallbackRoute(store) && (await __redirectToSsoIfRequired(e))) {
|
|
251
252
|
return;
|
|
252
253
|
}
|
|
253
254
|
contextHolder.setAccessToken(null);
|
|
@@ -94,12 +94,11 @@ export default ((store, api, sharedActions) => {
|
|
|
94
94
|
}
|
|
95
95
|
callback == null ? void 0 : callback(true);
|
|
96
96
|
} catch (e) {
|
|
97
|
-
callback == null ? void 0 : callback(false);
|
|
98
|
-
|
|
99
97
|
// the session's tenant requires SSO: its SSO login steps the user up, instead of logging them out
|
|
100
98
|
if (await actions.__redirectToSsoIfRequired(e)) {
|
|
101
99
|
return;
|
|
102
100
|
}
|
|
101
|
+
callback == null ? void 0 : callback(false);
|
|
103
102
|
await __handleStepUpError(e);
|
|
104
103
|
}
|
|
105
104
|
};
|
package/auth/helpers.d.ts
CHANGED
|
@@ -9,10 +9,11 @@ export declare const isResetPasswordRequired: (user: ILoginResponse, appName: st
|
|
|
9
9
|
export declare const mapMetaDataObjectToActions: (obj: any, path?: string[]) => CommitChangeDto[];
|
|
10
10
|
export declare const getUri: (urlStrategy: FronteggState["root"]["urlStrategy"]) => string;
|
|
11
11
|
/**
|
|
12
|
-
* On the OIDC callback the page still has to finish the
|
|
13
|
-
* a reason to go
|
|
12
|
+
* On the OIDC or hosted login callback the page still has to finish the login with its code: a refresh refused before
|
|
13
|
+
* that is not a reason to go to SSO again. On the OIDC callback the IdP would send the user straight back here, forever;
|
|
14
|
+
* on the hosted callback a new hosted login would replace the PKCE verifier the code exchange needs.
|
|
14
15
|
*/
|
|
15
|
-
export declare const
|
|
16
|
+
export declare const isOnLoginCodeCallbackRoute: (store: FronteggState) => boolean;
|
|
16
17
|
/**
|
|
17
18
|
* After a switch refused for SSO the tab points at the SSO tenant. Its SSO login comes back on a callback route and
|
|
18
19
|
* keeps it; any other page load means the user didn't finish that login, so the tab goes back to its tenant.
|
package/auth/helpers.js
CHANGED
|
@@ -2,7 +2,7 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
|
|
|
2
2
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
3
|
const _excluded = ["phoneNumber", "email", "username"],
|
|
4
4
|
_excluded2 = ["authenticatedUrl"];
|
|
5
|
-
import { ContextHolder, restoreTabTenantBeforeSsoSwitch
|
|
5
|
+
import { ContextHolder, restoreTabTenantBeforeSsoSwitch } from '@frontegg/rest-api';
|
|
6
6
|
import { defaultFronteggRoutes } from './LoginState/consts';
|
|
7
7
|
export * from './Entitlements/helpers';
|
|
8
8
|
export * from './LoginState/helpers';
|
|
@@ -67,15 +67,18 @@ const getCurrentRoutes = urlStrategy => {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
|
-
* On the OIDC callback the page still has to finish the
|
|
71
|
-
* a reason to go
|
|
70
|
+
* On the OIDC or hosted login callback the page still has to finish the login with its code: a refresh refused before
|
|
71
|
+
* that is not a reason to go to SSO again. On the OIDC callback the IdP would send the user straight back here, forever;
|
|
72
|
+
* on the hosted callback a new hosted login would replace the PKCE verifier the code exchange needs.
|
|
72
73
|
*/
|
|
73
|
-
export const
|
|
74
|
+
export const isOnLoginCodeCallbackRoute = store => {
|
|
74
75
|
var _store$root$urlStrate;
|
|
75
76
|
const {
|
|
76
|
-
oidcRedirectUrl
|
|
77
|
+
oidcRedirectUrl,
|
|
78
|
+
hostedLoginRedirectUrl
|
|
77
79
|
} = _extends({}, defaultFronteggRoutes, store.auth.routes);
|
|
78
|
-
|
|
80
|
+
const currentRoutes = getCurrentRoutes((_store$root$urlStrate = store.root.urlStrategy) != null ? _store$root$urlStrate : 'path');
|
|
81
|
+
return [oidcRedirectUrl, hostedLoginRedirectUrl].some(route => !!route && currentRoutes.some(currentRoute => currentRoute.endsWith(route)));
|
|
79
82
|
};
|
|
80
83
|
|
|
81
84
|
/**
|
|
@@ -84,7 +87,9 @@ export const isOnOidcCallbackRoute = store => {
|
|
|
84
87
|
*/
|
|
85
88
|
export const restoreTabTenantUnlessSsoCallback = store => {
|
|
86
89
|
var _store$root$urlStrate2;
|
|
87
|
-
|
|
90
|
+
// Flags load in parallel with the first refresh. Recover an existing marker
|
|
91
|
+
// before choosing that refresh's tenant, even if flags are not available yet.
|
|
92
|
+
if (!ContextHolder.for(store.root.appName).isSessionPerTenantEnabled()) {
|
|
88
93
|
return;
|
|
89
94
|
}
|
|
90
95
|
const {
|
package/index.js
CHANGED
|
@@ -34,6 +34,10 @@ var _default = (store, api, sharedActions) => {
|
|
|
34
34
|
response = await api.auth.silentOAuthRefreshTokenV2();
|
|
35
35
|
} catch (error) {
|
|
36
36
|
var _store$auth$user, _error$errorContext;
|
|
37
|
+
// on the hosted login callback the page finishes the login with its code: fail as with the flag off
|
|
38
|
+
if ((0, _helpers3.isOnLoginCodeCallbackRoute)(store)) {
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
37
41
|
// the tenant requires SSO: hosted login for that tenant, not the plain one the caller falls back to
|
|
38
42
|
if (await actions.__redirectToSsoIfRequired(error)) {
|
|
39
43
|
return;
|
|
@@ -136,7 +136,8 @@ var _default = (store, api, sharedActions) => {
|
|
|
136
136
|
*/
|
|
137
137
|
const __handleSsoEnforcementRefreshError = async (e, isSsoEnforcementRetry, refreshForTenant) => {
|
|
138
138
|
var _store$auth$user;
|
|
139
|
-
|
|
139
|
+
// on a login callback the page finishes the login with its code: log out as with the flag off, no new SSO trip
|
|
140
|
+
if (!(0, _restApi.isEnforceSsoOnTenantAccessEnabled)(store.root.appName) || !(0, _helpers.isSsoEnforcementError)(e) || (0, _helpers3.isOnLoginCodeCallbackRoute)(store)) {
|
|
140
141
|
return false;
|
|
141
142
|
}
|
|
142
143
|
if (await __redirectToSsoIfRequired(e)) {
|
|
@@ -253,8 +254,8 @@ var _default = (store, api, sharedActions) => {
|
|
|
253
254
|
}
|
|
254
255
|
} catch (e) {
|
|
255
256
|
// a refused identity refresh has already used up the refresh token: no retry, only the SSO redirect, except on
|
|
256
|
-
//
|
|
257
|
-
if ((0, _restApi.isEnforceSsoOnTenantAccessEnabled)(store.root.appName) && !(0, _helpers3.
|
|
257
|
+
// a login callback, where the page itself completes the login
|
|
258
|
+
if ((0, _restApi.isEnforceSsoOnTenantAccessEnabled)(store.root.appName) && !(0, _helpers3.isOnLoginCodeCallbackRoute)(store) && (await __redirectToSsoIfRequired(e))) {
|
|
258
259
|
return;
|
|
259
260
|
}
|
|
260
261
|
contextHolder.setAccessToken(null);
|
|
@@ -100,12 +100,11 @@ var _default = (store, api, sharedActions) => {
|
|
|
100
100
|
}
|
|
101
101
|
callback == null ? void 0 : callback(true);
|
|
102
102
|
} catch (e) {
|
|
103
|
-
callback == null ? void 0 : callback(false);
|
|
104
|
-
|
|
105
103
|
// the session's tenant requires SSO: its SSO login steps the user up, instead of logging them out
|
|
106
104
|
if (await actions.__redirectToSsoIfRequired(e)) {
|
|
107
105
|
return;
|
|
108
106
|
}
|
|
107
|
+
callback == null ? void 0 : callback(false);
|
|
109
108
|
await __handleStepUpError(e);
|
|
110
109
|
}
|
|
111
110
|
};
|
package/node/auth/helpers.js
CHANGED
|
@@ -9,13 +9,13 @@ var _exportNames = {
|
|
|
9
9
|
isResetPasswordRequired: true,
|
|
10
10
|
mapMetaDataObjectToActions: true,
|
|
11
11
|
getUri: true,
|
|
12
|
-
|
|
12
|
+
isOnLoginCodeCallbackRoute: true,
|
|
13
13
|
restoreTabTenantUnlessSsoCallback: true,
|
|
14
14
|
prepareIdentifiersForSignup: true,
|
|
15
15
|
isOnAuthPageRoute: true,
|
|
16
16
|
isAuthRoute: true
|
|
17
17
|
};
|
|
18
|
-
exports.restoreTabTenantUnlessSsoCallback = exports.prepareIdentifiersForSignup = exports.mapMetaDataObjectToActions = exports.isResetPasswordRequired = exports.
|
|
18
|
+
exports.restoreTabTenantUnlessSsoCallback = exports.prepareIdentifiersForSignup = exports.mapMetaDataObjectToActions = exports.isResetPasswordRequired = exports.isOnLoginCodeCallbackRoute = exports.isOnAuthPageRoute = exports.isMfaRequired = exports.isAuthRoute = exports.getUri = void 0;
|
|
19
19
|
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
|
|
20
20
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
21
21
|
var _restApi = require("@frontegg/rest-api");
|
|
@@ -122,25 +122,30 @@ const getCurrentRoutes = urlStrategy => {
|
|
|
122
122
|
};
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
|
-
* On the OIDC callback the page still has to finish the
|
|
126
|
-
* a reason to go
|
|
125
|
+
* On the OIDC or hosted login callback the page still has to finish the login with its code: a refresh refused before
|
|
126
|
+
* that is not a reason to go to SSO again. On the OIDC callback the IdP would send the user straight back here, forever;
|
|
127
|
+
* on the hosted callback a new hosted login would replace the PKCE verifier the code exchange needs.
|
|
127
128
|
*/
|
|
128
|
-
const
|
|
129
|
+
const isOnLoginCodeCallbackRoute = store => {
|
|
129
130
|
var _store$root$urlStrate;
|
|
130
131
|
const {
|
|
131
|
-
oidcRedirectUrl
|
|
132
|
+
oidcRedirectUrl,
|
|
133
|
+
hostedLoginRedirectUrl
|
|
132
134
|
} = (0, _extends2.default)({}, _consts.defaultFronteggRoutes, store.auth.routes);
|
|
133
|
-
|
|
135
|
+
const currentRoutes = getCurrentRoutes((_store$root$urlStrate = store.root.urlStrategy) != null ? _store$root$urlStrate : 'path');
|
|
136
|
+
return [oidcRedirectUrl, hostedLoginRedirectUrl].some(route => !!route && currentRoutes.some(currentRoute => currentRoute.endsWith(route)));
|
|
134
137
|
};
|
|
135
138
|
|
|
136
139
|
/**
|
|
137
140
|
* After a switch refused for SSO the tab points at the SSO tenant. Its SSO login comes back on a callback route and
|
|
138
141
|
* keeps it; any other page load means the user didn't finish that login, so the tab goes back to its tenant.
|
|
139
142
|
*/
|
|
140
|
-
exports.
|
|
143
|
+
exports.isOnLoginCodeCallbackRoute = isOnLoginCodeCallbackRoute;
|
|
141
144
|
const restoreTabTenantUnlessSsoCallback = store => {
|
|
142
145
|
var _store$root$urlStrate2;
|
|
143
|
-
|
|
146
|
+
// Flags load in parallel with the first refresh. Recover an existing marker
|
|
147
|
+
// before choosing that refresh's tenant, even if flags are not available yet.
|
|
148
|
+
if (!_restApi.ContextHolder.for(store.root.appName).isSessionPerTenantEnabled()) {
|
|
144
149
|
return;
|
|
145
150
|
}
|
|
146
151
|
const {
|
package/node/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontegg/redux-store",
|
|
3
|
-
"version": "7.131.0-alpha.
|
|
3
|
+
"version": "7.131.0-alpha.2",
|
|
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.131.0-alpha.
|
|
10
|
+
"@frontegg/rest-api": "7.131.0-alpha.2",
|
|
11
11
|
"fast-deep-equal": "3.1.3",
|
|
12
12
|
"get-value": "^3.0.1",
|
|
13
13
|
"proxy-compare": "^3.0.0",
|