@axa-fr/react-oidc 6.0.0-alpha8 → 6.0.0-beta1
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 +15 -8
- package/dist/OidcProvider.d.ts +1 -2
- package/dist/OidcProvider.d.ts.map +1 -1
- package/dist/OidcProvider.js +1 -1
- package/dist/OidcProvider.js.map +1 -1
- package/dist/core/default-component/SilentCallback.component.js +2 -2
- package/dist/core/default-component/SilentCallback.component.js.map +1 -1
- package/dist/core/default-component/SilentLogin.component.d.ts +4 -0
- package/dist/core/default-component/SilentLogin.component.d.ts.map +1 -0
- package/dist/core/default-component/{SilentSignin.component.js → SilentLogin.component.js} +3 -3
- package/dist/core/default-component/SilentLogin.component.js.map +1 -0
- package/dist/core/routes/OidcRoutes.d.ts +1 -1
- package/dist/core/routes/OidcRoutes.d.ts.map +1 -1
- package/dist/core/routes/OidcRoutes.js +5 -5
- package/dist/core/routes/OidcRoutes.js.map +1 -1
- package/dist/vanilla/checkSessionIFrame.d.ts +6 -6
- package/dist/vanilla/checkSessionIFrame.d.ts.map +1 -1
- package/dist/vanilla/checkSessionIFrame.js +1 -1
- package/dist/vanilla/checkSessionIFrame.js.map +1 -1
- package/dist/vanilla/oidc.d.ts +9 -9
- package/dist/vanilla/oidc.d.ts.map +1 -1
- package/dist/vanilla/oidc.js +156 -135
- package/dist/vanilla/oidc.js.map +1 -1
- package/package.json +2 -2
- package/src/oidc/OidcProvider.tsx +2 -3
- package/src/oidc/core/default-component/SilentCallback.component.tsx +2 -2
- package/src/oidc/core/default-component/{SilentSignin.component.tsx → SilentLogin.component.tsx} +2 -2
- package/src/oidc/core/routes/OidcRoutes.tsx +6 -6
- package/src/oidc/vanilla/checkSessionIFrame.ts +7 -7
- package/src/oidc/vanilla/oidc.ts +105 -110
- package/dist/core/default-component/SilentSignin.component.d.ts +0 -4
- package/dist/core/default-component/SilentSignin.component.d.ts.map +0 -1
- package/dist/core/default-component/SilentSignin.component.js.map +0 -1
- package/src/App.css +0 -38
- package/src/App.specold.tsx +0 -46
- package/src/App.tsx +0 -96
- package/src/FetchUser.tsx +0 -53
- package/src/Home.tsx +0 -22
- package/src/MultiAuth.tsx +0 -116
- package/src/Profile.tsx +0 -77
- package/src/configurations.ts +0 -70
- package/src/index.css +0 -13
- package/src/index.tsx +0 -9
- package/src/logo.svg +0 -7
- package/src/override/AuthenticateError.component.tsx +0 -14
- package/src/override/Authenticating.component.tsx +0 -14
- package/src/override/Callback.component.tsx +0 -13
- package/src/override/Loading.component.tsx +0 -13
- package/src/override/ServiceWorkerNotSupported.component.tsx +0 -15
- package/src/override/SessionLost.component.tsx +0 -21
- package/src/override/style.ts +0 -10
- package/src/setupTests.js +0 -5
package/src/oidc/vanilla/oidc.ts
CHANGED
|
@@ -20,18 +20,56 @@ import {CheckSessionIFrame} from "./checkSessionIFrame"
|
|
|
20
20
|
import {getParseQueryStringFromLocation} from "./route-utils";
|
|
21
21
|
import {AuthorizationServiceConfigurationJson} from "@openid/appauth/src/authorization_service_configuration";
|
|
22
22
|
|
|
23
|
+
const performTokenRequestAsync= async (url, details, extras) => {
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
for (let [key, value] of Object.entries(extras)) {
|
|
27
|
+
if (details[key] === undefined) {
|
|
28
|
+
details[key] = value;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let formBody = [];
|
|
33
|
+
for (const property in details) {
|
|
34
|
+
const encodedKey = encodeURIComponent(property);
|
|
35
|
+
const encodedValue = encodeURIComponent(details[property]);
|
|
36
|
+
formBody.push(`${encodedKey}=${encodedValue}`);
|
|
37
|
+
}
|
|
38
|
+
const formBodyString = formBody.join("&");
|
|
39
|
+
|
|
40
|
+
const response = await internalFetch(url, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
|
44
|
+
},
|
|
45
|
+
body: formBodyString,
|
|
46
|
+
});
|
|
47
|
+
if(response.status !== 200){
|
|
48
|
+
return {success:false, status: response.status}
|
|
49
|
+
}
|
|
50
|
+
const result = await response.json();
|
|
51
|
+
return { success : true,
|
|
52
|
+
data : {
|
|
53
|
+
accessToken: result.access_token,
|
|
54
|
+
expiresIn: result.expires_in,
|
|
55
|
+
idToken: result.id_token,
|
|
56
|
+
refreshToken: result.refresh_token,
|
|
57
|
+
scope: result.scope,
|
|
58
|
+
tokenType: result.token_type,
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
23
62
|
|
|
24
63
|
const internalFetch = async (url, headers, numberRetry=0) => {
|
|
25
64
|
let response;
|
|
26
65
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
() => reject(new Error('Timeout')), 10000))]);
|
|
66
|
+
let controller = new AbortController();
|
|
67
|
+
setTimeout(() => controller.abort(), 10000);
|
|
68
|
+
response = await fetch(url, {...headers, signal: controller.signal});
|
|
31
69
|
} catch (e) {
|
|
32
|
-
if (e.message === '
|
|
33
|
-
|| e.message === 'Network request failed'
|
|
34
|
-
if(numberRetry <=
|
|
70
|
+
if (e.message === 'AbortError'
|
|
71
|
+
|| e.message === 'Network request failed') {
|
|
72
|
+
if(numberRetry <=1) {
|
|
35
73
|
return await internalFetch(url, headers, numberRetry + 1);
|
|
36
74
|
}
|
|
37
75
|
else {
|
|
@@ -117,8 +155,8 @@ export interface AuthorityConfiguration {
|
|
|
117
155
|
client_id: string,
|
|
118
156
|
redirect_uri: string,
|
|
119
157
|
silent_redirect_uri?:string,
|
|
120
|
-
|
|
121
|
-
|
|
158
|
+
silent_login_uri?:string,
|
|
159
|
+
silent_login_timeout?:number,
|
|
122
160
|
scope: string,
|
|
123
161
|
authority: string,
|
|
124
162
|
authority_time_cache_wellknowurl_in_second?: number,
|
|
@@ -205,7 +243,8 @@ const userInfoAsync = async (oidc) => {
|
|
|
205
243
|
const fetchUserInfo = async (accessToken) => {
|
|
206
244
|
const res = await fetch(url, {
|
|
207
245
|
headers: {
|
|
208
|
-
authorization: `Bearer ${accessToken}
|
|
246
|
+
authorization: `Bearer ${accessToken}`,
|
|
247
|
+
credentials: 'same-origin'
|
|
209
248
|
}
|
|
210
249
|
});
|
|
211
250
|
|
|
@@ -258,10 +297,10 @@ const eventNames = {
|
|
|
258
297
|
tryKeepExistingSessionAsync_begin: "tryKeepExistingSessionAsync_begin",
|
|
259
298
|
tryKeepExistingSessionAsync_end: "tryKeepExistingSessionAsync_end",
|
|
260
299
|
tryKeepExistingSessionAsync_error: "tryKeepExistingSessionAsync_error",
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
300
|
+
silentLoginAsync_begin: "silentLoginAsync_begin",
|
|
301
|
+
silentLoginAsync: "silentLoginAsync",
|
|
302
|
+
silentLoginAsync_end: "silentLoginAsync_end",
|
|
303
|
+
silentLoginAsync_error: "silentLoginAsync_error",
|
|
265
304
|
syncTokensAsync_begin: "syncTokensAsync_begin",
|
|
266
305
|
syncTokensAsync_end: "syncTokensAsync_end",
|
|
267
306
|
syncTokensAsync_error: "syncTokensAsync_error"
|
|
@@ -282,7 +321,7 @@ const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHou
|
|
|
282
321
|
const fullUrl = `${openIdIssuerUrl}/${WELL_KNOWN_PATH}/${OPENID_CONFIGURATION}`;
|
|
283
322
|
|
|
284
323
|
const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
|
|
285
|
-
const cacheJson = window.
|
|
324
|
+
const cacheJson = window.sessionStorage.getItem(localStorageKey);
|
|
286
325
|
|
|
287
326
|
const oneHourMinisecond = 1000 * timeCacheSecond;
|
|
288
327
|
// @ts-ignore
|
|
@@ -296,9 +335,8 @@ const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHou
|
|
|
296
335
|
return null;
|
|
297
336
|
}
|
|
298
337
|
|
|
299
|
-
|
|
300
338
|
const result = await response.json();
|
|
301
|
-
window.
|
|
339
|
+
window.sessionStorage.setItem(localStorageKey, JSON.stringify({result, timestamp:Date.now()}));
|
|
302
340
|
|
|
303
341
|
return new OidcAuthorizationServiceConfiguration(result);
|
|
304
342
|
}
|
|
@@ -345,6 +383,7 @@ export class Oidc {
|
|
|
345
383
|
this.removeEventSubscription.bind(this);
|
|
346
384
|
this.publishEvent.bind(this);
|
|
347
385
|
this.destroyAsync.bind(this);
|
|
386
|
+
this.logoutAsync.bind(this);
|
|
348
387
|
}
|
|
349
388
|
|
|
350
389
|
subscriveEvents(func){
|
|
@@ -376,29 +415,29 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
376
415
|
}
|
|
377
416
|
static eventNames = eventNames;
|
|
378
417
|
|
|
379
|
-
|
|
380
|
-
if (this.configuration.silent_redirect_uri) {
|
|
418
|
+
silentLoginCallbackFromIFrame(){
|
|
419
|
+
if (this.configuration.silent_redirect_uri && this.configuration.silent_login_uri) {
|
|
381
420
|
const queryParams = getParseQueryStringFromLocation(window.location.href);
|
|
382
421
|
window.top.postMessage(`${this.configurationName}_oidc_tokens:${JSON.stringify({tokens:this.tokens, sessionState:queryParams.session_state})}`, window.location.origin);
|
|
383
422
|
}
|
|
384
423
|
}
|
|
385
|
-
|
|
386
|
-
if (this.configuration.silent_redirect_uri) {
|
|
424
|
+
silentLoginErrorCallbackFromIFrame(){
|
|
425
|
+
if (this.configuration.silent_redirect_uri && this.configuration.silent_login_uri) {
|
|
387
426
|
const queryParams = getParseQueryStringFromLocation(window.location.href);
|
|
388
427
|
window.top.postMessage(`${this.configurationName}_oidc_error:${JSON.stringify({error:queryParams.error})}`, window.location.origin);
|
|
389
428
|
}
|
|
390
429
|
}
|
|
391
|
-
async
|
|
392
|
-
if (!this.configuration.silent_redirect_uri || !this.configuration.
|
|
430
|
+
async silentLoginAsync(extras:StringMap=null, state:string=null, scope:string=null) {
|
|
431
|
+
if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
|
|
393
432
|
return Promise.resolve(null);
|
|
394
433
|
}
|
|
395
434
|
while (document.hidden) {
|
|
396
435
|
await sleepAsync(1000);
|
|
397
|
-
this.publishEvent(eventNames.
|
|
436
|
+
this.publishEvent(eventNames.silentLoginAsync, {message:"wait because document is hidden"});
|
|
398
437
|
}
|
|
399
438
|
|
|
400
439
|
try {
|
|
401
|
-
this.publishEvent(eventNames.
|
|
440
|
+
this.publishEvent(eventNames.silentLoginAsync_begin, {});
|
|
402
441
|
const configuration = this.configuration
|
|
403
442
|
let queries = "";
|
|
404
443
|
|
|
@@ -425,7 +464,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
425
464
|
}
|
|
426
465
|
}
|
|
427
466
|
}
|
|
428
|
-
const link = configuration.
|
|
467
|
+
const link = configuration.silent_login_uri + queries;
|
|
429
468
|
const idx = link.indexOf("/", link.indexOf("//") + 2);
|
|
430
469
|
const iFrameOrigin = link.substr(0, idx);
|
|
431
470
|
const iframe = document.createElement('iframe');
|
|
@@ -450,14 +489,14 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
450
489
|
if (!isResolved) {
|
|
451
490
|
if(data.startsWith(key)) {
|
|
452
491
|
const result = JSON.parse(e.data.replace(key, ''));
|
|
453
|
-
self.publishEvent(eventNames.
|
|
492
|
+
self.publishEvent(eventNames.silentLoginAsync_end, {});
|
|
454
493
|
iframe.remove();
|
|
455
494
|
isResolved = true;
|
|
456
495
|
resolve(result);
|
|
457
496
|
}
|
|
458
497
|
else if(data.startsWith(key_error)) {
|
|
459
498
|
const result = JSON.parse(e.data.replace(key_error, ''));
|
|
460
|
-
self.publishEvent(eventNames.
|
|
499
|
+
self.publishEvent(eventNames.silentLoginAsync_error, result);
|
|
461
500
|
iframe.remove();
|
|
462
501
|
isResolved = true;
|
|
463
502
|
reject(result);
|
|
@@ -466,10 +505,10 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
466
505
|
}
|
|
467
506
|
}
|
|
468
507
|
};
|
|
469
|
-
const silentSigninTimeout = configuration.
|
|
508
|
+
const silentSigninTimeout = configuration.silent_login_timeout ?? 12000
|
|
470
509
|
setTimeout(() => {
|
|
471
510
|
if (!isResolved) {
|
|
472
|
-
self.publishEvent(eventNames.
|
|
511
|
+
self.publishEvent(eventNames.silentLoginAsync_error, "timeout");
|
|
473
512
|
iframe.remove();
|
|
474
513
|
isResolved = true;
|
|
475
514
|
reject("timeout");
|
|
@@ -477,12 +516,12 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
477
516
|
}, silentSigninTimeout);
|
|
478
517
|
} catch (e) {
|
|
479
518
|
iframe.remove();
|
|
480
|
-
self.publishEvent(eventNames.
|
|
519
|
+
self.publishEvent(eventNames.silentLoginAsync_error, e);
|
|
481
520
|
reject(e);
|
|
482
521
|
}
|
|
483
522
|
});
|
|
484
523
|
} catch (e) {
|
|
485
|
-
this.publishEvent(eventNames.
|
|
524
|
+
this.publishEvent(eventNames.silentLoginAsync_error, e);
|
|
486
525
|
throw e;
|
|
487
526
|
}
|
|
488
527
|
}
|
|
@@ -672,12 +711,11 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
672
711
|
this.loginPromise = null;
|
|
673
712
|
return result;
|
|
674
713
|
});
|
|
675
|
-
|
|
676
714
|
}
|
|
677
715
|
|
|
678
716
|
async startCheckSessionAsync(checkSessionIFrameUri, clientId, sessionState, isSilentSignin=false){
|
|
679
717
|
return new Promise((resolve:Function, reject) => {
|
|
680
|
-
if (this.configuration.
|
|
718
|
+
if (this.configuration.silent_login_uri && this.configuration.silent_redirect_uri && this.configuration.monitor_session && checkSessionIFrameUri && sessionState && !isSilentSignin) {
|
|
681
719
|
const checkSessionCallback = () => {
|
|
682
720
|
this.checkSessionIFrame.stop();
|
|
683
721
|
|
|
@@ -688,7 +726,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
688
726
|
const idToken = this.tokens.idToken;
|
|
689
727
|
// @ts-ignore
|
|
690
728
|
const idTokenPayload = this.tokens.idTokenPayload;
|
|
691
|
-
this.
|
|
729
|
+
this.silentLoginAsync({
|
|
692
730
|
prompt: "none",
|
|
693
731
|
id_token_hint: idToken,
|
|
694
732
|
scope: "openid"
|
|
@@ -870,15 +908,10 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
870
908
|
}
|
|
871
909
|
|
|
872
910
|
async refreshTokensAsync(refreshToken) {
|
|
873
|
-
|
|
874
|
-
/*while (document.hidden) {
|
|
875
|
-
await sleepAsync(1000);
|
|
876
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message:"wait because document is hidden"});
|
|
877
|
-
}*/
|
|
878
911
|
|
|
879
|
-
const
|
|
912
|
+
const localsilentLoginAsync= async () => {
|
|
880
913
|
try {
|
|
881
|
-
const silent_token_response = await this.
|
|
914
|
+
const silent_token_response = await this.silentLoginAsync();
|
|
882
915
|
if (silent_token_response) {
|
|
883
916
|
return silent_token_response.tokens;
|
|
884
917
|
}
|
|
@@ -889,13 +922,10 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
889
922
|
timer.clearTimeout(this.timeoutId);
|
|
890
923
|
this.timeoutId=null;
|
|
891
924
|
}
|
|
892
|
-
this.publishEvent(eventNames.refreshTokensAsync_error,
|
|
925
|
+
this.publishEvent(eventNames.refreshTokensAsync_error, {message: "refresh token and silent refresh failed"});
|
|
893
926
|
return null;
|
|
894
927
|
}
|
|
895
|
-
|
|
896
|
-
try{
|
|
897
|
-
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken});
|
|
898
|
-
|
|
928
|
+
|
|
899
929
|
const configuration = this.configuration;
|
|
900
930
|
const clientId = configuration.client_id;
|
|
901
931
|
const redirectUri = configuration.redirect_uri;
|
|
@@ -903,10 +933,9 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
903
933
|
|
|
904
934
|
if(!refreshToken)
|
|
905
935
|
{
|
|
906
|
-
return await
|
|
936
|
+
return await localsilentLoginAsync();
|
|
907
937
|
}
|
|
908
938
|
|
|
909
|
-
|
|
910
939
|
let extras = {};
|
|
911
940
|
if(configuration.token_request_extras) {
|
|
912
941
|
for (let [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
@@ -914,73 +943,39 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
914
943
|
}
|
|
915
944
|
}
|
|
916
945
|
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
// use the token response to make a request for an access token
|
|
920
|
-
const request = new TokenRequest({
|
|
946
|
+
|
|
947
|
+
const details = {
|
|
921
948
|
client_id: clientId,
|
|
922
949
|
redirect_uri: redirectUri,
|
|
923
950
|
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
924
|
-
code: undefined,
|
|
925
951
|
refresh_token: refreshToken,
|
|
926
|
-
|
|
927
|
-
});
|
|
952
|
+
};
|
|
928
953
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
};
|
|
939
|
-
|
|
940
|
-
for (let [key, value] of Object.entries(extras)) {
|
|
941
|
-
if (details[key] === undefined) {
|
|
942
|
-
details[key] = value;
|
|
954
|
+
let index = 0;
|
|
955
|
+
while (index <=2) {
|
|
956
|
+
try {
|
|
957
|
+
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
|
|
958
|
+
if(index > 1) {
|
|
959
|
+
while (document.hidden) {
|
|
960
|
+
await sleepAsync(1000);
|
|
961
|
+
this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
|
|
962
|
+
}
|
|
943
963
|
}
|
|
964
|
+
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, extras)
|
|
965
|
+
if (tokenResponse.success) {
|
|
966
|
+
this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
|
|
967
|
+
return tokenResponse.data;
|
|
968
|
+
} else {
|
|
969
|
+
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "bad request" , tokenResponse: tokenResponse});
|
|
970
|
+
return await localsilentLoginAsync();
|
|
971
|
+
}
|
|
972
|
+
} catch (exception) {
|
|
973
|
+
console.error(exception);
|
|
974
|
+
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exception" ,exception: exception.message});
|
|
944
975
|
}
|
|
945
|
-
|
|
946
|
-
let formBody = [];
|
|
947
|
-
for (const property in details) {
|
|
948
|
-
const encodedKey = encodeURIComponent(property);
|
|
949
|
-
const encodedValue = encodeURIComponent(details[property]);
|
|
950
|
-
formBody.push(`${encodedKey}=${encodedValue}`);
|
|
951
|
-
}
|
|
952
|
-
const formBodyString = formBody.join("&");
|
|
953
|
-
|
|
954
|
-
const response = await internalFetch(url, {
|
|
955
|
-
method: 'POST',
|
|
956
|
-
headers: {
|
|
957
|
-
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
|
958
|
-
},
|
|
959
|
-
body: formBodyString,
|
|
960
|
-
});
|
|
961
|
-
if(response.status >= 299){
|
|
962
|
-
throw new Error("Error refreshing token");
|
|
963
|
-
}
|
|
964
|
-
const result = await response.json();
|
|
965
|
-
return {
|
|
966
|
-
accessToken: result.access_token,
|
|
967
|
-
expiresIn: result.expires_in,
|
|
968
|
-
idToken: result.id_token,
|
|
969
|
-
refreshToken: result.refresh_token,
|
|
970
|
-
scope: result.scope,
|
|
971
|
-
tokenType: result.token_type,
|
|
972
|
-
};
|
|
976
|
+
index++;
|
|
973
977
|
}
|
|
974
|
-
|
|
975
|
-
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint)
|
|
976
|
-
|
|
977
|
-
this.publishEvent(eventNames.refreshTokensAsync_end, {message:"success"});
|
|
978
|
-
return tokenResponse;
|
|
979
|
-
} catch(exception) {
|
|
980
|
-
console.error(exception);
|
|
981
|
-
this.publishEvent(eventNames.refreshTokensAsync_silent_error, exception);
|
|
982
|
-
return await localSilentSigninAsync(exception);
|
|
983
|
-
}
|
|
978
|
+
|
|
984
979
|
}
|
|
985
980
|
|
|
986
981
|
syncTokensAsyncPromise=null;
|
|
@@ -1002,12 +997,12 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
1002
997
|
else if (isLogin == null){
|
|
1003
998
|
try {
|
|
1004
999
|
this.publishEvent(eventNames.syncTokensAsync_begin, {});
|
|
1005
|
-
this.syncTokensAsyncPromise = this.
|
|
1000
|
+
this.syncTokensAsyncPromise = this.silentLoginAsync({prompt:"none"});
|
|
1006
1001
|
const silent_token_response = await this.syncTokensAsyncPromise;
|
|
1007
1002
|
if (silent_token_response && silent_token_response.tokens) {
|
|
1008
1003
|
this.tokens = await setTokensAsync(serviceWorker, silent_token_response.tokens);
|
|
1009
1004
|
} else{
|
|
1010
|
-
this.publishEvent(eventNames.syncTokensAsync_error,
|
|
1005
|
+
this.publishEvent(eventNames.syncTokensAsync_error, {message:"no token found in result"});
|
|
1011
1006
|
if(this.timeoutId){
|
|
1012
1007
|
timer.clearTimeout(this.timeoutId);
|
|
1013
1008
|
this.timeoutId=null;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SilentSignin.component.d.ts","sourceRoot":"","sources":["../../../src/oidc/core/default-component/SilentSignin.component.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAY,aAAa,EAAC,MAAM,OAAO,CAAC;AAKtD,QAAA,MAAM,YAAY,EAAE,aAAa,CAAC,GAAG,CA2BnC,CAAC;AAEH,eAAe,YAAY,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SilentSignin.component.js","sourceRoot":"","sources":["../../../src/oidc/core/default-component/SilentSignin.component.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAAsD;AACtD,4DAAsC;AACtC,yDAA0E;AAG1E,IAAM,YAAY,GAAuB,CAAC,UAAC,EAAoB;QAAnB,iBAAiB,uBAAA;IACzD,IAAM,WAAW,GAAG,IAAA,6CAA+B,EAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1E,IAAM,OAAO,GAAI,cAAI,CAAC,GAAG,CAAC;IAC1B,IAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExC,IAAI,MAAM,GAAG,IAAI,CAAC;IAElB,KAAyB,UAA2B,EAA3B,KAAA,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAA3B,cAA2B,EAA3B,IAA2B,EAAE;QAA7C,IAAA,WAAY,EAAX,GAAG,QAAA,EAAE,KAAK,QAAA;QAChB,IAAG,GAAG,KAAK,OAAO,IAAI,GAAG,IAAI,OAAO,EAAC;YACjC,SAAS;SACZ;QACD,IAAG,MAAM,KAAK,IAAI,EAAC;YACf,MAAM,GAAG,EAAE,CAAC;SACf;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;KACvB;IAED,IAAA,iBAAS,EAAC;QACN,IAAG,CAAC,IAAI,CAAC,MAAM,EAAC;YACZ,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;SACnF;QACD,OAAO;QACP,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,6DAAK,CAAC;AACjB,CAAC,CAAC,CAAC;AAEH,kBAAe,YAAY,CAAC"}
|
package/src/App.css
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
.App {
|
|
2
|
-
text-align: center;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.App-logo {
|
|
6
|
-
height: 40vmin;
|
|
7
|
-
pointer-events: none;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
11
|
-
.App-logo {
|
|
12
|
-
animation: App-logo-spin infinite 20s linear;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.App-header {
|
|
17
|
-
background-color: #282c34;
|
|
18
|
-
min-height: 100vh;
|
|
19
|
-
display: flex;
|
|
20
|
-
flex-direction: column;
|
|
21
|
-
align-items: center;
|
|
22
|
-
justify-content: center;
|
|
23
|
-
font-size: calc(10px + 2vmin);
|
|
24
|
-
color: white;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.App-link {
|
|
28
|
-
color: #61dafb;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
@keyframes App-logo-spin {
|
|
32
|
-
from {
|
|
33
|
-
transform: rotate(0deg);
|
|
34
|
-
}
|
|
35
|
-
to {
|
|
36
|
-
transform: rotate(360deg);
|
|
37
|
-
}
|
|
38
|
-
}
|
package/src/App.specold.tsx
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// __tests__/fetch.test.js
|
|
2
|
-
/*import React from 'react'
|
|
3
|
-
import {rest} from 'msw'
|
|
4
|
-
import {setupServer} from 'msw/node'
|
|
5
|
-
import {render, fireEvent, waitFor, screen} from '@testing-library/react'
|
|
6
|
-
import '@testing-library/jest-dom'
|
|
7
|
-
import App from "./App";
|
|
8
|
-
import {act} from "react-dom/test-utils";
|
|
9
|
-
|
|
10
|
-
const server = setupServer(
|
|
11
|
-
rest.get('http://api/.well-known/openid-configuration', (req, res, ctx) => {
|
|
12
|
-
return res( ctx.status(200),ctx.json({
|
|
13
|
-
"issuer":"https://demo.identityserver.io",
|
|
14
|
-
"jwks_uri":"https://demo.identityserver.io/.well-known/openid-configuration/jwks",
|
|
15
|
-
"authorization_endpoint":"https://demo.identityserver.io/connect/authorize",
|
|
16
|
-
"token_endpoint":"https://demo.identityserver.io/connect/token",
|
|
17
|
-
"userinfo_endpoint":"https://demo.identityserver.io/connect/userinfo",
|
|
18
|
-
"end_session_endpoint":"https://demo.identityserver.io/connect/endsession",
|
|
19
|
-
"check_session_iframe":"https://demo.identityserver.io/connect/checksession",
|
|
20
|
-
"revocation_endpoint":"https://demo.identityserver.io/connect/revocation",
|
|
21
|
-
"introspection_endpoint":"https://demo.identityserver.io/connect/introspect",
|
|
22
|
-
"device_authorization_endpoint":"https://demo.identityserver.io/connect/deviceauthorization","frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"scopes_supported":["openid","profile","email","api","api.scope1","api.scope2","scope2","policyserver.runtime","policyserver.management","offline_access"],"claims_supported":["sub","name","family_name","given_name","middle_name","nickname","preferred_username","profile","picture","website","gender","birthdate","zoneinfo","locale","updated_at","email","email_verified"],"grant_types_supported":["authorization_code","client_credentials","refresh_token","implicit","password","urn:ietf:params:oauth:grant-type:device_code"],"response_types_supported":["code","token","id_token","id_token token","code id_token","code token","code id_token token"],"response_modes_supported":["form_post","query","fragment"],"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],"id_token_signing_alg_values_supported":["RS256"],"subject_types_supported":["public"],"code_challenge_methods_supported":["plain","S256"],"request_parameter_supported":true}))
|
|
23
|
-
}),
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
beforeAll(() => server.listen())
|
|
27
|
-
afterEach(() => server.resetHandlers())
|
|
28
|
-
afterAll(() => server.close())
|
|
29
|
-
|
|
30
|
-
test('Load home page then login should log', async () => {
|
|
31
|
-
|
|
32
|
-
const configuration = {
|
|
33
|
-
client_id: 'interactive.public.short',
|
|
34
|
-
redirect_uri: 'http://localhost:4200/authentication/callback',
|
|
35
|
-
scope: 'openid profile email api offline_access',
|
|
36
|
-
authority: 'http://api',
|
|
37
|
-
refresh_time_before_tokens_expiration_in_second: 70,
|
|
38
|
-
};
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
const {debug, getByText, rerender} = render(<App configuration={configuration}/>);
|
|
41
|
-
await waitFor(() => getByText('React Demo Application protected by OpenId Connect'));
|
|
42
|
-
fireEvent.click(screen.getByText('Login'));
|
|
43
|
-
await waitFor(() => getByText('Authentification en cours'));
|
|
44
|
-
|
|
45
|
-
})
|
|
46
|
-
*/
|
package/src/App.tsx
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import React, {useReducer} from 'react';
|
|
2
|
-
import {BrowserRouter, Route, Link, Routes} from 'react-router-dom';
|
|
3
|
-
import { Home } from "./Home";
|
|
4
|
-
import { Profile, SecureProfile } from "./Profile";
|
|
5
|
-
import { configurationAuth0, configurationIdentityServer, configurationIdentityServerWithoutDiscovery } from './configurations';
|
|
6
|
-
import { withOidcSecure, OidcProvider } from "./oidc";
|
|
7
|
-
import {FetchUserHoc, FetchUserHook} from "./FetchUser";
|
|
8
|
-
import { MultiAuthContainer } from "./MultiAuth";
|
|
9
|
-
|
|
10
|
-
const OidcSecureHoc = withOidcSecure(Profile);
|
|
11
|
-
|
|
12
|
-
function reducer(state, action) {
|
|
13
|
-
switch (action.type) {
|
|
14
|
-
case 'event':
|
|
15
|
-
return [{...action.data, date:Date.now()}, ...state]
|
|
16
|
-
default:
|
|
17
|
-
throw new Error();
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function App() {
|
|
22
|
-
const [show, setShow] = React.useState(false);
|
|
23
|
-
const [events, dispatch] = useReducer(reducer, []);
|
|
24
|
-
|
|
25
|
-
const onEvent=(configurationName, eventName, data )=>{
|
|
26
|
-
// console.log(`oidc:${configurationName}:${eventName}`, data);
|
|
27
|
-
dispatch({type: 'event', data: {name: `oidc:${configurationName}:${eventName}`, data}})
|
|
28
|
-
}
|
|
29
|
-
return (<>
|
|
30
|
-
|
|
31
|
-
<OidcProvider configuration={configurationIdentityServer} onEvent={onEvent}>
|
|
32
|
-
<BrowserRouter>
|
|
33
|
-
<nav className="navbar navbar-expand-lg navbar-dark bg-primary">
|
|
34
|
-
<a className="navbar-brand" href="/">@axa-fr/react-oidc</a>
|
|
35
|
-
<button className="navbar-toggler" type="button" onClick={() => setShow(!show)} data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
36
|
-
<span className="navbar-toggler-icon"/>
|
|
37
|
-
</button>
|
|
38
|
-
<div style={show ? { display: "block" } : { display: 'none' }} className="collapse navbar-collapse" id="navbarNav">
|
|
39
|
-
<ul className="navbar-nav">
|
|
40
|
-
<li className="nav-item">
|
|
41
|
-
<Link className="nav-link" to="/">Home</Link>
|
|
42
|
-
</li>
|
|
43
|
-
<li className="nav-item">
|
|
44
|
-
<Link className="nav-link" to="/profile">Profile</Link>
|
|
45
|
-
</li>
|
|
46
|
-
<li className="nav-item">
|
|
47
|
-
<Link className="nav-link" to="/profile-secure-component">Secure Profile Component</Link>
|
|
48
|
-
</li>
|
|
49
|
-
<li className="nav-item">
|
|
50
|
-
<Link className="nav-link" to="/profile-secure-hoc">Secure Profile Hoc</Link>
|
|
51
|
-
</li>
|
|
52
|
-
<li className="nav-item">
|
|
53
|
-
<Link className="nav-link" to="/user-fetch-secure-hoc">Secure User Fetch Hoc</Link>
|
|
54
|
-
</li>
|
|
55
|
-
<li className="nav-item">
|
|
56
|
-
<Link className="nav-link" to="/user-fetch-secure-hook">Secure User Fetch Hook</Link>
|
|
57
|
-
</li>
|
|
58
|
-
<li className="nav-item">
|
|
59
|
-
<Link className="nav-link" to="/multi-auth">Multi Auth</Link>
|
|
60
|
-
</li>
|
|
61
|
-
</ul>
|
|
62
|
-
</div>
|
|
63
|
-
</nav>
|
|
64
|
-
|
|
65
|
-
<div>
|
|
66
|
-
<Routes>
|
|
67
|
-
<Route path="/" element={<Home></Home>} />
|
|
68
|
-
<Route path="/profile" element={<Profile></Profile>} />
|
|
69
|
-
<Route path="/profile-secure-component" element={<SecureProfile></SecureProfile>} />
|
|
70
|
-
<Route path="/profile-secure-hoc" element={<OidcSecureHoc></OidcSecureHoc>} />
|
|
71
|
-
<Route path="/user-fetch-secure-hoc" element={<FetchUserHoc></FetchUserHoc>} />
|
|
72
|
-
<Route path="/user-fetch-secure-hook" element={<FetchUserHook></FetchUserHook>} />
|
|
73
|
-
<Route path="/multi-auth/*" element={<MultiAuthContainer></MultiAuthContainer>} />
|
|
74
|
-
</Routes>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
</BrowserRouter>
|
|
78
|
-
</OidcProvider>
|
|
79
|
-
<div className="container-fluid mt-3">
|
|
80
|
-
<div className="card">
|
|
81
|
-
<div className="card-body" >
|
|
82
|
-
<h5 className="card-title">Default configuration Events</h5>
|
|
83
|
-
<div style={{"overflowX": "hidden", "overflowY": "scroll", "maxHeight": "400px"}}>
|
|
84
|
-
{events.map(e => {
|
|
85
|
-
const date = new Date(e.date);
|
|
86
|
-
const dateFormated = `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
|
|
87
|
-
return <p>{dateFormated} {e.name}: { JSON.stringify(e.data)}</p>
|
|
88
|
-
})}
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</div></>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export default App;
|
package/src/FetchUser.tsx
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import React, {useEffect, useState} from 'react';
|
|
2
|
-
|
|
3
|
-
import {useOidcFetch, withOidcFetch} from "./oidc/FetchToken";
|
|
4
|
-
import {OidcSecure} from "./oidc";
|
|
5
|
-
|
|
6
|
-
const DisplayUserInfo = ({ fetch }) => {
|
|
7
|
-
const [oidcUser, setOidcUser] = useState(null);
|
|
8
|
-
const [isLoading, setLoading] = useState(true);
|
|
9
|
-
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
const fetchUserInfoAsync = async () => {
|
|
12
|
-
const res = await fetch("https://demo.duendesoftware.com/connect/userinfo");
|
|
13
|
-
if (res.status != 200) {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
return res.json();
|
|
17
|
-
};
|
|
18
|
-
let isMounted = true;
|
|
19
|
-
fetchUserInfoAsync().then((userInfo) => {
|
|
20
|
-
if(isMounted) {
|
|
21
|
-
setLoading(false);
|
|
22
|
-
setOidcUser(userInfo)
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
return () => {
|
|
26
|
-
isMounted = false;
|
|
27
|
-
};
|
|
28
|
-
},[]);
|
|
29
|
-
|
|
30
|
-
if(isLoading){
|
|
31
|
-
return <>Loading</>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<div className="container mt-3">
|
|
36
|
-
<div className="card text-white bg-success mb-3">
|
|
37
|
-
<div className="card-body">
|
|
38
|
-
<h5 className="card-title">User information</h5>
|
|
39
|
-
{oidcUser != null && <p className="card-text">{JSON.stringify(oidcUser)}</p>}
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
)
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const UserInfoWithFetchHoc = withOidcFetch(fetch)(DisplayUserInfo);
|
|
47
|
-
|
|
48
|
-
export const FetchUserHoc= () => <OidcSecure><UserInfoWithFetchHoc/></OidcSecure>;
|
|
49
|
-
|
|
50
|
-
export const FetchUserHook= () => {
|
|
51
|
-
const {fetch} = useOidcFetch();
|
|
52
|
-
return <OidcSecure><DisplayUserInfo fetch={fetch} /></OidcSecure>
|
|
53
|
-
}
|