@axa-fr/react-oidc 6.11.4-alpha0 → 6.11.4-alpha2
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/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/initWorker.d.ts +1 -1
- package/dist/vanilla/initWorker.d.ts.map +1 -1
- package/dist/vanilla/initWorker.js +2 -2
- 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 +125 -0
- package/dist/vanilla/login.js.map +1 -0
- package/dist/vanilla/oidc.d.ts +7 -36
- package/dist/vanilla/oidc.d.ts.map +1 -1
- package/dist/vanilla/oidc.js +53 -349
- package/dist/vanilla/oidc.js.map +1 -1
- 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/silentLogin.d.ts +8 -0
- package/dist/vanilla/silentLogin.d.ts.map +1 -0
- package/dist/vanilla/silentLogin.js +95 -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/initWorker.ts +3 -3
- package/src/oidc/vanilla/login.ts +118 -0
- package/src/oidc/vanilla/oidc.ts +23 -372
- package/src/oidc/vanilla/requests.ts +24 -0
- package/src/oidc/vanilla/silentLogin.ts +102 -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,29 @@
|
|
|
1
|
+
|
|
2
|
+
export const eventNames = {
|
|
3
|
+
service_worker_not_supported_by_browser: 'service_worker_not_supported_by_browser',
|
|
4
|
+
token_aquired: 'token_aquired',
|
|
5
|
+
logout_from_another_tab: 'logout_from_another_tab',
|
|
6
|
+
logout_from_same_tab: 'logout_from_same_tab',
|
|
7
|
+
token_renewed: 'token_renewed',
|
|
8
|
+
token_timer: 'token_timer',
|
|
9
|
+
loginAsync_begin: 'loginAsync_begin',
|
|
10
|
+
loginAsync_error: 'loginAsync_error',
|
|
11
|
+
loginCallbackAsync_begin: 'loginCallbackAsync_begin',
|
|
12
|
+
loginCallbackAsync_end: 'loginCallbackAsync_end',
|
|
13
|
+
loginCallbackAsync_error: 'loginCallbackAsync_error',
|
|
14
|
+
refreshTokensAsync_begin: 'refreshTokensAsync_begin',
|
|
15
|
+
refreshTokensAsync: 'refreshTokensAsync',
|
|
16
|
+
refreshTokensAsync_end: 'refreshTokensAsync_end',
|
|
17
|
+
refreshTokensAsync_error: 'refreshTokensAsync_error',
|
|
18
|
+
refreshTokensAsync_silent_error: 'refreshTokensAsync_silent_error',
|
|
19
|
+
tryKeepExistingSessionAsync_begin: 'tryKeepExistingSessionAsync_begin',
|
|
20
|
+
tryKeepExistingSessionAsync_end: 'tryKeepExistingSessionAsync_end',
|
|
21
|
+
tryKeepExistingSessionAsync_error: 'tryKeepExistingSessionAsync_error',
|
|
22
|
+
silentLoginAsync_begin: 'silentLoginAsync_begin',
|
|
23
|
+
silentLoginAsync: 'silentLoginAsync',
|
|
24
|
+
silentLoginAsync_end: 'silentLoginAsync_end',
|
|
25
|
+
silentLoginAsync_error: 'silentLoginAsync_error',
|
|
26
|
+
syncTokensAsync_begin: 'syncTokensAsync_begin',
|
|
27
|
+
syncTokensAsync_end: 'syncTokensAsync_end',
|
|
28
|
+
syncTokensAsync_error: 'syncTokensAsync_error',
|
|
29
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { OidcConfiguration } from './
|
|
1
|
+
export { AuthorityConfiguration, OidcConfiguration, StringMap } from './types';
|
|
2
2
|
export { VanillaOidc } from './vanillaOidc';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { initSession } from './initSession';
|
|
2
|
-
import { OidcConfiguration } from './oidc';
|
|
3
2
|
import { parseOriginalTokens } from './parseTokens';
|
|
4
3
|
import timer from './timer';
|
|
4
|
+
import { OidcConfiguration } from './types';
|
|
5
5
|
|
|
6
6
|
export const getOperatingSystem = () => {
|
|
7
7
|
const nVer = navigator.appVersion;
|
|
@@ -268,12 +268,12 @@ export const initWorkerAsync = async(serviceWorkerRelativeUrl, configurationName
|
|
|
268
268
|
const setLoginParams = (configurationName:string, data) => {
|
|
269
269
|
const sessionKey = getLoginSessionKey(configurationName);
|
|
270
270
|
getLoginParamsCache = data;
|
|
271
|
-
|
|
271
|
+
localStorage[sessionKey] = JSON.stringify(data);
|
|
272
272
|
};
|
|
273
273
|
|
|
274
274
|
let getLoginParamsCache = null;
|
|
275
275
|
const getLoginParams = (configurationName) => {
|
|
276
|
-
const dataString =
|
|
276
|
+
const dataString = localStorage[getLoginSessionKey(configurationName)];
|
|
277
277
|
if (!getLoginParamsCache) {
|
|
278
278
|
getLoginParamsCache = JSON.parse(dataString);
|
|
279
279
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { AuthorizationRequest, DefaultCrypto, RedirectRequestHandler } from '@openid/appauth';
|
|
2
|
+
|
|
3
|
+
import { eventNames } from './events';
|
|
4
|
+
import { initSession } from './initSession';
|
|
5
|
+
import { initWorkerAsync } from './initWorker';
|
|
6
|
+
import { MemoryStorageBackend } from './memoryStorageBackend';
|
|
7
|
+
import { HashQueryStringUtils, NoHashQueryStringUtils } from './noHashQueryStringUtils';
|
|
8
|
+
import { OidcConfiguration, StringMap } from './types';
|
|
9
|
+
|
|
10
|
+
const randomString = function(length) {
|
|
11
|
+
let text = '';
|
|
12
|
+
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
13
|
+
for (let i = 0; i < length; i++) {
|
|
14
|
+
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
15
|
+
}
|
|
16
|
+
return text;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
20
|
+
export const defaultLoginAsync = (window, configurationName, configuration:OidcConfiguration, silentLoginAsync:Function, publishEvent :(string, any)=>void, initAsync:Function) => (callbackPath:string = undefined, extras:StringMap = null, isSilentSignin = false, scope:string = undefined) => {
|
|
21
|
+
const originExtras = extras;
|
|
22
|
+
extras = { ...extras };
|
|
23
|
+
const loginLocalAsync = async () => {
|
|
24
|
+
const location = window.location;
|
|
25
|
+
const url = callbackPath || location.pathname + (location.search || '') + (location.hash || '');
|
|
26
|
+
let state;
|
|
27
|
+
if (extras && 'state' in extras) {
|
|
28
|
+
state = extras.state;
|
|
29
|
+
delete extras.state;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
publishEvent(eventNames.loginAsync_begin, {});
|
|
33
|
+
if (extras) {
|
|
34
|
+
for (const key of Object.keys(extras)) {
|
|
35
|
+
if (key.endsWith(':token_request')) {
|
|
36
|
+
delete extras[key];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const redirectUri = isSilentSignin ? configuration.silent_redirect_uri : configuration.redirect_uri;
|
|
42
|
+
if (!scope) {
|
|
43
|
+
scope = configuration.scope;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const extraFinal = extras ?? configuration.extras ?? {};
|
|
47
|
+
if (!extraFinal.nonce) {
|
|
48
|
+
extraFinal.nonce = randomString(12);
|
|
49
|
+
}
|
|
50
|
+
const nonce = { nonce: extraFinal.nonce };
|
|
51
|
+
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
|
|
52
|
+
const oidcServerConfiguration = await initAsync(configuration.authority, configuration.authority_configuration);
|
|
53
|
+
let storage;
|
|
54
|
+
if (serviceWorker) {
|
|
55
|
+
serviceWorker.setLoginParams(configurationName, { callbackPath: url, extras: originExtras, state });
|
|
56
|
+
serviceWorker.startKeepAliveServiceWorker();
|
|
57
|
+
await serviceWorker.initAsync(oidcServerConfiguration, 'loginAsync', configuration);
|
|
58
|
+
await serviceWorker.setNonceAsync(nonce);
|
|
59
|
+
storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, {});
|
|
60
|
+
await storage.setItem('dummy', {});
|
|
61
|
+
} else {
|
|
62
|
+
let session = initSession(configurationName, configuration.storage ?? sessionStorage);
|
|
63
|
+
session.setLoginParams(configurationName, { callbackPath: url, extras: originExtras, state });
|
|
64
|
+
session = initSession(configurationName);
|
|
65
|
+
await session.setNonceAsync(nonce);
|
|
66
|
+
storage = new MemoryStorageBackend(session.saveItemsAsync, {});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
const queryStringUtil = redirectUri.includes('#') ? new HashQueryStringUtils() : new NoHashQueryStringUtils();
|
|
71
|
+
const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
|
|
72
|
+
const authRequest = new AuthorizationRequest({
|
|
73
|
+
client_id: configuration.client_id,
|
|
74
|
+
redirect_uri: redirectUri,
|
|
75
|
+
scope,
|
|
76
|
+
response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
|
|
77
|
+
state,
|
|
78
|
+
extras: extraFinal,
|
|
79
|
+
});
|
|
80
|
+
authorizationHandler.performAuthorizationRequest(oidcServerConfiguration, authRequest);
|
|
81
|
+
} catch (exception) {
|
|
82
|
+
publishEvent(eventNames.loginAsync_error, exception);
|
|
83
|
+
throw exception;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
return loginLocalAsync();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
90
|
+
export const defaultSilentLoginAsync2 = (window, configurationName, configuration:OidcConfiguration, publishEvent :(string, any)=>void, oidc:any) => (extras:StringMap = null, scope:string = undefined) => {
|
|
91
|
+
extras = { ...extras };
|
|
92
|
+
const loginLocalAsync = async () => {
|
|
93
|
+
let state;
|
|
94
|
+
if (extras && 'state' in extras) {
|
|
95
|
+
state = extras.state;
|
|
96
|
+
delete extras.state;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const extraFinal = extras ?? configuration.extras ?? {};
|
|
101
|
+
const silentResult = await oidc.silentLoginAsync({
|
|
102
|
+
...extraFinal,
|
|
103
|
+
prompt: 'none',
|
|
104
|
+
}, state, scope);
|
|
105
|
+
|
|
106
|
+
if (silentResult) {
|
|
107
|
+
oidc.tokens = silentResult.tokens;
|
|
108
|
+
publishEvent(eventNames.token_aquired, {});
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt, extras);
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
} catch (e) {
|
|
114
|
+
return e;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
return loginLocalAsync();
|
|
118
|
+
};
|
package/src/oidc/vanilla/oidc.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthorizationNotifier,
|
|
3
|
-
AuthorizationRequest,
|
|
4
3
|
AuthorizationServiceConfiguration,
|
|
5
4
|
BaseTokenRequestHandler,
|
|
6
5
|
DefaultCrypto,
|
|
@@ -12,31 +11,26 @@ import {
|
|
|
12
11
|
} from '@openid/appauth';
|
|
13
12
|
import { AuthorizationServiceConfigurationJson } from '@openid/appauth/src/authorization_service_configuration';
|
|
14
13
|
|
|
15
|
-
import {
|
|
14
|
+
import { startCheckSessionAsync as defaultStartCheckSessionAsync } from './checkSession';
|
|
16
15
|
import { CheckSessionIFrame } from './checkSessionIFrame';
|
|
16
|
+
import { eventNames } from './events';
|
|
17
17
|
import { initSession } from './initSession';
|
|
18
18
|
import { initWorkerAsync, sleepAsync } from './initWorker';
|
|
19
|
+
import { defaultLoginAsync, defaultSilentLoginAsync2 } from './login';
|
|
19
20
|
import { MemoryStorageBackend } from './memoryStorageBackend';
|
|
20
21
|
import { HashQueryStringUtils, NoHashQueryStringUtils } from './noHashQueryStringUtils';
|
|
21
22
|
import {
|
|
22
23
|
computeTimeLeft,
|
|
23
24
|
isTokensOidcValid,
|
|
24
|
-
isTokensValid,
|
|
25
25
|
setTokens, TokenRenewMode,
|
|
26
26
|
Tokens,
|
|
27
27
|
} from './parseTokens';
|
|
28
|
-
import { performRevocationRequestAsync, performTokenRequestAsync, TOKEN_TYPE } from './requests';
|
|
28
|
+
import { fetchFromIssuer, performRevocationRequestAsync, performTokenRequestAsync, TOKEN_TYPE } from './requests';
|
|
29
29
|
import { getParseQueryStringFromLocation } from './route-utils';
|
|
30
|
+
import defaultSilentLoginAsync from './silentLogin';
|
|
30
31
|
import timer from './timer';
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
let text = '';
|
|
34
|
-
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
35
|
-
for (let i = 0; i < length; i++) {
|
|
36
|
-
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
37
|
-
}
|
|
38
|
-
return text;
|
|
39
|
-
};
|
|
32
|
+
import { AuthorityConfiguration, OidcConfiguration, StringMap } from './types';
|
|
33
|
+
import { userInfoAsync } from './user';
|
|
40
34
|
|
|
41
35
|
export interface OidcAuthorizationServiceConfigurationJson extends AuthorizationServiceConfigurationJson{
|
|
42
36
|
check_session_iframe?: string;
|
|
@@ -58,41 +52,6 @@ export class OidcAuthorizationServiceConfiguration extends AuthorizationServiceC
|
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
export interface StringMap {
|
|
62
|
-
[key: string]: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface AuthorityConfiguration {
|
|
66
|
-
authorization_endpoint: string;
|
|
67
|
-
token_endpoint: string;
|
|
68
|
-
revocation_endpoint: string;
|
|
69
|
-
end_session_endpoint?: string;
|
|
70
|
-
userinfo_endpoint?: string;
|
|
71
|
-
check_session_iframe?:string;
|
|
72
|
-
issuer:string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export type OidcConfiguration = {
|
|
76
|
-
client_id: string;
|
|
77
|
-
redirect_uri: string;
|
|
78
|
-
silent_redirect_uri?:string;
|
|
79
|
-
silent_login_uri?:string;
|
|
80
|
-
silent_login_timeout?:number;
|
|
81
|
-
scope: string;
|
|
82
|
-
authority: string;
|
|
83
|
-
authority_time_cache_wellknowurl_in_second?: number;
|
|
84
|
-
authority_configuration?: AuthorityConfiguration;
|
|
85
|
-
refresh_time_before_tokens_expiration_in_second?: number;
|
|
86
|
-
token_request_timeout?: number;
|
|
87
|
-
service_worker_relative_url?:string;
|
|
88
|
-
service_worker_only?:boolean;
|
|
89
|
-
extras?:StringMap;
|
|
90
|
-
token_request_extras?:StringMap;
|
|
91
|
-
storage?: Storage;
|
|
92
|
-
monitor_session?: boolean;
|
|
93
|
-
token_renew_mode?: string;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
55
|
const oidcDatabase = {};
|
|
97
56
|
const oidcFactory = (configuration: OidcConfiguration, name = 'default') => {
|
|
98
57
|
if (oidcDatabase[name]) {
|
|
@@ -146,105 +105,17 @@ const autoRenewTokens = (oidc, refreshToken, expiresAt, extras:StringMap = null)
|
|
|
146
105
|
}, 1000);
|
|
147
106
|
};
|
|
148
107
|
|
|
149
|
-
const userInfoAsync = async (oidc) => {
|
|
150
|
-
if (oidc.userInfo != null) {
|
|
151
|
-
return oidc.userInfo;
|
|
152
|
-
}
|
|
153
|
-
if (!oidc.tokens) {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
const accessToken = oidc.tokens.accessToken;
|
|
157
|
-
if (!accessToken) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// We wait the synchronisation before making a request
|
|
162
|
-
while (oidc.tokens && !isTokensValid(oidc.tokens)) {
|
|
163
|
-
await sleepAsync(200);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
|
|
167
|
-
const url = oidcServerConfiguration.userInfoEndpoint;
|
|
168
|
-
const fetchUserInfo = async (accessToken) => {
|
|
169
|
-
const res = await fetch(url, {
|
|
170
|
-
headers: {
|
|
171
|
-
authorization: `Bearer ${accessToken}`,
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
if (res.status !== 200) {
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return res.json();
|
|
180
|
-
};
|
|
181
|
-
const userInfo = await fetchUserInfo(accessToken);
|
|
182
|
-
oidc.userInfo = userInfo;
|
|
183
|
-
return userInfo;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
const eventNames = {
|
|
187
|
-
service_worker_not_supported_by_browser: 'service_worker_not_supported_by_browser',
|
|
188
|
-
token_aquired: 'token_aquired',
|
|
189
|
-
logout_from_another_tab: 'logout_from_another_tab',
|
|
190
|
-
logout_from_same_tab: 'logout_from_same_tab',
|
|
191
|
-
token_renewed: 'token_renewed',
|
|
192
|
-
token_timer: 'token_timer',
|
|
193
|
-
loginAsync_begin: 'loginAsync_begin',
|
|
194
|
-
loginAsync_error: 'loginAsync_error',
|
|
195
|
-
loginCallbackAsync_begin: 'loginCallbackAsync_begin',
|
|
196
|
-
loginCallbackAsync_end: 'loginCallbackAsync_end',
|
|
197
|
-
loginCallbackAsync_error: 'loginCallbackAsync_error',
|
|
198
|
-
refreshTokensAsync_begin: 'refreshTokensAsync_begin',
|
|
199
|
-
refreshTokensAsync: 'refreshTokensAsync',
|
|
200
|
-
refreshTokensAsync_end: 'refreshTokensAsync_end',
|
|
201
|
-
refreshTokensAsync_error: 'refreshTokensAsync_error',
|
|
202
|
-
refreshTokensAsync_silent_error: 'refreshTokensAsync_silent_error',
|
|
203
|
-
tryKeepExistingSessionAsync_begin: 'tryKeepExistingSessionAsync_begin',
|
|
204
|
-
tryKeepExistingSessionAsync_end: 'tryKeepExistingSessionAsync_end',
|
|
205
|
-
tryKeepExistingSessionAsync_error: 'tryKeepExistingSessionAsync_error',
|
|
206
|
-
silentLoginAsync_begin: 'silentLoginAsync_begin',
|
|
207
|
-
silentLoginAsync: 'silentLoginAsync',
|
|
208
|
-
silentLoginAsync_end: 'silentLoginAsync_end',
|
|
209
|
-
silentLoginAsync_error: 'silentLoginAsync_error',
|
|
210
|
-
syncTokensAsync_begin: 'syncTokensAsync_begin',
|
|
211
|
-
syncTokensAsync_end: 'syncTokensAsync_end',
|
|
212
|
-
syncTokensAsync_error: 'syncTokensAsync_error',
|
|
213
|
-
};
|
|
214
|
-
|
|
215
108
|
const getRandomInt = (max) => {
|
|
216
109
|
return Math.floor(Math.random() * max);
|
|
217
110
|
};
|
|
218
111
|
|
|
219
|
-
const oneHourSecond = 60 * 60;
|
|
220
|
-
const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage = window.sessionStorage):
|
|
221
|
-
Promise<OidcAuthorizationServiceConfiguration> => {
|
|
222
|
-
const fullUrl = `${openIdIssuerUrl}/.well-known/openid-configuration`;
|
|
223
|
-
|
|
224
|
-
const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
|
|
225
|
-
const data = getFromCache(localStorageKey, storage, timeCacheSecond);
|
|
226
|
-
if (data) {
|
|
227
|
-
return new OidcAuthorizationServiceConfiguration(data);
|
|
228
|
-
}
|
|
229
|
-
const response = await fetch(fullUrl);
|
|
230
|
-
|
|
231
|
-
if (response.status !== 200) {
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const result = await response.json();
|
|
236
|
-
|
|
237
|
-
setCache(localStorageKey, result, storage);
|
|
238
|
-
return new OidcAuthorizationServiceConfiguration(result);
|
|
239
|
-
};
|
|
240
|
-
|
|
241
112
|
export class Oidc {
|
|
242
113
|
public configuration: OidcConfiguration;
|
|
243
114
|
public userInfo: null;
|
|
244
115
|
public tokens?: Tokens;
|
|
245
116
|
public events: Array<any>;
|
|
246
117
|
private timeoutId: NodeJS.Timeout;
|
|
247
|
-
|
|
118
|
+
public configurationName: string;
|
|
248
119
|
private checkSessionIFrame: CheckSessionIFrame;
|
|
249
120
|
constructor(configuration:OidcConfiguration, configurationName = 'default') {
|
|
250
121
|
let silent_login_uri = configuration.silent_login_uri;
|
|
@@ -335,96 +206,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
335
206
|
}
|
|
336
207
|
|
|
337
208
|
async silentLoginAsync(extras:StringMap = null, state:string = null, scope:string = null) {
|
|
338
|
-
|
|
339
|
-
return Promise.resolve(null);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
try {
|
|
343
|
-
this.publishEvent(eventNames.silentLoginAsync_begin, {});
|
|
344
|
-
const configuration = this.configuration;
|
|
345
|
-
let queries = '';
|
|
346
|
-
|
|
347
|
-
if (state) {
|
|
348
|
-
if (extras == null) {
|
|
349
|
-
extras = {};
|
|
350
|
-
}
|
|
351
|
-
extras.state = state;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
if (scope) {
|
|
355
|
-
if (extras == null) {
|
|
356
|
-
extras = {};
|
|
357
|
-
}
|
|
358
|
-
extras.scope = scope;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (extras != null) {
|
|
362
|
-
for (const [key, value] of Object.entries(extras)) {
|
|
363
|
-
if (queries === '') {
|
|
364
|
-
queries = `?${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
365
|
-
} else {
|
|
366
|
-
queries += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
const link = configuration.silent_login_uri + queries;
|
|
371
|
-
const idx = link.indexOf('/', link.indexOf('//') + 2);
|
|
372
|
-
const iFrameOrigin = link.substr(0, idx);
|
|
373
|
-
const iframe = document.createElement('iframe');
|
|
374
|
-
iframe.width = '0px';
|
|
375
|
-
iframe.height = '0px';
|
|
376
|
-
|
|
377
|
-
iframe.id = `${this.configurationName}_oidc_iframe`;
|
|
378
|
-
iframe.setAttribute('src', link);
|
|
379
|
-
document.body.appendChild(iframe);
|
|
380
|
-
return new Promise((resolve, reject) => {
|
|
381
|
-
try {
|
|
382
|
-
let isResolved = false;
|
|
383
|
-
window.onmessage = (e: MessageEvent<any>) => {
|
|
384
|
-
if (e.origin === iFrameOrigin &&
|
|
385
|
-
e.source === iframe.contentWindow
|
|
386
|
-
) {
|
|
387
|
-
const key = `${this.configurationName}_oidc_tokens:`;
|
|
388
|
-
const key_error = `${this.configurationName}_oidc_error:`;
|
|
389
|
-
const data = e.data;
|
|
390
|
-
if (data && typeof (data) === 'string') {
|
|
391
|
-
if (!isResolved) {
|
|
392
|
-
if (data.startsWith(key)) {
|
|
393
|
-
const result = JSON.parse(e.data.replace(key, ''));
|
|
394
|
-
this.publishEvent(eventNames.silentLoginAsync_end, {});
|
|
395
|
-
iframe.remove();
|
|
396
|
-
isResolved = true;
|
|
397
|
-
resolve(result);
|
|
398
|
-
} else if (data.startsWith(key_error)) {
|
|
399
|
-
const result = JSON.parse(e.data.replace(key_error, ''));
|
|
400
|
-
this.publishEvent(eventNames.silentLoginAsync_error, result);
|
|
401
|
-
iframe.remove();
|
|
402
|
-
isResolved = true;
|
|
403
|
-
reject(new Error('oidc_' + result.error));
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
const silentSigninTimeout = configuration.silent_login_timeout;
|
|
410
|
-
setTimeout(() => {
|
|
411
|
-
if (!isResolved) {
|
|
412
|
-
this.publishEvent(eventNames.silentLoginAsync_error, { reason: 'timeout' });
|
|
413
|
-
iframe.remove();
|
|
414
|
-
isResolved = true;
|
|
415
|
-
reject(new Error('timeout'));
|
|
416
|
-
}
|
|
417
|
-
}, silentSigninTimeout);
|
|
418
|
-
} catch (e) {
|
|
419
|
-
iframe.remove();
|
|
420
|
-
this.publishEvent(eventNames.silentLoginAsync_error, e);
|
|
421
|
-
reject(e);
|
|
422
|
-
}
|
|
423
|
-
});
|
|
424
|
-
} catch (e) {
|
|
425
|
-
this.publishEvent(eventNames.silentLoginAsync_error, e);
|
|
426
|
-
throw e;
|
|
427
|
-
}
|
|
209
|
+
return defaultSilentLoginAsync(this.configurationName, this.configuration, this.publishEvent.bind(this))(extras, state, scope);
|
|
428
210
|
}
|
|
429
211
|
|
|
430
212
|
initPromise = null;
|
|
@@ -537,157 +319,26 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
537
319
|
});
|
|
538
320
|
}
|
|
539
321
|
|
|
322
|
+
async startCheckSessionAsync(checkSessionIFrameUri, clientId, sessionState, isSilentSignin = false) {
|
|
323
|
+
const getCurrentTokens = () => this.tokens;
|
|
324
|
+
this.checkSessionIFrame = await defaultStartCheckSessionAsync(oidcDatabase, this.configuration, this.checkSessionIFrame, this.silentLoginAsync.bind(this), getCurrentTokens)(checkSessionIFrameUri, clientId, sessionState, isSilentSignin);
|
|
325
|
+
}
|
|
326
|
+
|
|
540
327
|
loginPromise: Promise<void> = null;
|
|
541
328
|
async loginAsync(callbackPath:string = undefined, extras:StringMap = null, isSilentSignin = false, scope:string = undefined, silentLoginOnly = false) {
|
|
542
329
|
if (this.loginPromise !== null) {
|
|
543
330
|
return this.loginPromise;
|
|
544
331
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const url = callbackPath || location.pathname + (location.search || '') + (location.hash || '');
|
|
550
|
-
const configuration = this.configuration;
|
|
551
|
-
let state;
|
|
552
|
-
if (extras && 'state' in extras) {
|
|
553
|
-
state = extras.state;
|
|
554
|
-
delete extras.state;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
if (silentLoginOnly) {
|
|
558
|
-
try {
|
|
559
|
-
const extraFinal = extras ?? configuration.extras ?? {};
|
|
560
|
-
const silentResult = await this.silentLoginAsync({
|
|
561
|
-
...extraFinal,
|
|
562
|
-
prompt: 'none',
|
|
563
|
-
}, state, scope);
|
|
564
|
-
|
|
565
|
-
if (silentResult) {
|
|
566
|
-
this.tokens = silentResult.tokens;
|
|
567
|
-
this.publishEvent(eventNames.token_aquired, {});
|
|
568
|
-
// @ts-ignore
|
|
569
|
-
this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt, extras);
|
|
570
|
-
return {};
|
|
571
|
-
}
|
|
572
|
-
} catch (e) {
|
|
573
|
-
return e;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
this.publishEvent(eventNames.loginAsync_begin, {});
|
|
577
|
-
console.log('extras', extras);
|
|
578
|
-
if (extras) {
|
|
579
|
-
for (const key of Object.keys(extras)) {
|
|
580
|
-
if (key.endsWith(':authorize_request')) {
|
|
581
|
-
delete extras[key];
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
try {
|
|
586
|
-
const redirectUri = isSilentSignin ? configuration.silent_redirect_uri : configuration.redirect_uri;
|
|
587
|
-
if (!scope) {
|
|
588
|
-
scope = configuration.scope;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
const extraFinal = extras ?? configuration.extras ?? {};
|
|
592
|
-
if (!extraFinal.nonce) {
|
|
593
|
-
extraFinal.nonce = randomString(12);
|
|
594
|
-
}
|
|
595
|
-
const nonce = { nonce: extraFinal.nonce };
|
|
596
|
-
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
597
|
-
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
598
|
-
let storage;
|
|
599
|
-
if (serviceWorker) {
|
|
600
|
-
serviceWorker.setLoginParams(this.configurationName, { callbackPath: url, extras: originExtras, state });
|
|
601
|
-
serviceWorker.startKeepAliveServiceWorker();
|
|
602
|
-
await serviceWorker.initAsync(oidcServerConfiguration, 'loginAsync', configuration);
|
|
603
|
-
await serviceWorker.setNonceAsync(nonce);
|
|
604
|
-
storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, {});
|
|
605
|
-
await storage.setItem('dummy', {});
|
|
606
|
-
} else {
|
|
607
|
-
let session = initSession(this.configurationName, configuration.storage ?? sessionStorage);
|
|
608
|
-
session.setLoginParams(this.configurationName, { callbackPath: url, extras: originExtras, state });
|
|
609
|
-
session = initSession(this.configurationName);
|
|
610
|
-
await session.setNonceAsync(nonce);
|
|
611
|
-
storage = new MemoryStorageBackend(session.saveItemsAsync, {});
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// @ts-ignore
|
|
615
|
-
const queryStringUtil = redirectUri.includes('#') ? new HashQueryStringUtils() : new NoHashQueryStringUtils();
|
|
616
|
-
const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
|
|
617
|
-
const authRequest = new AuthorizationRequest({
|
|
618
|
-
client_id: configuration.client_id,
|
|
619
|
-
redirect_uri: redirectUri,
|
|
620
|
-
scope,
|
|
621
|
-
response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
|
|
622
|
-
state,
|
|
623
|
-
extras: extraFinal,
|
|
624
|
-
});
|
|
625
|
-
authorizationHandler.performAuthorizationRequest(oidcServerConfiguration, authRequest);
|
|
626
|
-
} catch (exception) {
|
|
627
|
-
this.publishEvent(eventNames.loginAsync_error, exception);
|
|
628
|
-
throw exception;
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
|
-
this.loginPromise = loginLocalAsync();
|
|
332
|
+
if (silentLoginOnly) {
|
|
333
|
+
return defaultSilentLoginAsync2(window, this.configurationName, this.configuration, this.publishEvent.bind(this), this)(extras, scope);
|
|
334
|
+
}
|
|
335
|
+
this.loginPromise = defaultLoginAsync(window, this.configurationName, this.configuration, this.silentLoginAsync.bind(this), this.publishEvent.bind(this), this.initAsync.bind(this))(callbackPath, extras, isSilentSignin, scope);
|
|
632
336
|
return this.loginPromise.then(result => {
|
|
633
337
|
this.loginPromise = null;
|
|
634
338
|
return result;
|
|
635
339
|
});
|
|
636
340
|
}
|
|
637
341
|
|
|
638
|
-
async startCheckSessionAsync(checkSessionIFrameUri, clientId, sessionState, isSilentSignin = false) {
|
|
639
|
-
return new Promise<void>((resolve, reject): void => {
|
|
640
|
-
if (this.configuration.silent_login_uri && this.configuration.silent_redirect_uri && this.configuration.monitor_session && checkSessionIFrameUri && sessionState && !isSilentSignin) {
|
|
641
|
-
const checkSessionCallback = () => {
|
|
642
|
-
this.checkSessionIFrame.stop();
|
|
643
|
-
|
|
644
|
-
if (this.tokens === null) {
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
// @ts-ignore
|
|
648
|
-
const idToken = this.tokens.idToken;
|
|
649
|
-
// @ts-ignore
|
|
650
|
-
const idTokenPayload = this.tokens.idTokenPayload;
|
|
651
|
-
this.silentLoginAsync({
|
|
652
|
-
prompt: 'none',
|
|
653
|
-
id_token_hint: idToken,
|
|
654
|
-
scope: 'openid',
|
|
655
|
-
}).then((silentSigninResponse) => {
|
|
656
|
-
const iFrameIdTokenPayload = silentSigninResponse.tokens.idTokenPayload;
|
|
657
|
-
if (idTokenPayload.sub === iFrameIdTokenPayload.sub) {
|
|
658
|
-
const sessionState = silentSigninResponse.sessionState;
|
|
659
|
-
this.checkSessionIFrame.start(silentSigninResponse.sessionState);
|
|
660
|
-
if (idTokenPayload.sid === iFrameIdTokenPayload.sid) {
|
|
661
|
-
console.debug('SessionMonitor._callback: Same sub still logged in at OP, restarting check session iframe; session_state:', sessionState);
|
|
662
|
-
} else {
|
|
663
|
-
console.debug('SessionMonitor._callback: Same sub still logged in at OP, session state has changed, restarting check session iframe; session_state:', sessionState);
|
|
664
|
-
}
|
|
665
|
-
} else {
|
|
666
|
-
console.debug('SessionMonitor._callback: Different subject signed into OP:', iFrameIdTokenPayload.sub);
|
|
667
|
-
}
|
|
668
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
669
|
-
}).catch(async (e) => {
|
|
670
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
671
|
-
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
672
|
-
// @ts-ignore
|
|
673
|
-
await oidc.logoutOtherTabAsync(this.configuration.client_id, idTokenPayload.sub);
|
|
674
|
-
}
|
|
675
|
-
});
|
|
676
|
-
};
|
|
677
|
-
|
|
678
|
-
this.checkSessionIFrame = new CheckSessionIFrame(checkSessionCallback, clientId, checkSessionIFrameUri);
|
|
679
|
-
this.checkSessionIFrame.load().then(() => {
|
|
680
|
-
this.checkSessionIFrame.start(sessionState);
|
|
681
|
-
resolve();
|
|
682
|
-
}).catch((e) => {
|
|
683
|
-
reject(e);
|
|
684
|
-
});
|
|
685
|
-
} else {
|
|
686
|
-
resolve();
|
|
687
|
-
}
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
|
-
|
|
691
342
|
loginCallbackPromise : Promise<any> = null;
|
|
692
343
|
async loginCallbackAsync(isSilenSignin = false) {
|
|
693
344
|
if (this.loginCallbackPromise !== null) {
|
|
@@ -775,9 +426,9 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
775
426
|
return;
|
|
776
427
|
}
|
|
777
428
|
|
|
778
|
-
|
|
429
|
+
const extras = {};
|
|
779
430
|
if (request && request.internal) {
|
|
780
|
-
|
|
431
|
+
// @ts-ignore
|
|
781
432
|
extras.code_verifier = request.internal.code_verifier;
|
|
782
433
|
if (configuration.token_request_extras) {
|
|
783
434
|
for (const [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
@@ -786,7 +437,7 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
786
437
|
}
|
|
787
438
|
if (getLoginParams && getLoginParams.extras) {
|
|
788
439
|
for (const [key, value] of Object.entries(getLoginParams.extras)) {
|
|
789
|
-
if (key.endsWith(':
|
|
440
|
+
if (key.endsWith(':token_request')) {
|
|
790
441
|
extras[key.replace(':token_request', '')] = value;
|
|
791
442
|
}
|
|
792
443
|
}
|
|
@@ -795,8 +446,8 @@ Please checkout that you are using OIDC hook inside a <OidcProvider configuratio
|
|
|
795
446
|
|
|
796
447
|
const tokenRequest = new TokenRequest({
|
|
797
448
|
client_id: clientId,
|
|
798
|
-
redirect_uri: redirectUri,
|
|
799
|
-
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
|
|
449
|
+
redirect_uri: redirectUri, // @ts-ignore
|
|
450
|
+
grant_type: extras.grant_type ?? GRANT_TYPE_AUTHORIZATION_CODE,
|
|
800
451
|
code: response.code,
|
|
801
452
|
refresh_token: undefined,
|
|
802
453
|
extras,
|