@axa-fr/react-oidc 6.0.0-beta7 → 6.0.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/README.md +13 -4
- package/dist/FetchToken.d.ts.map +1 -1
- package/dist/FetchToken.js +10 -6
- package/dist/FetchToken.js.map +1 -1
- package/dist/OidcProvider.d.ts +1 -0
- package/dist/OidcProvider.d.ts.map +1 -1
- package/dist/OidcProvider.js +11 -4
- package/dist/OidcProvider.js.map +1 -1
- package/dist/OidcSecure.js +2 -2
- package/dist/OidcSecure.js.map +1 -1
- package/dist/OidcServiceWorker.js +62 -32
- package/dist/OidcTrustedDomains.js +7 -2
- package/dist/ReactOidc.d.ts.map +1 -1
- package/dist/ReactOidc.js +4 -3
- package/dist/ReactOidc.js.map +1 -1
- package/dist/core/default-component/SilentLogin.component.js +1 -1
- package/dist/core/default-component/SilentLogin.component.js.map +1 -1
- package/dist/core/routes/OidcRoutes.d.ts.map +1 -1
- package/dist/core/routes/OidcRoutes.js +1 -4
- package/dist/core/routes/OidcRoutes.js.map +1 -1
- package/dist/vanilla/initSession.d.ts +2 -1
- package/dist/vanilla/initSession.d.ts.map +1 -1
- package/dist/vanilla/initSession.js +7 -7
- package/dist/vanilla/initSession.js.map +1 -1
- package/dist/vanilla/initWorker.d.ts +2 -3
- package/dist/vanilla/initWorker.d.ts.map +1 -1
- package/dist/vanilla/initWorker.js +6 -21
- package/dist/vanilla/initWorker.js.map +1 -1
- package/dist/vanilla/oidc.d.ts +10 -5
- package/dist/vanilla/oidc.d.ts.map +1 -1
- package/dist/vanilla/oidc.js +451 -442
- package/dist/vanilla/oidc.js.map +1 -1
- package/package.json +1 -1
- package/src/oidc/FetchToken.tsx +7 -4
- package/src/oidc/OidcProvider.tsx +9 -0
- package/src/oidc/OidcSecure.tsx +2 -2
- package/src/oidc/ReactOidc.tsx +4 -3
- package/src/oidc/core/default-component/SilentLogin.component.tsx +1 -1
- package/src/oidc/core/routes/OidcRoutes.tsx +0 -4
- package/src/oidc/vanilla/OidcServiceWorker.js +62 -32
- package/src/oidc/vanilla/OidcTrustedDomains.js +7 -2
- package/src/oidc/vanilla/initSession.ts +6 -7
- package/src/oidc/vanilla/initWorker.ts +6 -15
- package/src/oidc/vanilla/oidc.ts +219 -241
- package/src/oidc/vanilla/parseTokens.js +107 -0
- package/dist/core/default-component/ServiceWorkerInstall.component.d.ts +0 -4
- package/dist/core/default-component/ServiceWorkerInstall.component.d.ts.map +0 -1
- package/dist/core/default-component/ServiceWorkerInstall.component.js +0 -131
- package/dist/core/default-component/ServiceWorkerInstall.component.js.map +0 -1
- package/src/oidc/core/default-component/ServiceWorkerInstall.component.tsx +0 -60
package/src/oidc/vanilla/oidc.ts
CHANGED
|
@@ -19,6 +19,7 @@ import timer from './timer';
|
|
|
19
19
|
import {CheckSessionIFrame} from "./checkSessionIFrame"
|
|
20
20
|
import {getParseQueryStringFromLocation} from "./route-utils";
|
|
21
21
|
import {AuthorizationServiceConfigurationJson} from "@openid/appauth/src/authorization_service_configuration";
|
|
22
|
+
import {computeTimeLeft, isTokensValid, parseOriginalTokens, setTokens} from "./parseTokens";
|
|
22
23
|
|
|
23
24
|
const performTokenRequestAsync= async (url, details, extras) => {
|
|
24
25
|
|
|
@@ -47,22 +48,9 @@ const performTokenRequestAsync= async (url, details, extras) => {
|
|
|
47
48
|
return {success:false, status: response.status}
|
|
48
49
|
}
|
|
49
50
|
const tokens = await response.json();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
tokens.issued_at = currentTimeUnixSecond;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return { success : true,
|
|
57
|
-
data : {
|
|
58
|
-
accessToken: tokens.access_token,
|
|
59
|
-
expiresIn: tokens.expires_in,
|
|
60
|
-
idToken: tokens.id_token,
|
|
61
|
-
refreshToken: tokens.refresh_token,
|
|
62
|
-
scope: tokens.scope,
|
|
63
|
-
tokenType: tokens.token_type,
|
|
64
|
-
issuedAt: tokens.issued_at
|
|
65
|
-
}
|
|
51
|
+
return {
|
|
52
|
+
success : true,
|
|
53
|
+
data: parseOriginalTokens(tokens)
|
|
66
54
|
};
|
|
67
55
|
}
|
|
68
56
|
|
|
@@ -82,7 +70,6 @@ const internalFetch = async (url, headers, numberRetry=0) => {
|
|
|
82
70
|
throw e;
|
|
83
71
|
}
|
|
84
72
|
} else {
|
|
85
|
-
|
|
86
73
|
console.error(e.message);
|
|
87
74
|
throw e; // rethrow other unexpected errors
|
|
88
75
|
}
|
|
@@ -108,36 +95,6 @@ export class OidcAuthorizationServiceConfiguration extends AuthorizationServiceC
|
|
|
108
95
|
|
|
109
96
|
}
|
|
110
97
|
|
|
111
|
-
const idTokenPayload = (token) => {
|
|
112
|
-
const base64Url = token.split('.')[1];
|
|
113
|
-
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
|
114
|
-
const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
|
|
115
|
-
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
|
116
|
-
}).join(''));
|
|
117
|
-
|
|
118
|
-
return JSON.parse(jsonPayload);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const countLetter = (str, find)=> {
|
|
122
|
-
return (str.split(find)).length - 1;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const extractAccessTokenPayload = tokens => {
|
|
126
|
-
if(tokens.accessTokenPayload)
|
|
127
|
-
{
|
|
128
|
-
return tokens.accessTokenPayload;
|
|
129
|
-
}
|
|
130
|
-
const accessToken = tokens.accessToken;
|
|
131
|
-
try{
|
|
132
|
-
if (!accessToken || countLetter(accessToken,'.') != 2) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
return JSON.parse(atob(accessToken.split('.')[1]));
|
|
136
|
-
} catch (e) {
|
|
137
|
-
console.warn(e);
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
};
|
|
141
98
|
|
|
142
99
|
export interface StringMap {
|
|
143
100
|
[key: string]: string;
|
|
@@ -193,44 +150,46 @@ const loginCallbackWithAutoTokensRenewAsync = async (oidc) => {
|
|
|
193
150
|
}
|
|
194
151
|
|
|
195
152
|
const autoRenewTokens = (oidc, refreshToken, expiresAt) => {
|
|
196
|
-
const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second
|
|
153
|
+
const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second;
|
|
197
154
|
return timer.setTimeout(async () => {
|
|
198
|
-
const
|
|
199
|
-
const timeInfo = { timeLeft
|
|
155
|
+
const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
|
|
156
|
+
const timeInfo = { timeLeft };
|
|
200
157
|
oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
oidc.tokens= await setTokensAsync(oidc.serviceWorker, tokens);
|
|
158
|
+
const {tokens, status} = await oidc.synchroniseTokensAsync(refreshToken);
|
|
159
|
+
oidc.tokens= tokens;
|
|
204
160
|
if(!oidc.serviceWorker){
|
|
205
161
|
await oidc.session.setTokens(oidc.tokens);
|
|
206
162
|
}
|
|
207
163
|
if(!oidc.tokens){
|
|
208
|
-
|
|
209
|
-
oidc.checkSessionIFrame.stop();
|
|
210
|
-
oidc.checkSessionIFrame = null;
|
|
211
|
-
}
|
|
164
|
+
await oidc.destroyAsync(status);
|
|
212
165
|
return;
|
|
213
166
|
}
|
|
214
|
-
|
|
167
|
+
|
|
215
168
|
if(oidc.timeoutId) {
|
|
216
169
|
oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt);
|
|
217
170
|
}
|
|
218
|
-
|
|
219
|
-
await oidc.syncTokensAsync();
|
|
220
|
-
if(oidc.timeoutId) {
|
|
221
|
-
oidc.timeoutId = autoRenewTokens(oidc, refreshToken, expiresAt);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
171
|
+
|
|
224
172
|
}, 1000);
|
|
225
173
|
}
|
|
226
174
|
|
|
227
175
|
const getLoginSessionKey = (configurationName:string, redirectUri:string) => {
|
|
228
176
|
return `oidc_login.${configurationName}:${redirectUri}`;
|
|
229
177
|
}
|
|
230
|
-
|
|
231
|
-
|
|
178
|
+
|
|
179
|
+
const setLoginParams = (configurationName:string, redirectUri:string, data) =>{
|
|
180
|
+
const sessionKey = getLoginSessionKey(configurationName, redirectUri);
|
|
181
|
+
getLoginParamsCache = data
|
|
182
|
+
sessionStorage[sessionKey] = JSON.stringify(data);
|
|
232
183
|
}
|
|
233
184
|
|
|
185
|
+
let getLoginParamsCache = null;
|
|
186
|
+
const getLoginParams = (configurationName, redirectUri) => {
|
|
187
|
+
const dataString = sessionStorage[getLoginSessionKey(configurationName, redirectUri)];
|
|
188
|
+
if(!getLoginParamsCache){
|
|
189
|
+
getLoginParamsCache = JSON.parse(dataString);
|
|
190
|
+
}
|
|
191
|
+
return getLoginParamsCache;
|
|
192
|
+
}
|
|
234
193
|
|
|
235
194
|
const userInfoAsync = async (oidc) => {
|
|
236
195
|
if(oidc.userInfo != null){
|
|
@@ -239,11 +198,15 @@ const userInfoAsync = async (oidc) => {
|
|
|
239
198
|
if(!oidc.tokens){
|
|
240
199
|
return null;
|
|
241
200
|
}
|
|
242
|
-
if(oidc.syncTokensAsyncPromise){
|
|
243
|
-
await oidc.syncTokensAsyncPromise;
|
|
244
|
-
}
|
|
245
201
|
const accessToken = oidc.tokens.accessToken;
|
|
246
|
-
|
|
202
|
+
if(!accessToken){
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
// We wait the synchronisation before making a request
|
|
206
|
+
while (oidc.tokens && !isTokensValid(oidc.tokens)){
|
|
207
|
+
await sleepAsync(200);
|
|
208
|
+
}
|
|
209
|
+
|
|
247
210
|
const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
|
|
248
211
|
const url = oidcServerConfiguration.userInfoEndpoint;
|
|
249
212
|
const fetchUserInfo = async (accessToken) => {
|
|
@@ -265,29 +228,11 @@ const userInfoAsync = async (oidc) => {
|
|
|
265
228
|
return userInfo;
|
|
266
229
|
}
|
|
267
230
|
|
|
268
|
-
const setTokensAsync = async (serviceWorker, tokens) =>{
|
|
269
|
-
let accessTokenPayload;
|
|
270
|
-
if(tokens == null){
|
|
271
|
-
if(serviceWorker){
|
|
272
|
-
await serviceWorker.clearAsync();
|
|
273
|
-
}
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
if(serviceWorker){
|
|
277
|
-
accessTokenPayload = await serviceWorker.getAccessTokenPayloadAsync();
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
accessTokenPayload = extractAccessTokenPayload(tokens);
|
|
281
|
-
}
|
|
282
|
-
const _idTokenPayload = idTokenPayload(tokens.idToken);
|
|
283
|
-
const expiresAt = (_idTokenPayload && _idTokenPayload.exp) ? _idTokenPayload.exp : tokens.issuedAt + tokens.expiresIn;
|
|
284
|
-
return {...tokens, idTokenPayload: _idTokenPayload, accessTokenPayload, expiresAt};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
231
|
const eventNames = {
|
|
288
232
|
service_worker_not_supported_by_browser: "service_worker_not_supported_by_browser",
|
|
289
233
|
token_aquired: "token_aquired",
|
|
290
234
|
logout_from_another_tab: "logout_from_another_tab",
|
|
235
|
+
logout_from_same_tab: "logout_from_same_tab",
|
|
291
236
|
token_renewed: "token_renewed",
|
|
292
237
|
token_timer: "token_timer",
|
|
293
238
|
loginAsync_begin:"loginAsync_begin",
|
|
@@ -380,7 +325,12 @@ export class Oidc {
|
|
|
380
325
|
silent_login_uri = `${configuration.silent_redirect_uri.replace("-callback", "").replace("callback", "")}-login`;
|
|
381
326
|
}
|
|
382
327
|
|
|
383
|
-
this.configuration = {...configuration,
|
|
328
|
+
this.configuration = {...configuration,
|
|
329
|
+
silent_login_uri,
|
|
330
|
+
monitor_session: configuration.monitor_session ?? true,
|
|
331
|
+
refresh_time_before_tokens_expiration_in_second : configuration.refresh_time_before_tokens_expiration_in_second ?? 60,
|
|
332
|
+
silent_login_timeout: configuration.silent_login_timeout ?? 12000,
|
|
333
|
+
};
|
|
384
334
|
this.configurationName= configurationName;
|
|
385
335
|
this.tokens = null
|
|
386
336
|
this.userInfo = null;
|
|
@@ -388,7 +338,7 @@ export class Oidc {
|
|
|
388
338
|
this.timeoutId = null;
|
|
389
339
|
this.serviceWorker = null;
|
|
390
340
|
this.session = null;
|
|
391
|
-
this.
|
|
341
|
+
this.synchroniseTokensAsync.bind(this);
|
|
392
342
|
this.loginCallbackWithAutoTokensRenewAsync.bind(this);
|
|
393
343
|
this.initAsync.bind(this);
|
|
394
344
|
this.loginCallbackAsync.bind(this);
|
|
@@ -458,10 +408,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
458
408
|
if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
|
|
459
409
|
return Promise.resolve(null);
|
|
460
410
|
}
|
|
461
|
-
while (document.hidden) {
|
|
462
|
-
await sleepAsync(1000);
|
|
463
|
-
this.publishEvent(eventNames.silentLoginAsync, {message:"wait because document is hidden"});
|
|
464
|
-
}
|
|
465
411
|
|
|
466
412
|
try {
|
|
467
413
|
this.publishEvent(eventNames.silentLoginAsync_begin, {});
|
|
@@ -526,19 +472,19 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
526
472
|
self.publishEvent(eventNames.silentLoginAsync_error, result);
|
|
527
473
|
iframe.remove();
|
|
528
474
|
isResolved = true;
|
|
529
|
-
reject(result);
|
|
475
|
+
reject(new Error("oidc_"+result.error));
|
|
530
476
|
}
|
|
531
477
|
}
|
|
532
478
|
}
|
|
533
479
|
}
|
|
534
480
|
};
|
|
535
|
-
const silentSigninTimeout = configuration.silent_login_timeout
|
|
481
|
+
const silentSigninTimeout = configuration.silent_login_timeout;
|
|
536
482
|
setTimeout(() => {
|
|
537
483
|
if (!isResolved) {
|
|
538
|
-
self.publishEvent(eventNames.silentLoginAsync_error, "timeout");
|
|
484
|
+
self.publishEvent(eventNames.silentLoginAsync_error, {reason: "timeout"});
|
|
539
485
|
iframe.remove();
|
|
540
486
|
isResolved = true;
|
|
541
|
-
reject("timeout");
|
|
487
|
+
reject(new Error("timeout"));
|
|
542
488
|
}
|
|
543
489
|
}, silentSigninTimeout);
|
|
544
490
|
} catch (e) {
|
|
@@ -566,8 +512,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
566
512
|
|
|
567
513
|
const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
|
|
568
514
|
const storage = serviceWorker ? window.localStorage : null;
|
|
569
|
-
|
|
570
|
-
return initAsyncPromise;
|
|
515
|
+
return await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage);
|
|
571
516
|
}
|
|
572
517
|
|
|
573
518
|
tryKeepExistingSessionPromise = null;
|
|
@@ -591,16 +536,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
591
536
|
if (tokens) {
|
|
592
537
|
serviceWorker.startKeepAliveServiceWorker();
|
|
593
538
|
// @ts-ignore
|
|
594
|
-
|
|
595
|
-
accessToken : tokens.access_token,
|
|
596
|
-
refreshToken : tokens.refresh_token,
|
|
597
|
-
expiresIn: tokens.expires_in,
|
|
598
|
-
idToken: tokens.id_token,
|
|
599
|
-
scope: tokens.scope,
|
|
600
|
-
tokenType: tokens.token_type,
|
|
601
|
-
issuedAt: tokens.issued_at
|
|
602
|
-
}
|
|
603
|
-
this.tokens = await setTokensAsync(serviceWorker, reformattedToken);
|
|
539
|
+
this.tokens = tokens;
|
|
604
540
|
this.serviceWorker = serviceWorker;
|
|
605
541
|
// @ts-ignore
|
|
606
542
|
this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt);
|
|
@@ -627,7 +563,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
627
563
|
const {tokens} = await session.initAsync();
|
|
628
564
|
if (tokens) {
|
|
629
565
|
// @ts-ignore
|
|
630
|
-
this.tokens =
|
|
566
|
+
this.tokens = setTokens(tokens);
|
|
631
567
|
//session.setTokens(this.tokens);
|
|
632
568
|
this.session = session;
|
|
633
569
|
// @ts-ignore
|
|
@@ -665,7 +601,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
665
601
|
}
|
|
666
602
|
|
|
667
603
|
loginPromise: Promise<any>=null;
|
|
668
|
-
async loginAsync(callbackPath:string=undefined, extras:StringMap=null,
|
|
604
|
+
async loginAsync(callbackPath:string=undefined, extras:StringMap=null, state:string=undefined, isSilentSignin:boolean=false, scope:string=undefined) {
|
|
669
605
|
if(this.loginPromise !== null){
|
|
670
606
|
return this.loginPromise;
|
|
671
607
|
}
|
|
@@ -682,28 +618,10 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
682
618
|
scope = configuration.scope;
|
|
683
619
|
}
|
|
684
620
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
621
|
+
setLoginParams(this.configurationName, redirectUri, {callbackPath: url, extras, state});
|
|
622
|
+
|
|
688
623
|
let serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
689
624
|
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
690
|
-
/*if (serviceWorker && installServiceWorker) {
|
|
691
|
-
const isServiceWorkerProxyActive = await serviceWorker.isServiceWorkerProxyActiveAsync();
|
|
692
|
-
if (!isServiceWorkerProxyActive) {
|
|
693
|
-
const isUnregistered = await serviceWorker.unregisterAsync();
|
|
694
|
-
console.log("isUnregistered")
|
|
695
|
-
console.log(isUnregistered)
|
|
696
|
-
if(isUnregistered){
|
|
697
|
-
serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
698
|
-
}
|
|
699
|
-
const extrasQueries = extras != null ? {...extras}: {};
|
|
700
|
-
extrasQueries.callbackPath = url;
|
|
701
|
-
extrasQueries.state = state;
|
|
702
|
-
const queryString = buildQueries(extrasQueries);
|
|
703
|
-
window.location.href = `${redirectUri}/service-worker-install${queryString}`;
|
|
704
|
-
//return;
|
|
705
|
-
}
|
|
706
|
-
}*/
|
|
707
625
|
let storage;
|
|
708
626
|
if (serviceWorker) {
|
|
709
627
|
serviceWorker.startKeepAliveServiceWorker();
|
|
@@ -772,9 +690,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
772
690
|
else {
|
|
773
691
|
console.debug("SessionMonitor._callback: Different subject signed into OP:", iFrameIdTokenPayload.sub);
|
|
774
692
|
}
|
|
775
|
-
}).catch((e) => {
|
|
776
|
-
|
|
777
|
-
|
|
693
|
+
}).catch(async (e) => {
|
|
694
|
+
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
695
|
+
//if(oidc !== this) {
|
|
696
|
+
// @ts-ignore
|
|
697
|
+
await oidc.logoutOtherTabAsync(this.configuration.client_id, idTokenPayload.sub);
|
|
698
|
+
//}
|
|
699
|
+
}
|
|
700
|
+
//await this.destroyAsync();
|
|
701
|
+
//this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor"});
|
|
702
|
+
|
|
778
703
|
});
|
|
779
704
|
};
|
|
780
705
|
|
|
@@ -801,7 +726,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
801
726
|
const response = await this._loginCallbackAsync(isSilenSignin);
|
|
802
727
|
// @ts-ignore
|
|
803
728
|
const tokens = response.tokens;
|
|
804
|
-
const parsedTokens =
|
|
729
|
+
const parsedTokens = setTokens(tokens);
|
|
805
730
|
this.tokens = parsedTokens;
|
|
806
731
|
if(!this.serviceWorker){
|
|
807
732
|
await this.session.setTokens(parsedTokens);
|
|
@@ -901,13 +826,19 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
901
826
|
}, tokenRequestTimeout ?? 12000);
|
|
902
827
|
try {
|
|
903
828
|
const tokenHandler = new BaseTokenRequestHandler(new FetchRequestor());
|
|
904
|
-
tokenHandler.performTokenRequest(oidcServerConfiguration, tokenRequest).then((tokenResponse)=>{
|
|
905
|
-
if(timeoutId) {
|
|
829
|
+
tokenHandler.performTokenRequest(oidcServerConfiguration, tokenRequest).then(async (tokenResponse) => {
|
|
830
|
+
if (timeoutId) {
|
|
906
831
|
clearTimeout(timeoutId);
|
|
907
|
-
this.timeoutId=null;
|
|
832
|
+
this.timeoutId = null;
|
|
908
833
|
const loginParams = getLoginParams(this.configurationName, redirectUri);
|
|
834
|
+
|
|
835
|
+
if (serviceWorker) {
|
|
836
|
+
const {tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
|
|
837
|
+
tokenResponse = tokens;
|
|
838
|
+
}
|
|
839
|
+
|
|
909
840
|
// @ts-ignore
|
|
910
|
-
this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, clientId, sessionState, isSilentSignin).then(() =>{
|
|
841
|
+
this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, clientId, sessionState, isSilentSignin).then(() => {
|
|
911
842
|
this.publishEvent(eventNames.loginCallbackAsync_end, {});
|
|
912
843
|
resolve({
|
|
913
844
|
tokens: tokenResponse,
|
|
@@ -936,130 +867,153 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
936
867
|
}
|
|
937
868
|
}
|
|
938
869
|
|
|
939
|
-
async
|
|
870
|
+
async synchroniseTokensAsync(refreshToken, index=0) {
|
|
940
871
|
|
|
872
|
+
if (document.hidden) {
|
|
873
|
+
await sleepAsync(1000);
|
|
874
|
+
this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
|
|
875
|
+
return await this.synchroniseTokensAsync(refreshToken, index);
|
|
876
|
+
}
|
|
877
|
+
let numberTryOnline = 6;
|
|
878
|
+
while (!navigator.onLine && numberTryOnline > 0) {
|
|
879
|
+
await sleepAsync(1000);
|
|
880
|
+
numberTryOnline--;
|
|
881
|
+
this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
const configuration = this.configuration;
|
|
941
885
|
const localsilentLoginAsync= async () => {
|
|
942
886
|
try {
|
|
943
|
-
const
|
|
887
|
+
const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
|
|
888
|
+
const silent_token_response = await this.silentLoginAsync({
|
|
889
|
+
...loginParams.extras,
|
|
890
|
+
prompt: "none"
|
|
891
|
+
}, loginParams.state);
|
|
944
892
|
if (silent_token_response) {
|
|
945
|
-
|
|
893
|
+
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
894
|
+
return {tokens:silent_token_response.tokens, status:"LOGGED"};
|
|
946
895
|
}
|
|
947
896
|
} catch (exceptionSilent) {
|
|
948
897
|
console.error(exceptionSilent);
|
|
898
|
+
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exceptionSilent" ,exception: exceptionSilent.message});
|
|
899
|
+
if(exceptionSilent && exceptionSilent.message && exceptionSilent.message.startsWith("oidc")){
|
|
900
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent` });
|
|
901
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
902
|
+
}
|
|
903
|
+
await sleepAsync(1000);
|
|
904
|
+
throw exceptionSilent;
|
|
949
905
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
this.timeoutId=null;
|
|
953
|
-
}
|
|
954
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: "refresh token and silent refresh failed"});
|
|
955
|
-
return null;
|
|
906
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent return` });
|
|
907
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
956
908
|
}
|
|
957
|
-
|
|
958
|
-
const configuration = this.configuration;
|
|
959
|
-
const clientId = configuration.client_id;
|
|
960
|
-
const redirectUri = configuration.redirect_uri;
|
|
961
|
-
const authority = configuration.authority;
|
|
962
|
-
|
|
963
|
-
if(!refreshToken)
|
|
964
|
-
{
|
|
965
|
-
return await localsilentLoginAsync();
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
let extras = {};
|
|
969
|
-
if(configuration.token_request_extras) {
|
|
970
|
-
for (let [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
971
|
-
extras[key] = value;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
975
|
-
|
|
976
|
-
const details = {
|
|
977
|
-
client_id: clientId,
|
|
978
|
-
redirect_uri: redirectUri,
|
|
979
|
-
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
980
|
-
refresh_token: refreshToken,
|
|
981
|
-
};
|
|
982
909
|
|
|
983
|
-
|
|
984
|
-
while (index <=2) {
|
|
910
|
+
if (index <=4) {
|
|
985
911
|
try {
|
|
986
|
-
|
|
987
|
-
if(
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
|
|
994
|
-
if (tokenResponse.success) {
|
|
995
|
-
this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
|
|
996
|
-
return tokenResponse.data;
|
|
997
|
-
} else {
|
|
998
|
-
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "bad request" , tokenResponse: tokenResponse});
|
|
912
|
+
|
|
913
|
+
if(!refreshToken)
|
|
914
|
+
{
|
|
915
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
|
|
999
916
|
return await localsilentLoginAsync();
|
|
1000
917
|
}
|
|
918
|
+
const { status, tokens } = await this.syncTokensInfoAsync(configuration, this.configurationName, this.tokens);
|
|
919
|
+
switch (status) {
|
|
920
|
+
case "SESSION_LOST":
|
|
921
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token session lost` });
|
|
922
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
923
|
+
case "NOT_CONNECTED":
|
|
924
|
+
return {tokens:null, status:null};
|
|
925
|
+
case "TOKENS_VALID":
|
|
926
|
+
case "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID":
|
|
927
|
+
return {tokens, status:"LOGGED_IN"};
|
|
928
|
+
case "LOGOUT_FROM_ANOTHER_TAB":
|
|
929
|
+
this.publishEvent(eventNames.logout_from_another_tab, {"status": "session syncTokensAsync"});
|
|
930
|
+
return {tokens:null, status:"LOGGED_OUT"};
|
|
931
|
+
case "REQUIRE_SYNC_TOKENS":
|
|
932
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
|
|
933
|
+
return await localsilentLoginAsync();
|
|
934
|
+
default:
|
|
935
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
|
|
936
|
+
const clientId = configuration.client_id;
|
|
937
|
+
const redirectUri = configuration.redirect_uri;
|
|
938
|
+
const authority = configuration.authority;
|
|
939
|
+
let extras = {};
|
|
940
|
+
if(configuration.token_request_extras) {
|
|
941
|
+
for (let [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
942
|
+
extras[key] = value;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const details = {
|
|
946
|
+
client_id: clientId,
|
|
947
|
+
redirect_uri: redirectUri,
|
|
948
|
+
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
949
|
+
refresh_token: tokens.refreshToken,
|
|
950
|
+
};
|
|
951
|
+
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
952
|
+
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
|
|
953
|
+
if (tokenResponse.success) {
|
|
954
|
+
this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
|
|
955
|
+
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
956
|
+
return {tokens: tokenResponse.data, status:"LOGGED_IN"};
|
|
957
|
+
} else {
|
|
958
|
+
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
959
|
+
message: "bad request",
|
|
960
|
+
tokenResponse: tokenResponse
|
|
961
|
+
});
|
|
962
|
+
return await this.synchroniseTokensAsync(null, index+1);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
1001
965
|
} catch (exception) {
|
|
1002
966
|
console.error(exception);
|
|
1003
967
|
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exception" ,exception: exception.message});
|
|
968
|
+
return this.synchroniseTokensAsync(refreshToken, index+1);
|
|
1004
969
|
}
|
|
1005
|
-
index++;
|
|
1006
970
|
}
|
|
1007
|
-
|
|
971
|
+
|
|
972
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token` });
|
|
973
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
1008
974
|
}
|
|
1009
975
|
|
|
1010
|
-
|
|
1011
|
-
async syncTokensAsync() {
|
|
976
|
+
async syncTokensInfoAsync(configuration, configurationName, currentTokens) {
|
|
1012
977
|
// Service Worker can be killed by the browser (when it wants,for example after 10 seconds of inactivity, so we retreieve the session if it happen)
|
|
1013
|
-
const configuration = this.configuration;
|
|
1014
|
-
if(!
|
|
1015
|
-
return;
|
|
978
|
+
//const configuration = this.configuration;
|
|
979
|
+
if (!currentTokens) {
|
|
980
|
+
return { tokens : null, status: "NOT_CONNECTED"};
|
|
1016
981
|
}
|
|
1017
982
|
|
|
1018
983
|
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
1019
|
-
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url,
|
|
984
|
+
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
|
|
1020
985
|
if (serviceWorker) {
|
|
1021
|
-
const {
|
|
1022
|
-
if(
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
else if (
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
this.tokens = await setTokensAsync(serviceWorker, silent_token_response.tokens);
|
|
1033
|
-
} else{
|
|
1034
|
-
this.publishEvent(eventNames.syncTokensAsync_error, {message:"no token found in result"});
|
|
1035
|
-
if(this.timeoutId){
|
|
1036
|
-
timer.clearTimeout(this.timeoutId);
|
|
1037
|
-
this.timeoutId=null;
|
|
1038
|
-
}
|
|
1039
|
-
return;
|
|
1040
|
-
}
|
|
1041
|
-
} catch (exceptionSilent) {
|
|
1042
|
-
console.error(exceptionSilent);
|
|
1043
|
-
this.publishEvent(eventNames.syncTokensAsync_error, exceptionSilent);
|
|
1044
|
-
if(this.timeoutId){
|
|
1045
|
-
timer.clearTimeout(this.timeoutId);
|
|
1046
|
-
this.timeoutId=null;
|
|
1047
|
-
}
|
|
1048
|
-
return;
|
|
1049
|
-
}
|
|
1050
|
-
this.syncTokensAsyncPromise = null;
|
|
1051
|
-
this.publishEvent(eventNames.syncTokensAsync_end, {});
|
|
986
|
+
const {status, tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
|
|
987
|
+
if (status == "LOGGED_OUT") {
|
|
988
|
+
return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB"};
|
|
989
|
+
}else if (status == "SESSIONS_LOST") {
|
|
990
|
+
return { tokens : null, status: "SESSIONS_LOST"};
|
|
991
|
+
} else if (!status || !tokens) {
|
|
992
|
+
return { tokens : null, status: "REQUIRE_SYNC_TOKENS"};
|
|
993
|
+
} else if(tokens.issuedAt !== currentTokens.issuedAt) {
|
|
994
|
+
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
|
|
995
|
+
const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
|
|
996
|
+
return { tokens : tokens, status };
|
|
1052
997
|
}
|
|
1053
998
|
} else {
|
|
1054
|
-
const session = initSession(
|
|
1055
|
-
const {tokens} = await session.initAsync();
|
|
1056
|
-
if(!tokens){
|
|
1057
|
-
|
|
1058
|
-
|
|
999
|
+
const session = initSession(configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
|
|
1000
|
+
const {tokens, status } = await session.initAsync();
|
|
1001
|
+
if (!tokens) {
|
|
1002
|
+
return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB"};
|
|
1003
|
+
} else if (status == "SESSIONS_LOST") {
|
|
1004
|
+
return { tokens : null, status: "SESSIONS_LOST"};
|
|
1005
|
+
}
|
|
1006
|
+
else if(tokens.issuedAt !== currentTokens.issuedAt){
|
|
1007
|
+
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
|
|
1008
|
+
const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
|
|
1009
|
+
return { tokens : tokens, status };
|
|
1059
1010
|
}
|
|
1060
1011
|
}
|
|
1061
|
-
}
|
|
1062
1012
|
|
|
1013
|
+
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, currentTokens.expiresAt);
|
|
1014
|
+
const status = (timeLeft > 0) ? "TOKENS_VALID" : "TOKENS_INVALID";
|
|
1015
|
+
return { tokens:currentTokens, status};
|
|
1016
|
+
}
|
|
1063
1017
|
|
|
1064
1018
|
loginCallbackWithAutoTokensRenewPromise:Promise<loginCallbackResult> = null;
|
|
1065
1019
|
loginCallbackWithAutoTokensRenewAsync():Promise<loginCallbackResult>{
|
|
@@ -1077,24 +1031,39 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
1077
1031
|
return userInfoAsync(this);
|
|
1078
1032
|
}
|
|
1079
1033
|
|
|
1080
|
-
async destroyAsync() {
|
|
1034
|
+
async destroyAsync(status) {
|
|
1081
1035
|
timer.clearTimeout(this.timeoutId);
|
|
1082
1036
|
this.timeoutId=null;
|
|
1083
1037
|
if(this.checkSessionIFrame){
|
|
1084
1038
|
this.checkSessionIFrame.stop();
|
|
1085
1039
|
}
|
|
1086
1040
|
if(this.serviceWorker){
|
|
1087
|
-
await this.serviceWorker.clearAsync();
|
|
1041
|
+
await this.serviceWorker.clearAsync(status);
|
|
1088
1042
|
}
|
|
1089
1043
|
if(this.session){
|
|
1090
|
-
await this.session.clearAsync();
|
|
1044
|
+
await this.session.clearAsync(status);
|
|
1091
1045
|
}
|
|
1092
1046
|
this.tokens = null;
|
|
1093
1047
|
this.userInfo = null;
|
|
1094
|
-
|
|
1095
|
-
|
|
1048
|
+
// this.events = [];
|
|
1096
1049
|
}
|
|
1097
1050
|
|
|
1051
|
+
async logoutSameTabAsync(clientId, sub){
|
|
1052
|
+
// @ts-ignore
|
|
1053
|
+
if(this.configuration.monitor_session&& this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1054
|
+
this.publishEvent(eventNames.logout_from_same_tab, {"message": sub});
|
|
1055
|
+
await this.destroyAsync("LOGGED_OUT");
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
async logoutOtherTabAsync(clientId, sub){
|
|
1060
|
+
// @ts-ignore
|
|
1061
|
+
if(this.configuration.monitor_session && this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1062
|
+
await this.destroyAsync("LOGGED_OUT");
|
|
1063
|
+
this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor", "sub": sub});
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1098
1067
|
async logoutAsync(callbackPathOrUrl: string | undefined = undefined, extras: StringMap = null) {
|
|
1099
1068
|
const configuration = this.configuration;
|
|
1100
1069
|
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
@@ -1111,7 +1080,16 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
1111
1080
|
const url = isUri ? callbackPathOrUrl : window.location.origin + path;
|
|
1112
1081
|
// @ts-ignore
|
|
1113
1082
|
const idToken = this.tokens ? this.tokens.idToken : "";
|
|
1114
|
-
|
|
1083
|
+
// @ts-ignore
|
|
1084
|
+
const sub = this.tokens && this.tokens.idTokenPayload ? this.tokens.idTokenPayload.sub : null;
|
|
1085
|
+
await this.destroyAsync("LOGGED_OUT");
|
|
1086
|
+
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
1087
|
+
if(oidc !== this) {
|
|
1088
|
+
// @ts-ignore
|
|
1089
|
+
await oidc.logoutSameTabAsync(this.configuration.client_id, sub);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1115
1093
|
if(oidcServerConfiguration.endSessionEndpoint) {
|
|
1116
1094
|
let extraQueryString = "";
|
|
1117
1095
|
if(extras){
|