@axa-fr/react-oidc 6.12.0 → 6.13.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/bin/copy.js +12 -9
- package/dist/OidcProvider.d.ts +1 -1
- package/dist/OidcProvider.d.ts.map +1 -1
- package/dist/OidcSecure.d.ts +1 -1
- package/dist/OidcSecure.d.ts.map +1 -1
- package/dist/ReactOidc.d.ts +1 -1
- package/dist/ReactOidc.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/vanilla/checkSession.d.ts +5 -0
- package/dist/vanilla/checkSession.d.ts.map +1 -0
- package/dist/vanilla/checkSession.js +68 -0
- package/dist/vanilla/checkSession.js.map +1 -0
- package/dist/vanilla/events.d.ts +29 -0
- package/dist/vanilla/events.d.ts.map +1 -0
- package/dist/vanilla/events.js +32 -0
- package/dist/vanilla/events.js.map +1 -0
- package/dist/vanilla/initSession.d.ts +3 -3
- package/dist/vanilla/initSession.d.ts.map +1 -1
- package/dist/vanilla/initSession.js +19 -23
- package/dist/vanilla/initSession.js.map +1 -1
- package/dist/vanilla/initWorker.d.ts +4 -4
- package/dist/vanilla/initWorker.d.ts.map +1 -1
- package/dist/vanilla/initWorker.js +11 -15
- package/dist/vanilla/initWorker.js.map +1 -1
- package/dist/vanilla/login.d.ts +4 -0
- package/dist/vanilla/login.d.ts.map +1 -0
- package/dist/vanilla/login.js +244 -0
- package/dist/vanilla/login.js.map +1 -0
- package/dist/vanilla/oidc.d.ts +4 -37
- package/dist/vanilla/oidc.d.ts.map +1 -1
- package/dist/vanilla/oidc.js +99 -519
- package/dist/vanilla/oidc.js.map +1 -1
- package/dist/vanilla/renewTokens.d.ts +4 -0
- package/dist/vanilla/renewTokens.d.ts.map +1 -0
- package/dist/vanilla/renewTokens.js +50 -0
- package/dist/vanilla/renewTokens.js.map +1 -0
- package/dist/vanilla/requests.d.ts +2 -0
- package/dist/vanilla/requests.d.ts.map +1 -1
- package/dist/vanilla/requests.js +20 -1
- package/dist/vanilla/requests.js.map +1 -1
- package/dist/vanilla/route-utils.js +1 -1
- package/dist/vanilla/route-utils.js.map +1 -1
- package/dist/vanilla/silentLogin.d.ts +9 -0
- package/dist/vanilla/silentLogin.d.ts.map +1 -0
- package/dist/vanilla/silentLogin.js +145 -0
- package/dist/vanilla/silentLogin.js.map +1 -0
- package/dist/vanilla/types.d.ts +33 -0
- package/dist/vanilla/types.d.ts.map +1 -0
- package/dist/vanilla/types.js +3 -0
- package/dist/vanilla/types.js.map +1 -0
- package/dist/vanilla/user.d.ts +2 -0
- package/dist/vanilla/user.d.ts.map +1 -0
- package/dist/vanilla/user.js +48 -0
- package/dist/vanilla/user.js.map +1 -0
- package/dist/vanilla/vanillaOidc.d.ts +2 -1
- package/dist/vanilla/vanillaOidc.d.ts.map +1 -1
- package/dist/vanilla/vanillaOidc.js.map +1 -1
- package/package.json +1 -1
- package/src/oidc/OidcProvider.tsx +1 -1
- package/src/oidc/OidcSecure.tsx +1 -1
- package/src/oidc/ReactOidc.tsx +1 -1
- package/src/oidc/index.ts +1 -1
- package/src/oidc/vanilla/checkSession.ts +55 -0
- package/src/oidc/vanilla/events.ts +29 -0
- package/src/oidc/vanilla/index.ts +1 -1
- package/src/oidc/vanilla/initSession.ts +19 -25
- package/src/oidc/vanilla/initWorker.ts +12 -18
- package/src/oidc/vanilla/login.ts +242 -0
- package/src/oidc/vanilla/oidc.ts +53 -554
- package/src/oidc/vanilla/renewTokens.ts +36 -0
- package/src/oidc/vanilla/requests.ts +24 -0
- package/src/oidc/vanilla/route-utils.ts +1 -1
- package/src/oidc/vanilla/silentLogin.ts +143 -0
- package/src/oidc/vanilla/types.ts +35 -0
- package/src/oidc/vanilla/user.ts +39 -0
- package/src/oidc/vanilla/vanillaOidc.ts +2 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { initSession } from './initSession';
|
|
2
|
+
import { initWorkerAsync } from './initWorker';
|
|
3
|
+
import Oidc from './oidc';
|
|
4
|
+
import { computeTimeLeft } from './parseTokens';
|
|
5
|
+
import timer from './timer';
|
|
6
|
+
import { StringMap } from './types';
|
|
7
|
+
|
|
8
|
+
export async function renewTokensAndStartTimerAsync(oidc, refreshToken, forceRefresh = false, extras:StringMap = null) {
|
|
9
|
+
const updateTokens = (tokens) => { oidc.tokens = tokens; };
|
|
10
|
+
const { tokens, status } = await oidc.synchroniseTokensAsync(refreshToken, 0, forceRefresh, extras, updateTokens);
|
|
11
|
+
|
|
12
|
+
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName);
|
|
13
|
+
if (!serviceWorker) {
|
|
14
|
+
const session = initSession(oidc.configurationName, oidc.configuration.storage);
|
|
15
|
+
await session.setTokens(oidc.tokens);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!oidc.tokens) {
|
|
19
|
+
await oidc.destroyAsync(status);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (oidc.timeoutId) {
|
|
24
|
+
oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt, extras);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const autoRenewTokens = (oidc, refreshToken, expiresAt, extras:StringMap = null) => {
|
|
29
|
+
const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second;
|
|
30
|
+
return timer.setTimeout(async () => {
|
|
31
|
+
const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
|
|
32
|
+
const timeInfo = { timeLeft };
|
|
33
|
+
oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
|
|
34
|
+
await renewTokensAndStartTimerAsync(oidc, refreshToken, false, extras);
|
|
35
|
+
}, 1000);
|
|
36
|
+
};
|
|
@@ -1,5 +1,29 @@
|
|
|
1
|
+
import { getFromCache, setCache } from './cache';
|
|
2
|
+
import { OidcAuthorizationServiceConfiguration } from './oidc';
|
|
1
3
|
import { parseOriginalTokens } from './parseTokens';
|
|
2
4
|
|
|
5
|
+
const oneHourSecond = 60 * 60;
|
|
6
|
+
export const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage = window.sessionStorage):
|
|
7
|
+
Promise<OidcAuthorizationServiceConfiguration> => {
|
|
8
|
+
const fullUrl = `${openIdIssuerUrl}/.well-known/openid-configuration`;
|
|
9
|
+
|
|
10
|
+
const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
|
|
11
|
+
const data = getFromCache(localStorageKey, storage, timeCacheSecond);
|
|
12
|
+
if (data) {
|
|
13
|
+
return new OidcAuthorizationServiceConfiguration(data);
|
|
14
|
+
}
|
|
15
|
+
const response = await fetch(fullUrl);
|
|
16
|
+
|
|
17
|
+
if (response.status !== 200) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = await response.json();
|
|
22
|
+
|
|
23
|
+
setCache(localStorageKey, result, storage);
|
|
24
|
+
return new OidcAuthorizationServiceConfiguration(result);
|
|
25
|
+
};
|
|
26
|
+
|
|
3
27
|
const internalFetch = async (url, headers, numberRetry = 0, timeoutMs = 10000) => {
|
|
4
28
|
let response;
|
|
5
29
|
try {
|
|
@@ -72,7 +72,7 @@ const parseQueryString = (queryString:string) => {
|
|
|
72
72
|
// Convert the array of strings into an object
|
|
73
73
|
for (i = 0, l = queries.length; i < l; i++) {
|
|
74
74
|
temp = queries[i].split('=');
|
|
75
|
-
params[temp[0]] = temp[1];
|
|
75
|
+
params[decodeURIComponent(temp[0])] = temp[1];
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
return params;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { eventNames } from './events';
|
|
2
|
+
import { Tokens } from './parseTokens';
|
|
3
|
+
import { autoRenewTokens } from './renewTokens';
|
|
4
|
+
import timer from './timer';
|
|
5
|
+
import { OidcConfiguration, StringMap } from './types';
|
|
6
|
+
type SilentLoginResponse = {
|
|
7
|
+
tokens:Tokens;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
11
|
+
export const _silentLoginAsync = (configurationName:string, configuration:OidcConfiguration, publishEvent:Function) => (extras:StringMap = null, state:string = null, scope:string = null):Promise<SilentLoginResponse> => {
|
|
12
|
+
if (!configuration.silent_redirect_uri || !configuration.silent_login_uri) {
|
|
13
|
+
return Promise.resolve(null);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
publishEvent(eventNames.silentLoginAsync_begin, {});
|
|
18
|
+
let queries = '';
|
|
19
|
+
|
|
20
|
+
if (state) {
|
|
21
|
+
if (extras == null) {
|
|
22
|
+
extras = {};
|
|
23
|
+
}
|
|
24
|
+
extras.state = state;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (scope) {
|
|
28
|
+
if (extras == null) {
|
|
29
|
+
extras = {};
|
|
30
|
+
}
|
|
31
|
+
extras.scope = scope;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (extras != null) {
|
|
35
|
+
for (const [key, value] of Object.entries(extras)) {
|
|
36
|
+
if (queries === '') {
|
|
37
|
+
queries = `?${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
38
|
+
} else {
|
|
39
|
+
queries += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const link = configuration.silent_login_uri + queries;
|
|
44
|
+
const idx = link.indexOf('/', link.indexOf('//') + 2);
|
|
45
|
+
const iFrameOrigin = link.substr(0, idx);
|
|
46
|
+
const iframe = document.createElement('iframe');
|
|
47
|
+
iframe.width = '0px';
|
|
48
|
+
iframe.height = '0px';
|
|
49
|
+
|
|
50
|
+
iframe.id = `${configurationName}_oidc_iframe`;
|
|
51
|
+
iframe.setAttribute('src', link);
|
|
52
|
+
document.body.appendChild(iframe);
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
try {
|
|
55
|
+
let isResolved = false;
|
|
56
|
+
window.onmessage = (e: MessageEvent<any>) => {
|
|
57
|
+
if (e.origin === iFrameOrigin &&
|
|
58
|
+
e.source === iframe.contentWindow
|
|
59
|
+
) {
|
|
60
|
+
const key = `${configurationName}_oidc_tokens:`;
|
|
61
|
+
const key_error = `${configurationName}_oidc_error:`;
|
|
62
|
+
const data = e.data;
|
|
63
|
+
if (data && typeof (data) === 'string') {
|
|
64
|
+
if (!isResolved) {
|
|
65
|
+
if (data.startsWith(key)) {
|
|
66
|
+
const result = JSON.parse(e.data.replace(key, ''));
|
|
67
|
+
publishEvent(eventNames.silentLoginAsync_end, {});
|
|
68
|
+
iframe.remove();
|
|
69
|
+
isResolved = true;
|
|
70
|
+
resolve(result);
|
|
71
|
+
} else if (data.startsWith(key_error)) {
|
|
72
|
+
const result = JSON.parse(e.data.replace(key_error, ''));
|
|
73
|
+
publishEvent(eventNames.silentLoginAsync_error, result);
|
|
74
|
+
iframe.remove();
|
|
75
|
+
isResolved = true;
|
|
76
|
+
reject(new Error('oidc_' + result.error));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const silentSigninTimeout = configuration.silent_login_timeout;
|
|
83
|
+
setTimeout(() => {
|
|
84
|
+
if (!isResolved) {
|
|
85
|
+
publishEvent(eventNames.silentLoginAsync_error, { reason: 'timeout' });
|
|
86
|
+
iframe.remove();
|
|
87
|
+
isResolved = true;
|
|
88
|
+
reject(new Error('timeout'));
|
|
89
|
+
}
|
|
90
|
+
}, silentSigninTimeout);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
iframe.remove();
|
|
93
|
+
publishEvent(eventNames.silentLoginAsync_error, e);
|
|
94
|
+
reject(e);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch (e) {
|
|
98
|
+
publishEvent(eventNames.silentLoginAsync_error, e);
|
|
99
|
+
throw e;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
104
|
+
export const defaultSilentLoginAsync = (window, configurationName, configuration:OidcConfiguration, publishEvent :(string, any)=>void, oidc:any) => (extras:StringMap = null, scope:string = undefined) => {
|
|
105
|
+
extras = { ...extras };
|
|
106
|
+
|
|
107
|
+
const silentLoginAsync = (extras, state, scope) => {
|
|
108
|
+
return _silentLoginAsync(configurationName, configuration, publishEvent.bind(oidc))(extras, state, scope);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const loginLocalAsync = async () => {
|
|
112
|
+
if (oidc.timeoutId) {
|
|
113
|
+
timer.clearTimeout(oidc.timeoutId);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let state;
|
|
117
|
+
if (extras && 'state' in extras) {
|
|
118
|
+
state = extras.state;
|
|
119
|
+
delete extras.state;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const extraFinal = extras ?? configuration.extras ?? {};
|
|
124
|
+
const silentResult = await silentLoginAsync({
|
|
125
|
+
...extraFinal,
|
|
126
|
+
prompt: 'none',
|
|
127
|
+
}, state, scope);
|
|
128
|
+
|
|
129
|
+
if (silentResult) {
|
|
130
|
+
oidc.tokens = silentResult.tokens;
|
|
131
|
+
publishEvent(eventNames.token_aquired, {});
|
|
132
|
+
// @ts-ignore
|
|
133
|
+
oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.refreshToken, oidc.tokens.expiresAt, extras);
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
} catch (e) {
|
|
137
|
+
return e;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
return loginLocalAsync();
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export default defaultSilentLoginAsync;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
export type OidcConfiguration = {
|
|
3
|
+
client_id: string;
|
|
4
|
+
redirect_uri: string;
|
|
5
|
+
silent_redirect_uri?:string;
|
|
6
|
+
silent_login_uri?:string;
|
|
7
|
+
silent_login_timeout?:number;
|
|
8
|
+
scope: string;
|
|
9
|
+
authority: string;
|
|
10
|
+
authority_time_cache_wellknowurl_in_second?: number;
|
|
11
|
+
authority_configuration?: AuthorityConfiguration;
|
|
12
|
+
refresh_time_before_tokens_expiration_in_second?: number;
|
|
13
|
+
token_request_timeout?: number;
|
|
14
|
+
service_worker_relative_url?:string;
|
|
15
|
+
service_worker_only?:boolean;
|
|
16
|
+
extras?:StringMap;
|
|
17
|
+
token_request_extras?:StringMap;
|
|
18
|
+
storage?: Storage;
|
|
19
|
+
monitor_session?: boolean;
|
|
20
|
+
token_renew_mode?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export interface StringMap {
|
|
24
|
+
[key: string]: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AuthorityConfiguration {
|
|
28
|
+
authorization_endpoint: string;
|
|
29
|
+
token_endpoint: string;
|
|
30
|
+
revocation_endpoint: string;
|
|
31
|
+
end_session_endpoint?: string;
|
|
32
|
+
userinfo_endpoint?: string;
|
|
33
|
+
check_session_iframe?:string;
|
|
34
|
+
issuer:string;
|
|
35
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { sleepAsync } from './initWorker';
|
|
2
|
+
import { isTokensValid } from './parseTokens';
|
|
3
|
+
|
|
4
|
+
export const userInfoAsync = async (oidc) => {
|
|
5
|
+
if (oidc.userInfo != null) {
|
|
6
|
+
return oidc.userInfo;
|
|
7
|
+
}
|
|
8
|
+
if (!oidc.tokens) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const accessToken = oidc.tokens.accessToken;
|
|
12
|
+
if (!accessToken) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// We wait the synchronisation before making a request
|
|
17
|
+
while (oidc.tokens && !isTokensValid(oidc.tokens)) {
|
|
18
|
+
await sleepAsync(200);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
|
|
22
|
+
const url = oidcServerConfiguration.userInfoEndpoint;
|
|
23
|
+
const fetchUserInfo = async (accessToken) => {
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
headers: {
|
|
26
|
+
authorization: `Bearer ${accessToken}`,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (res.status !== 200) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return res.json();
|
|
35
|
+
};
|
|
36
|
+
const userInfo = await fetchUserInfo(accessToken);
|
|
37
|
+
oidc.userInfo = userInfo;
|
|
38
|
+
return userInfo;
|
|
39
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { LoginCallback, Oidc
|
|
1
|
+
import { LoginCallback, Oidc } from './oidc';
|
|
2
2
|
import { getValidTokenAsync, Tokens, ValidToken } from './parseTokens';
|
|
3
|
+
import { OidcConfiguration, StringMap } from './types';
|
|
3
4
|
|
|
4
5
|
export interface EventSubscriber {
|
|
5
6
|
(name: string, data:any);
|