@axa-fr/react-oidc 6.0.0-beta13 → 6.0.0-beta16
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/dist/FetchToken.d.ts.map +1 -1
- package/dist/FetchToken.js +10 -6
- package/dist/FetchToken.js.map +1 -1
- package/dist/OidcSecure.js +2 -2
- package/dist/OidcSecure.js.map +1 -1
- package/dist/OidcServiceWorker.js +38 -13
- package/dist/ReactOidc.js +1 -1
- 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/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 +9 -7
- package/dist/vanilla/oidc.d.ts.map +1 -1
- package/dist/vanilla/oidc.js +347 -460
- package/dist/vanilla/oidc.js.map +1 -1
- package/package.json +1 -1
- package/src/oidc/FetchToken.tsx +7 -4
- package/src/oidc/OidcSecure.tsx +2 -2
- package/src/oidc/ReactOidc.tsx +1 -1
- package/src/oidc/core/default-component/SilentLogin.component.tsx +1 -1
- package/src/oidc/vanilla/OidcServiceWorker.js +38 -13
- package/src/oidc/vanilla/initSession.ts +6 -7
- package/src/oidc/vanilla/initWorker.ts +6 -15
- package/src/oidc/vanilla/oidc.ts +180 -268
- package/src/oidc/vanilla/parseTokens.js +104 -0
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,29 +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
|
-
const data = {
|
|
57
|
-
accessToken: tokens.access_token,
|
|
58
|
-
expiresIn: tokens.expires_in,
|
|
59
|
-
idToken: tokens.id_token,
|
|
60
|
-
refreshToken: tokens.refresh_token,
|
|
61
|
-
scope: tokens.scope,
|
|
62
|
-
tokenType: tokens.token_type,
|
|
63
|
-
issuedAt: tokens.issued_at
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
if(tokens.accessTokenPayload !== undefined){
|
|
67
|
-
// @ts-ignore
|
|
68
|
-
data.accessTokenPayload = tokens.accessTokenPayload;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return { success : true,
|
|
72
|
-
data
|
|
51
|
+
return {
|
|
52
|
+
success : true,
|
|
53
|
+
data: parseOriginalTokens(tokens)
|
|
73
54
|
};
|
|
74
55
|
}
|
|
75
56
|
|
|
@@ -89,7 +70,6 @@ const internalFetch = async (url, headers, numberRetry=0) => {
|
|
|
89
70
|
throw e;
|
|
90
71
|
}
|
|
91
72
|
} else {
|
|
92
|
-
|
|
93
73
|
console.error(e.message);
|
|
94
74
|
throw e; // rethrow other unexpected errors
|
|
95
75
|
}
|
|
@@ -115,36 +95,6 @@ export class OidcAuthorizationServiceConfiguration extends AuthorizationServiceC
|
|
|
115
95
|
|
|
116
96
|
}
|
|
117
97
|
|
|
118
|
-
const idTokenPayload = (token) => {
|
|
119
|
-
const base64Url = token.split('.')[1];
|
|
120
|
-
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
|
121
|
-
const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
|
|
122
|
-
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
|
123
|
-
}).join(''));
|
|
124
|
-
|
|
125
|
-
return JSON.parse(jsonPayload);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const countLetter = (str, find)=> {
|
|
129
|
-
return (str.split(find)).length - 1;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const extractAccessTokenPayload = tokens => {
|
|
133
|
-
if(tokens.accessTokenPayload)
|
|
134
|
-
{
|
|
135
|
-
return tokens.accessTokenPayload;
|
|
136
|
-
}
|
|
137
|
-
const accessToken = tokens.accessToken;
|
|
138
|
-
try{
|
|
139
|
-
if (!accessToken || countLetter(accessToken,'.') != 2) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
return JSON.parse(atob(accessToken.split('.')[1]));
|
|
143
|
-
} catch (e) {
|
|
144
|
-
console.warn(e);
|
|
145
|
-
}
|
|
146
|
-
return null;
|
|
147
|
-
};
|
|
148
98
|
|
|
149
99
|
export interface StringMap {
|
|
150
100
|
[key: string]: string;
|
|
@@ -200,42 +150,45 @@ const loginCallbackWithAutoTokensRenewAsync = async (oidc) => {
|
|
|
200
150
|
}
|
|
201
151
|
|
|
202
152
|
const autoRenewTokens = (oidc, refreshToken, expiresAt) => {
|
|
203
|
-
const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second
|
|
153
|
+
const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second;
|
|
204
154
|
return timer.setTimeout(async () => {
|
|
205
|
-
const
|
|
206
|
-
const timeInfo = { timeLeft
|
|
155
|
+
const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
|
|
156
|
+
const timeInfo = { timeLeft };
|
|
207
157
|
oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
oidc.tokens= await setTokensAsync(oidc.serviceWorker, tokens);
|
|
158
|
+
const {tokens, status} = await oidc.synchroniseTokensAsync(refreshToken);
|
|
159
|
+
oidc.tokens= tokens;
|
|
211
160
|
if(!oidc.serviceWorker){
|
|
212
161
|
await oidc.session.setTokens(oidc.tokens);
|
|
213
162
|
}
|
|
214
163
|
if(!oidc.tokens){
|
|
215
|
-
|
|
216
|
-
oidc.checkSessionIFrame.stop();
|
|
217
|
-
oidc.checkSessionIFrame = null;
|
|
218
|
-
}
|
|
164
|
+
await oidc.destroyAsync(status);
|
|
219
165
|
return;
|
|
220
166
|
}
|
|
221
|
-
|
|
167
|
+
|
|
222
168
|
if(oidc.timeoutId) {
|
|
223
169
|
oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt);
|
|
224
170
|
}
|
|
225
|
-
|
|
226
|
-
const tokens = await oidc.syncTokensAsync();
|
|
227
|
-
if(tokens && oidc.timeoutId) {
|
|
228
|
-
oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, tokens.expiresAt);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
171
|
+
|
|
231
172
|
}, 1000);
|
|
232
173
|
}
|
|
233
174
|
|
|
234
175
|
const getLoginSessionKey = (configurationName:string, redirectUri:string) => {
|
|
235
176
|
return `oidc_login.${configurationName}:${redirectUri}`;
|
|
236
177
|
}
|
|
178
|
+
|
|
179
|
+
const setLoginParams = (configurationName:string, redirectUri:string, data) =>{
|
|
180
|
+
const sessionKey = getLoginSessionKey(configurationName, redirectUri);
|
|
181
|
+
getLoginParamsCache = data
|
|
182
|
+
sessionStorage[sessionKey] = JSON.stringify(data);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let getLoginParamsCache = null;
|
|
237
186
|
const getLoginParams = (configurationName, redirectUri) => {
|
|
238
|
-
|
|
187
|
+
const dataString = sessionStorage[getLoginSessionKey(configurationName, redirectUri)];
|
|
188
|
+
if(!getLoginParamsCache){
|
|
189
|
+
getLoginParamsCache = JSON.parse(dataString);
|
|
190
|
+
}
|
|
191
|
+
return getLoginParamsCache;
|
|
239
192
|
}
|
|
240
193
|
|
|
241
194
|
const userInfoAsync = async (oidc) => {
|
|
@@ -245,11 +198,15 @@ const userInfoAsync = async (oidc) => {
|
|
|
245
198
|
if(!oidc.tokens){
|
|
246
199
|
return null;
|
|
247
200
|
}
|
|
248
|
-
if(oidc.syncTokensAsyncPromise){
|
|
249
|
-
await oidc.syncTokensAsyncPromise;
|
|
250
|
-
}
|
|
251
201
|
const accessToken = oidc.tokens.accessToken;
|
|
252
|
-
|
|
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
|
+
|
|
253
210
|
const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
|
|
254
211
|
const url = oidcServerConfiguration.userInfoEndpoint;
|
|
255
212
|
const fetchUserInfo = async (accessToken) => {
|
|
@@ -271,28 +228,6 @@ const userInfoAsync = async (oidc) => {
|
|
|
271
228
|
return userInfo;
|
|
272
229
|
}
|
|
273
230
|
|
|
274
|
-
const setTokensAsync = async (serviceWorker, tokens) =>{
|
|
275
|
-
let accessTokenPayload;
|
|
276
|
-
/*if(tokens == null){
|
|
277
|
-
if(serviceWorker){
|
|
278
|
-
await serviceWorker.clearAsync();
|
|
279
|
-
}
|
|
280
|
-
return null;
|
|
281
|
-
}*/
|
|
282
|
-
if(tokens.accessTokenPayload !== undefined) {
|
|
283
|
-
accessTokenPayload = tokens.accessTokenPayload;//await serviceWorker.getAccessTokenPayloadAsync();
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
accessTokenPayload = extractAccessTokenPayload(tokens);
|
|
287
|
-
}
|
|
288
|
-
const _idTokenPayload = idTokenPayload(tokens.idToken);
|
|
289
|
-
|
|
290
|
-
const idTokenExipreAt =(_idTokenPayload && _idTokenPayload.exp) ? _idTokenPayload.exp: Number.MAX_VALUE;
|
|
291
|
-
const accessTokenExpiresAt = (accessTokenPayload && accessTokenPayload.exp)? accessTokenPayload.exp : tokens.issuedAt + tokens.expiresIn;
|
|
292
|
-
const expiresAt = idTokenExipreAt < accessTokenExpiresAt ? idTokenExipreAt : accessTokenExpiresAt;
|
|
293
|
-
return {...tokens, idTokenPayload: _idTokenPayload, accessTokenPayload, expiresAt};
|
|
294
|
-
}
|
|
295
|
-
|
|
296
231
|
const eventNames = {
|
|
297
232
|
service_worker_not_supported_by_browser: "service_worker_not_supported_by_browser",
|
|
298
233
|
token_aquired: "token_aquired",
|
|
@@ -390,7 +325,12 @@ export class Oidc {
|
|
|
390
325
|
silent_login_uri = `${configuration.silent_redirect_uri.replace("-callback", "").replace("callback", "")}-login`;
|
|
391
326
|
}
|
|
392
327
|
|
|
393
|
-
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
|
+
};
|
|
394
334
|
this.configurationName= configurationName;
|
|
395
335
|
this.tokens = null
|
|
396
336
|
this.userInfo = null;
|
|
@@ -398,7 +338,7 @@ export class Oidc {
|
|
|
398
338
|
this.timeoutId = null;
|
|
399
339
|
this.serviceWorker = null;
|
|
400
340
|
this.session = null;
|
|
401
|
-
this.
|
|
341
|
+
this.synchroniseTokensAsync.bind(this);
|
|
402
342
|
this.loginCallbackWithAutoTokensRenewAsync.bind(this);
|
|
403
343
|
this.initAsync.bind(this);
|
|
404
344
|
this.loginCallbackAsync.bind(this);
|
|
@@ -468,17 +408,6 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
468
408
|
if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
|
|
469
409
|
return Promise.resolve(null);
|
|
470
410
|
}
|
|
471
|
-
while (document.hidden) {
|
|
472
|
-
await sleepAsync(1000);
|
|
473
|
-
this.publishEvent(eventNames.silentLoginAsync, {message:"wait because document is hidden"});
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
let numberTryOnline = 6;
|
|
477
|
-
while (!navigator.onLine && numberTryOnline > 0) {
|
|
478
|
-
await sleepAsync(1000);
|
|
479
|
-
numberTryOnline--;
|
|
480
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
|
|
481
|
-
}
|
|
482
411
|
|
|
483
412
|
try {
|
|
484
413
|
this.publishEvent(eventNames.silentLoginAsync_begin, {});
|
|
@@ -549,7 +478,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
549
478
|
}
|
|
550
479
|
}
|
|
551
480
|
};
|
|
552
|
-
const silentSigninTimeout = configuration.silent_login_timeout
|
|
481
|
+
const silentSigninTimeout = configuration.silent_login_timeout;
|
|
553
482
|
setTimeout(() => {
|
|
554
483
|
if (!isResolved) {
|
|
555
484
|
self.publishEvent(eventNames.silentLoginAsync_error, {reason: "timeout"});
|
|
@@ -583,8 +512,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
583
512
|
|
|
584
513
|
const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
|
|
585
514
|
const storage = serviceWorker ? window.localStorage : null;
|
|
586
|
-
|
|
587
|
-
return initAsyncPromise;
|
|
515
|
+
return await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage);
|
|
588
516
|
}
|
|
589
517
|
|
|
590
518
|
tryKeepExistingSessionPromise = null;
|
|
@@ -608,16 +536,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
608
536
|
if (tokens) {
|
|
609
537
|
serviceWorker.startKeepAliveServiceWorker();
|
|
610
538
|
// @ts-ignore
|
|
611
|
-
|
|
612
|
-
accessToken : tokens.access_token,
|
|
613
|
-
refreshToken : tokens.refresh_token,
|
|
614
|
-
expiresIn: tokens.expires_in,
|
|
615
|
-
idToken: tokens.id_token,
|
|
616
|
-
scope: tokens.scope,
|
|
617
|
-
tokenType: tokens.token_type,
|
|
618
|
-
issuedAt: tokens.issued_at
|
|
619
|
-
}
|
|
620
|
-
this.tokens = await setTokensAsync(serviceWorker, reformattedToken);
|
|
539
|
+
this.tokens = tokens;
|
|
621
540
|
this.serviceWorker = serviceWorker;
|
|
622
541
|
// @ts-ignore
|
|
623
542
|
this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt);
|
|
@@ -644,7 +563,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
644
563
|
const {tokens} = await session.initAsync();
|
|
645
564
|
if (tokens) {
|
|
646
565
|
// @ts-ignore
|
|
647
|
-
this.tokens =
|
|
566
|
+
this.tokens = setTokens(tokens);
|
|
648
567
|
//session.setTokens(this.tokens);
|
|
649
568
|
this.session = session;
|
|
650
569
|
// @ts-ignore
|
|
@@ -682,7 +601,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
682
601
|
}
|
|
683
602
|
|
|
684
603
|
loginPromise: Promise<any>=null;
|
|
685
|
-
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) {
|
|
686
605
|
if(this.loginPromise !== null){
|
|
687
606
|
return this.loginPromise;
|
|
688
607
|
}
|
|
@@ -699,9 +618,8 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
699
618
|
scope = configuration.scope;
|
|
700
619
|
}
|
|
701
620
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
621
|
+
setLoginParams(this.configurationName, redirectUri, {callbackPath: url, extras, state});
|
|
622
|
+
|
|
705
623
|
let serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
706
624
|
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
707
625
|
let storage;
|
|
@@ -776,7 +694,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
776
694
|
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
777
695
|
//if(oidc !== this) {
|
|
778
696
|
// @ts-ignore
|
|
779
|
-
await oidc.logoutOtherTabAsync(idTokenPayload.sub);
|
|
697
|
+
await oidc.logoutOtherTabAsync(this.configuration.client_id, idTokenPayload.sub);
|
|
780
698
|
//}
|
|
781
699
|
}
|
|
782
700
|
//await this.destroyAsync();
|
|
@@ -808,7 +726,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
808
726
|
const response = await this._loginCallbackAsync(isSilenSignin);
|
|
809
727
|
// @ts-ignore
|
|
810
728
|
const tokens = response.tokens;
|
|
811
|
-
const parsedTokens =
|
|
729
|
+
const parsedTokens = setTokens(tokens);
|
|
812
730
|
this.tokens = parsedTokens;
|
|
813
731
|
if(!this.serviceWorker){
|
|
814
732
|
await this.session.setTokens(parsedTokens);
|
|
@@ -943,158 +861,154 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
943
861
|
}
|
|
944
862
|
}
|
|
945
863
|
|
|
946
|
-
async
|
|
864
|
+
async synchroniseTokensAsync(refreshToken, index=0) {
|
|
947
865
|
|
|
866
|
+
if (document.hidden) {
|
|
867
|
+
await sleepAsync(1000);
|
|
868
|
+
this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
|
|
869
|
+
return await this.synchroniseTokensAsync(refreshToken, index);
|
|
870
|
+
}
|
|
871
|
+
let numberTryOnline = 6;
|
|
872
|
+
while (!navigator.onLine && numberTryOnline > 0) {
|
|
873
|
+
await sleepAsync(1000);
|
|
874
|
+
numberTryOnline--;
|
|
875
|
+
this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
const configuration = this.configuration;
|
|
948
879
|
const localsilentLoginAsync= async () => {
|
|
949
880
|
try {
|
|
950
881
|
const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
|
|
951
|
-
const silent_token_response = await this.silentLoginAsync(
|
|
882
|
+
const silent_token_response = await this.silentLoginAsync({
|
|
883
|
+
...loginParams.extras,
|
|
884
|
+
prompt: "none"
|
|
885
|
+
}, loginParams.state);
|
|
952
886
|
if (silent_token_response) {
|
|
953
|
-
|
|
887
|
+
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
888
|
+
return {tokens:silent_token_response.tokens, status:"LOGGED"};
|
|
954
889
|
}
|
|
955
890
|
} catch (exceptionSilent) {
|
|
956
891
|
console.error(exceptionSilent);
|
|
892
|
+
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exceptionSilent" ,exception: exceptionSilent.message});
|
|
893
|
+
if(exceptionSilent && exceptionSilent.message && exceptionSilent.message.startsWith("oidc")){
|
|
894
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent` });
|
|
895
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
896
|
+
}
|
|
897
|
+
await sleepAsync(1000);
|
|
898
|
+
throw exceptionSilent;
|
|
957
899
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
this.timeoutId=null;
|
|
961
|
-
}
|
|
962
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: "refresh token and silent refresh failed"});
|
|
963
|
-
return null;
|
|
900
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent return` });
|
|
901
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
964
902
|
}
|
|
965
|
-
|
|
966
|
-
const configuration = this.configuration;
|
|
967
|
-
const clientId = configuration.client_id;
|
|
968
|
-
const redirectUri = configuration.redirect_uri;
|
|
969
|
-
const authority = configuration.authority;
|
|
970
|
-
|
|
971
|
-
if(!refreshToken)
|
|
972
|
-
{
|
|
973
|
-
return await localsilentLoginAsync();
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
let extras = {};
|
|
977
|
-
if(configuration.token_request_extras) {
|
|
978
|
-
for (let [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
979
|
-
extras[key] = value;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
983
|
-
|
|
984
|
-
const details = {
|
|
985
|
-
client_id: clientId,
|
|
986
|
-
redirect_uri: redirectUri,
|
|
987
|
-
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
988
|
-
refresh_token: refreshToken,
|
|
989
|
-
};
|
|
990
903
|
|
|
991
|
-
|
|
992
|
-
while (index <=4) {
|
|
904
|
+
if (index <=4) {
|
|
993
905
|
try {
|
|
994
|
-
|
|
995
|
-
if(
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
|
|
999
|
-
}
|
|
1000
|
-
let numberTryOnline = 6;
|
|
1001
|
-
while (!navigator.onLine && numberTryOnline > 0) {
|
|
1002
|
-
await sleepAsync(1000);
|
|
1003
|
-
numberTryOnline--;
|
|
1004
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
|
|
1008
|
-
if (tokenResponse.success) {
|
|
1009
|
-
this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
|
|
1010
|
-
return tokenResponse.data;
|
|
1011
|
-
} else {
|
|
1012
|
-
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "bad request" , tokenResponse: tokenResponse});
|
|
906
|
+
|
|
907
|
+
if(!refreshToken)
|
|
908
|
+
{
|
|
909
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
|
|
1013
910
|
return await localsilentLoginAsync();
|
|
1014
911
|
}
|
|
912
|
+
const { status, tokens } = await this.syncTokensInfoAsync(configuration, this.configurationName, this.tokens);
|
|
913
|
+
switch (status) {
|
|
914
|
+
case "SESSION_LOST":
|
|
915
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token session lost` });
|
|
916
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
917
|
+
case "NOT_CONNECTED":
|
|
918
|
+
return {tokens:null, status:null};
|
|
919
|
+
case "TOKENS_VALID":
|
|
920
|
+
case "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID":
|
|
921
|
+
return {tokens, status:"LOGGED_IN"};
|
|
922
|
+
case "LOGOUT_FROM_ANOTHER_TAB":
|
|
923
|
+
this.publishEvent(eventNames.logout_from_another_tab, {"status": "session syncTokensAsync"});
|
|
924
|
+
return {tokens:null, status:"LOGGED_OUT"};
|
|
925
|
+
case "REQUIRE_SYNC_TOKENS":
|
|
926
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
|
|
927
|
+
return await localsilentLoginAsync();
|
|
928
|
+
default:
|
|
929
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
|
|
930
|
+
const clientId = configuration.client_id;
|
|
931
|
+
const redirectUri = configuration.redirect_uri;
|
|
932
|
+
const authority = configuration.authority;
|
|
933
|
+
let extras = {};
|
|
934
|
+
if(configuration.token_request_extras) {
|
|
935
|
+
for (let [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
936
|
+
extras[key] = value;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
const details = {
|
|
940
|
+
client_id: clientId,
|
|
941
|
+
redirect_uri: redirectUri,
|
|
942
|
+
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
943
|
+
refresh_token: tokens.refreshToken,
|
|
944
|
+
};
|
|
945
|
+
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
946
|
+
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
|
|
947
|
+
if (tokenResponse.success) {
|
|
948
|
+
this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
|
|
949
|
+
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
950
|
+
return {tokens: tokenResponse.data, status:"LOGGED_IN"};
|
|
951
|
+
} else {
|
|
952
|
+
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
953
|
+
message: "bad request",
|
|
954
|
+
tokenResponse: tokenResponse
|
|
955
|
+
});
|
|
956
|
+
return await this.synchroniseTokensAsync(null, index+1);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
1015
959
|
} catch (exception) {
|
|
1016
960
|
console.error(exception);
|
|
1017
961
|
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exception" ,exception: exception.message});
|
|
962
|
+
return this.synchroniseTokensAsync(refreshToken, index+1);
|
|
1018
963
|
}
|
|
1019
|
-
index++;
|
|
1020
964
|
}
|
|
1021
|
-
|
|
965
|
+
|
|
966
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token` });
|
|
967
|
+
return {tokens:null, status:"SESSION_LOST"};
|
|
1022
968
|
}
|
|
1023
969
|
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
if (!this.tokens) {
|
|
1031
|
-
return null;
|
|
1032
|
-
}
|
|
970
|
+
async syncTokensInfoAsync(configuration, configurationName, currentTokens) {
|
|
971
|
+
// 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)
|
|
972
|
+
//const configuration = this.configuration;
|
|
973
|
+
if (!currentTokens) {
|
|
974
|
+
return { tokens : null, status: "NOT_CONNECTED"};
|
|
975
|
+
}
|
|
1033
976
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
return null;
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
this.publishEvent(eventNames.syncTokensAsync_end, {});
|
|
1058
|
-
return null;
|
|
1059
|
-
}
|
|
1060
|
-
} catch (exceptionSilent) {
|
|
1061
|
-
console.error(exceptionSilent);
|
|
1062
|
-
this.publishEvent(eventNames.syncTokensAsync_error, exceptionSilent);
|
|
1063
|
-
if (this.timeoutId) {
|
|
1064
|
-
timer.clearTimeout(this.timeoutId);
|
|
1065
|
-
this.timeoutId = null;
|
|
1066
|
-
}
|
|
1067
|
-
this.publishEvent(eventNames.syncTokensAsync_end, {});
|
|
1068
|
-
return null;
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
} else {
|
|
1072
|
-
const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
|
|
1073
|
-
const {tokens} = await session.initAsync();
|
|
1074
|
-
if (!tokens) {
|
|
1075
|
-
this.publishEvent(eventNames.logout_from_another_tab, {"message": "session syncTokensAsync"});
|
|
1076
|
-
await this.destroyAsync();
|
|
1077
|
-
return null;
|
|
977
|
+
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
978
|
+
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
|
|
979
|
+
if (serviceWorker) {
|
|
980
|
+
const {status, tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
|
|
981
|
+
if (status == "LOGGED_OUT") {
|
|
982
|
+
return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB"};
|
|
983
|
+
}else if (status == "SESSIONS_LOST") {
|
|
984
|
+
return { tokens : null, status: "SESSIONS_LOST"};
|
|
985
|
+
} else if (!status || !tokens) {
|
|
986
|
+
return { tokens : null, status: "REQUIRE_SYNC_TOKENS"};
|
|
987
|
+
} else if(tokens.issuedAt !== currentTokens.issuedAt) {
|
|
988
|
+
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
|
|
989
|
+
const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
|
|
990
|
+
return { tokens : tokens, status };
|
|
991
|
+
}
|
|
992
|
+
} else {
|
|
993
|
+
const session = initSession(configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
|
|
994
|
+
const {tokens, status } = await session.initAsync();
|
|
995
|
+
if (!tokens) {
|
|
996
|
+
return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB"};
|
|
997
|
+
} else if (status == "SESSIONS_LOST") {
|
|
998
|
+
return { tokens : null, status: "SESSIONS_LOST"};
|
|
1078
999
|
}
|
|
1000
|
+
else if(tokens.issuedAt !== currentTokens.issuedAt){
|
|
1001
|
+
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
|
|
1002
|
+
const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
|
|
1003
|
+
return { tokens : tokens, status };
|
|
1079
1004
|
}
|
|
1080
|
-
return this.tokens;
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
if(this.syncTokensAsyncPromise){
|
|
1084
|
-
return this.syncTokensAsyncPromise;
|
|
1085
1005
|
}
|
|
1086
1006
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
}
|
|
1091
|
-
return result;
|
|
1092
|
-
});
|
|
1093
|
-
|
|
1094
|
-
return this.syncTokensAsyncPromise
|
|
1007
|
+
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, currentTokens.expiresAt);
|
|
1008
|
+
const status = (timeLeft > 0) ? "TOKENS_VALID" : "TOKENS_INVALID";
|
|
1009
|
+
return { tokens:currentTokens, status};
|
|
1095
1010
|
}
|
|
1096
1011
|
|
|
1097
|
-
|
|
1098
1012
|
loginCallbackWithAutoTokensRenewPromise:Promise<loginCallbackResult> = null;
|
|
1099
1013
|
loginCallbackWithAutoTokensRenewAsync():Promise<loginCallbackResult>{
|
|
1100
1014
|
if(this.loginCallbackWithAutoTokensRenewPromise !== null){
|
|
@@ -1111,37 +1025,35 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
1111
1025
|
return userInfoAsync(this);
|
|
1112
1026
|
}
|
|
1113
1027
|
|
|
1114
|
-
async destroyAsync() {
|
|
1028
|
+
async destroyAsync(status) {
|
|
1115
1029
|
timer.clearTimeout(this.timeoutId);
|
|
1116
1030
|
this.timeoutId=null;
|
|
1117
1031
|
if(this.checkSessionIFrame){
|
|
1118
1032
|
this.checkSessionIFrame.stop();
|
|
1119
1033
|
}
|
|
1120
1034
|
if(this.serviceWorker){
|
|
1121
|
-
await this.serviceWorker.clearAsync();
|
|
1035
|
+
await this.serviceWorker.clearAsync(status);
|
|
1122
1036
|
}
|
|
1123
1037
|
if(this.session){
|
|
1124
|
-
await this.session.clearAsync();
|
|
1038
|
+
await this.session.clearAsync(status);
|
|
1125
1039
|
}
|
|
1126
1040
|
this.tokens = null;
|
|
1127
1041
|
this.userInfo = null;
|
|
1128
1042
|
// this.events = [];
|
|
1129
1043
|
}
|
|
1130
1044
|
|
|
1131
|
-
async logoutSameTabAsync(sub){
|
|
1045
|
+
async logoutSameTabAsync(clientId, sub){
|
|
1132
1046
|
// @ts-ignore
|
|
1133
|
-
if(this.configuration.monitor_session && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1047
|
+
if(this.configuration.monitor_session&& this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1134
1048
|
this.publishEvent(eventNames.logout_from_same_tab, {"message": sub});
|
|
1135
|
-
await this.destroyAsync();
|
|
1049
|
+
await this.destroyAsync("LOGGED_OUT");
|
|
1136
1050
|
}
|
|
1137
1051
|
}
|
|
1138
1052
|
|
|
1139
|
-
async logoutOtherTabAsync(sub){
|
|
1053
|
+
async logoutOtherTabAsync(clientId, sub){
|
|
1140
1054
|
// @ts-ignore
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
await this.destroyAsync();
|
|
1144
|
-
console.log("logoutOtherTabAsync(sub)" +this.configurationName);
|
|
1055
|
+
if(this.configuration.monitor_session && this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1056
|
+
await this.destroyAsync("LOGGED_OUT");
|
|
1145
1057
|
this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor", "sub": sub});
|
|
1146
1058
|
}
|
|
1147
1059
|
}
|
|
@@ -1164,11 +1076,11 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
1164
1076
|
const idToken = this.tokens ? this.tokens.idToken : "";
|
|
1165
1077
|
// @ts-ignore
|
|
1166
1078
|
const sub = this.tokens && this.tokens.idTokenPayload ? this.tokens.idTokenPayload.sub : null;
|
|
1167
|
-
await this.destroyAsync();
|
|
1079
|
+
await this.destroyAsync("LOGGED_OUT");
|
|
1168
1080
|
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
1169
1081
|
if(oidc !== this) {
|
|
1170
1082
|
// @ts-ignore
|
|
1171
|
-
await oidc.logoutSameTabAsync(sub);
|
|
1083
|
+
await oidc.logoutSameTabAsync(this.configuration.client_id, sub);
|
|
1172
1084
|
}
|
|
1173
1085
|
}
|
|
1174
1086
|
|