@finos/legend-application 16.0.116 → 16.0.118
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/lib/components/LegendTokenSync.d.ts +16 -4
- package/lib/components/LegendTokenSync.d.ts.map +1 -1
- package/lib/components/LegendTokenSync.js +25 -32
- package/lib/components/LegendTokenSync.js.map +1 -1
- package/lib/index.css +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/navigation/BrowserNavigator.js +1 -1
- package/lib/stores/navigation/BrowserNavigator.js.map +1 -1
- package/package.json +4 -4
- package/src/components/LegendTokenSync.tsx +25 -39
- package/src/stores/navigation/BrowserNavigator.ts +1 -1
|
@@ -17,10 +17,22 @@
|
|
|
17
17
|
* Must be rendered inside an `<AuthProvider>` and an
|
|
18
18
|
* `<ApplicationStoreProvider>`.
|
|
19
19
|
*
|
|
20
|
-
* Keeps the in-memory token and cookie in sync with the OIDC provider
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* Keeps the in-memory token and cookie in sync with the OIDC provider.
|
|
21
|
+
*
|
|
22
|
+
* `react-oidc-context`'s `UserManager` already renews the access token
|
|
23
|
+
* automatically before it expires (`automaticSilentRenew`, on by default),
|
|
24
|
+
* and internally listens to its own `accessTokenExpiring`/`accessTokenExpired`
|
|
25
|
+
* events to do so. This component must NOT also call `auth.signinSilent()`
|
|
26
|
+
* on those same events — doing so previously caused two concurrent
|
|
27
|
+
* `signinSilent()` calls per renewal, racing to redeem the same (single-use)
|
|
28
|
+
* refresh token against the IdP, which surfaced as an intermittent `400` from
|
|
29
|
+
* the token endpoint and — because the losing call's failure handler cleared
|
|
30
|
+
* the token outright — as `401`s on API calls right around every token
|
|
31
|
+
* expiry, even when the other, winning renewal had actually succeeded.
|
|
32
|
+
*
|
|
33
|
+
* Instead, we only react passively to the outcome of the library's own
|
|
34
|
+
* renewal: sync the token when it changes, and clear it if the library
|
|
35
|
+
* reports the renewal ultimately failed (`SilentRenewError`).
|
|
24
36
|
*/
|
|
25
37
|
export declare const LegendTokenSync: (props: {
|
|
26
38
|
children: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendTokenSync.d.ts","sourceRoot":"","sources":["../../src/components/LegendTokenSync.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH
|
|
1
|
+
{"version":3,"file":"LegendTokenSync.d.ts","sourceRoot":"","sources":["../../src/components/LegendTokenSync.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,KAAG,KAAK,CAAC,YAiCT,CAAC"}
|
|
@@ -14,7 +14,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
import { useEffect
|
|
17
|
+
import { useEffect } from 'react';
|
|
18
18
|
import { useAuth } from 'react-oidc-context';
|
|
19
19
|
import { LogEvent } from '@finos/legend-shared';
|
|
20
20
|
import { useApplicationStore } from './ApplicationStoreProvider.js';
|
|
@@ -23,25 +23,28 @@ import { APPLICATION_EVENT } from '../__lib__/LegendApplicationEvent.js';
|
|
|
23
23
|
* Must be rendered inside an `<AuthProvider>` and an
|
|
24
24
|
* `<ApplicationStoreProvider>`.
|
|
25
25
|
*
|
|
26
|
-
* Keeps the in-memory token and cookie in sync with the OIDC provider
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* Keeps the in-memory token and cookie in sync with the OIDC provider.
|
|
27
|
+
*
|
|
28
|
+
* `react-oidc-context`'s `UserManager` already renews the access token
|
|
29
|
+
* automatically before it expires (`automaticSilentRenew`, on by default),
|
|
30
|
+
* and internally listens to its own `accessTokenExpiring`/`accessTokenExpired`
|
|
31
|
+
* events to do so. This component must NOT also call `auth.signinSilent()`
|
|
32
|
+
* on those same events — doing so previously caused two concurrent
|
|
33
|
+
* `signinSilent()` calls per renewal, racing to redeem the same (single-use)
|
|
34
|
+
* refresh token against the IdP, which surfaced as an intermittent `400` from
|
|
35
|
+
* the token endpoint and — because the losing call's failure handler cleared
|
|
36
|
+
* the token outright — as `401`s on API calls right around every token
|
|
37
|
+
* expiry, even when the other, winning renewal had actually succeeded.
|
|
38
|
+
*
|
|
39
|
+
* Instead, we only react passively to the outcome of the library's own
|
|
40
|
+
* renewal: sync the token when it changes, and clear it if the library
|
|
41
|
+
* reports the renewal ultimately failed (`SilentRenewError`).
|
|
30
42
|
*/
|
|
31
43
|
export const LegendTokenSync = (props) => {
|
|
32
44
|
const auth = useAuth();
|
|
33
45
|
const applicationStore = useApplicationStore();
|
|
34
46
|
const token = auth.user?.access_token;
|
|
35
47
|
const expiresAt = auth.user?.expires_at;
|
|
36
|
-
const attemptSilentRenew = useCallback(async () => {
|
|
37
|
-
try {
|
|
38
|
-
await auth.signinSilent();
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
applicationStore.logService.warn(LogEvent.create(APPLICATION_EVENT.TOKEN_EXPIRED), 'OIDC silent renewal failed — clearing token');
|
|
42
|
-
applicationStore.setAccessToken(undefined);
|
|
43
|
-
}
|
|
44
|
-
}, [auth, applicationStore]);
|
|
45
48
|
// Sync token into ApplicationStore whenever it changes (including
|
|
46
49
|
// after a successful automatic silent renewal). When the auth object
|
|
47
50
|
// contains an `expires_at` timestamp we derive `max-age` so the
|
|
@@ -52,26 +55,16 @@ export const LegendTokenSync = (props) => {
|
|
|
52
55
|
: undefined;
|
|
53
56
|
applicationStore.setAccessToken(token ?? undefined, maxAge);
|
|
54
57
|
}, [applicationStore, token, expiresAt]);
|
|
58
|
+
// The library's automatic silent renewal (see UserManager's
|
|
59
|
+
// `automaticSilentRenew`) exhausted its own retries and gave up — only now
|
|
60
|
+
// do we clear the token, since sending it further would just 401.
|
|
55
61
|
useEffect(() => {
|
|
56
|
-
const
|
|
57
|
-
applicationStore.logService.
|
|
58
|
-
|
|
59
|
-
/* handled inside attemptSilentRenew */
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
return removeExpiring;
|
|
63
|
-
}, [auth.events, applicationStore, attemptSilentRenew]);
|
|
64
|
-
// If the token fully expires (automatic renewal failed or was never
|
|
65
|
-
// attempted) make one last renewal attempt before giving up.
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
const removeExpired = auth.events.addAccessTokenExpired(() => {
|
|
68
|
-
applicationStore.logService.warn(LogEvent.create(APPLICATION_EVENT.TOKEN_EXPIRED), 'OIDC access token expired — attempting silent renewal');
|
|
69
|
-
attemptSilentRenew().catch(() => {
|
|
70
|
-
/* handled inside attemptSilentRenew */
|
|
71
|
-
});
|
|
62
|
+
const removeSilentRenewError = auth.events.addSilentRenewError((err) => {
|
|
63
|
+
applicationStore.logService.warn(LogEvent.create(APPLICATION_EVENT.TOKEN_EXPIRED), `OIDC silent renewal failed: ${err.message} — clearing token`);
|
|
64
|
+
applicationStore.setAccessToken(undefined);
|
|
72
65
|
});
|
|
73
|
-
return
|
|
74
|
-
}, [auth.events, applicationStore
|
|
66
|
+
return removeSilentRenewError;
|
|
67
|
+
}, [auth.events, applicationStore]);
|
|
75
68
|
return _jsx(_Fragment, { children: props.children });
|
|
76
69
|
};
|
|
77
70
|
//# sourceMappingURL=LegendTokenSync.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendTokenSync.js","sourceRoot":"","sources":["../../src/components/LegendTokenSync.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"LegendTokenSync.js","sourceRoot":"","sources":["../../src/components/LegendTokenSync.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAE/B,EAAsB,EAAE;IACvB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC;IAExC,kEAAkE;IAClE,sEAAsE;IACtE,gEAAgE;IAChE,wDAAwD;IACxD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GACV,SAAS,KAAK,SAAS;YACrB,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAC3C,CAAC,CAAC,SAAS,CAAC;QAChB,gBAAgB,CAAC,cAAc,CAAC,KAAK,IAAI,SAAS,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;IAEzC,4DAA4D;IAC5D,2EAA2E;IAC3E,kEAAkE;IAClE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,sBAAsB,GAAG,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,GAAG,EAAE,EAAE;YACrE,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAC9B,QAAQ,CAAC,MAAM,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAChD,+BAA+B,GAAG,CAAC,OAAO,mBAAmB,CAC9D,CAAC;YACF,gBAAgB,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,OAAO,sBAAsB,CAAC;IAChC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAEpC,OAAO,4BAAG,KAAK,CAAC,QAAQ,GAAI,CAAC;AAC/B,CAAC,CAAC"}
|
package/lib/index.css
CHANGED
package/lib/package.json
CHANGED
|
@@ -116,7 +116,7 @@ export class BrowserNavigator {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
visitAddress(address) {
|
|
119
|
-
this.window.open(address, '_blank');
|
|
119
|
+
this.window.open(address, '_blank', 'noopener');
|
|
120
120
|
}
|
|
121
121
|
generateAddress(location) {
|
|
122
122
|
return this.window.location.origin + this.baseUrl + location;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserNavigator.js","sourceRoot":"","sources":["../../../src/stores/navigation/BrowserNavigator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"BrowserNavigator.js","sourceRoot":"","sources":["../../../src/stores/navigation/BrowserNavigator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos/legend-application",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.118",
|
|
4
4
|
"description": "Legend application core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"legend",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"test:watch": "jest --watch"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@finos/legend-art": "7.1.
|
|
49
|
-
"@finos/legend-shared": "11.0.
|
|
50
|
-
"@finos/legend-storage": "3.0.
|
|
48
|
+
"@finos/legend-art": "7.1.158",
|
|
49
|
+
"@finos/legend-shared": "11.0.27",
|
|
50
|
+
"@finos/legend-storage": "3.0.149",
|
|
51
51
|
"@types/react": "19.0.10",
|
|
52
52
|
"@types/react-dom": "19.0.4",
|
|
53
53
|
"@types/react-router-dom": "5.3.3",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { useEffect
|
|
17
|
+
import { useEffect } from 'react';
|
|
18
18
|
import { useAuth } from 'react-oidc-context';
|
|
19
19
|
import { LogEvent } from '@finos/legend-shared';
|
|
20
20
|
import { useApplicationStore } from './ApplicationStoreProvider.js';
|
|
@@ -24,10 +24,22 @@ import { APPLICATION_EVENT } from '../__lib__/LegendApplicationEvent.js';
|
|
|
24
24
|
* Must be rendered inside an `<AuthProvider>` and an
|
|
25
25
|
* `<ApplicationStoreProvider>`.
|
|
26
26
|
*
|
|
27
|
-
* Keeps the in-memory token and cookie in sync with the OIDC provider
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* Keeps the in-memory token and cookie in sync with the OIDC provider.
|
|
28
|
+
*
|
|
29
|
+
* `react-oidc-context`'s `UserManager` already renews the access token
|
|
30
|
+
* automatically before it expires (`automaticSilentRenew`, on by default),
|
|
31
|
+
* and internally listens to its own `accessTokenExpiring`/`accessTokenExpired`
|
|
32
|
+
* events to do so. This component must NOT also call `auth.signinSilent()`
|
|
33
|
+
* on those same events — doing so previously caused two concurrent
|
|
34
|
+
* `signinSilent()` calls per renewal, racing to redeem the same (single-use)
|
|
35
|
+
* refresh token against the IdP, which surfaced as an intermittent `400` from
|
|
36
|
+
* the token endpoint and — because the losing call's failure handler cleared
|
|
37
|
+
* the token outright — as `401`s on API calls right around every token
|
|
38
|
+
* expiry, even when the other, winning renewal had actually succeeded.
|
|
39
|
+
*
|
|
40
|
+
* Instead, we only react passively to the outcome of the library's own
|
|
41
|
+
* renewal: sync the token when it changes, and clear it if the library
|
|
42
|
+
* reports the renewal ultimately failed (`SilentRenewError`).
|
|
31
43
|
*/
|
|
32
44
|
export const LegendTokenSync = (props: {
|
|
33
45
|
children: React.ReactNode;
|
|
@@ -37,18 +49,6 @@ export const LegendTokenSync = (props: {
|
|
|
37
49
|
const token = auth.user?.access_token;
|
|
38
50
|
const expiresAt = auth.user?.expires_at;
|
|
39
51
|
|
|
40
|
-
const attemptSilentRenew = useCallback(async () => {
|
|
41
|
-
try {
|
|
42
|
-
await auth.signinSilent();
|
|
43
|
-
} catch {
|
|
44
|
-
applicationStore.logService.warn(
|
|
45
|
-
LogEvent.create(APPLICATION_EVENT.TOKEN_EXPIRED),
|
|
46
|
-
'OIDC silent renewal failed — clearing token',
|
|
47
|
-
);
|
|
48
|
-
applicationStore.setAccessToken(undefined);
|
|
49
|
-
}
|
|
50
|
-
}, [auth, applicationStore]);
|
|
51
|
-
|
|
52
52
|
// Sync token into ApplicationStore whenever it changes (including
|
|
53
53
|
// after a successful automatic silent renewal). When the auth object
|
|
54
54
|
// contains an `expires_at` timestamp we derive `max-age` so the
|
|
@@ -61,33 +61,19 @@ export const LegendTokenSync = (props: {
|
|
|
61
61
|
applicationStore.setAccessToken(token ?? undefined, maxAge);
|
|
62
62
|
}, [applicationStore, token, expiresAt]);
|
|
63
63
|
|
|
64
|
+
// The library's automatic silent renewal (see UserManager's
|
|
65
|
+
// `automaticSilentRenew`) exhausted its own retries and gave up — only now
|
|
66
|
+
// do we clear the token, since sending it further would just 401.
|
|
64
67
|
useEffect(() => {
|
|
65
|
-
const
|
|
66
|
-
applicationStore.logService.info(
|
|
67
|
-
LogEvent.create(APPLICATION_EVENT.TOKEN_EXPIRED),
|
|
68
|
-
'OIDC access token expiring soon — attempting silent renewal',
|
|
69
|
-
);
|
|
70
|
-
attemptSilentRenew().catch(() => {
|
|
71
|
-
/* handled inside attemptSilentRenew */
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
return removeExpiring;
|
|
75
|
-
}, [auth.events, applicationStore, attemptSilentRenew]);
|
|
76
|
-
|
|
77
|
-
// If the token fully expires (automatic renewal failed or was never
|
|
78
|
-
// attempted) make one last renewal attempt before giving up.
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
const removeExpired = auth.events.addAccessTokenExpired(() => {
|
|
68
|
+
const removeSilentRenewError = auth.events.addSilentRenewError((err) => {
|
|
81
69
|
applicationStore.logService.warn(
|
|
82
70
|
LogEvent.create(APPLICATION_EVENT.TOKEN_EXPIRED),
|
|
83
|
-
|
|
71
|
+
`OIDC silent renewal failed: ${err.message} — clearing token`,
|
|
84
72
|
);
|
|
85
|
-
|
|
86
|
-
/* handled inside attemptSilentRenew */
|
|
87
|
-
});
|
|
73
|
+
applicationStore.setAccessToken(undefined);
|
|
88
74
|
});
|
|
89
|
-
return
|
|
90
|
-
}, [auth.events, applicationStore
|
|
75
|
+
return removeSilentRenewError;
|
|
76
|
+
}, [auth.events, applicationStore]);
|
|
91
77
|
|
|
92
78
|
return <>{props.children}</>;
|
|
93
79
|
};
|
|
@@ -179,7 +179,7 @@ export class BrowserNavigator implements ApplicationNavigator {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
visitAddress(address: NavigationAddress): void {
|
|
182
|
-
this.window.open(address, '_blank');
|
|
182
|
+
this.window.open(address, '_blank', 'noopener');
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
generateAddress(location: NavigationLocation): string {
|