@axa-fr/react-oidc 6.5.7 → 6.5.8
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.js +39 -104
- package/dist/FetchToken.js.map +1 -1
- package/dist/OidcProvider.js +76 -110
- package/dist/OidcProvider.js.map +1 -1
- package/dist/OidcSecure.js +11 -60
- package/dist/OidcSecure.js.map +1 -1
- package/dist/ReactOidc.js +56 -74
- package/dist/ReactOidc.js.map +1 -1
- package/dist/User.js +13 -32
- package/dist/User.js.map +1 -1
- package/dist/core/default-component/AuthenticateError.component.js +4 -29
- package/dist/core/default-component/AuthenticateError.component.js.map +1 -1
- package/dist/core/default-component/Authenticating.component.js +4 -29
- package/dist/core/default-component/Authenticating.component.js.map +1 -1
- package/dist/core/default-component/Callback.component.js +29 -99
- package/dist/core/default-component/Callback.component.js.map +1 -1
- package/dist/core/default-component/Loading.component.js +3 -28
- package/dist/core/default-component/Loading.component.js.map +1 -1
- package/dist/core/default-component/ServiceWorkerNotSupported.component.js +4 -29
- package/dist/core/default-component/ServiceWorkerNotSupported.component.js.map +1 -1
- package/dist/core/default-component/SessionLost.component.js +6 -13
- package/dist/core/default-component/SessionLost.component.js.map +1 -1
- package/dist/core/default-component/SilentCallback.component.js +13 -73
- package/dist/core/default-component/SilentCallback.component.js.map +1 -1
- package/dist/core/default-component/SilentLogin.component.js +13 -43
- package/dist/core/default-component/SilentLogin.component.js.map +1 -1
- package/dist/core/default-component/index.js +6 -19
- package/dist/core/default-component/index.js.map +1 -1
- package/dist/core/routes/OidcRoutes.js +20 -49
- package/dist/core/routes/OidcRoutes.js.map +1 -1
- package/dist/core/routes/index.js +1 -8
- package/dist/core/routes/index.js.map +1 -1
- package/dist/core/routes/withRouter.js +13 -20
- package/dist/core/routes/withRouter.js.map +1 -1
- package/dist/index.js +5 -18
- package/dist/index.js.map +1 -1
- package/dist/vanilla/checkSessionIFrame.js +21 -30
- package/dist/vanilla/checkSessionIFrame.js.map +1 -1
- package/dist/vanilla/index.js +1 -5
- package/dist/vanilla/index.js.map +1 -1
- package/dist/vanilla/initSession.js +41 -78
- package/dist/vanilla/initSession.js.map +1 -1
- package/dist/vanilla/initWorker.js +99 -168
- package/dist/vanilla/initWorker.js.map +1 -1
- package/dist/vanilla/memoryStorageBackend.js +11 -17
- package/dist/vanilla/memoryStorageBackend.js.map +1 -1
- package/dist/vanilla/noHashQueryStringUtils.js +15 -46
- package/dist/vanilla/noHashQueryStringUtils.js.map +1 -1
- package/dist/vanilla/oidc.js +945 -1394
- package/dist/vanilla/oidc.js.map +1 -1
- package/dist/vanilla/parseTokens.js +33 -53
- package/dist/vanilla/parseTokens.js.map +1 -1
- package/dist/vanilla/route-utils.js +17 -23
- package/dist/vanilla/route-utils.js.map +1 -1
- package/dist/vanilla/timer.js +21 -23
- package/dist/vanilla/timer.js.map +1 -1
- package/package.json +2 -3
- package/src/oidc/FetchToken.tsx +0 -61
- package/src/oidc/OidcProvider.tsx +0 -206
- package/src/oidc/OidcSecure.tsx +0 -37
- package/src/oidc/ReactOidc.tsx +0 -139
- package/src/oidc/User.ts +0 -38
- package/src/oidc/core/default-component/AuthenticateError.component.tsx +0 -13
- package/src/oidc/core/default-component/Authenticating.component.tsx +0 -13
- package/src/oidc/core/default-component/Callback.component.tsx +0 -46
- package/src/oidc/core/default-component/Loading.component.tsx +0 -10
- package/src/oidc/core/default-component/ServiceWorkerNotSupported.component.tsx +0 -13
- package/src/oidc/core/default-component/SessionLost.component.tsx +0 -14
- package/src/oidc/core/default-component/SilentCallback.component.tsx +0 -22
- package/src/oidc/core/default-component/SilentLogin.component.tsx +0 -35
- package/src/oidc/core/default-component/index.ts +0 -6
- package/src/oidc/core/routes/OidcRoutes.spec.tsx +0 -15
- package/src/oidc/core/routes/OidcRoutes.tsx +0 -69
- package/src/oidc/core/routes/__snapshots__/OidcRoutes.spec.tsx.snap +0 -7
- package/src/oidc/core/routes/index.ts +0 -2
- package/src/oidc/core/routes/withRouter.spec.tsx +0 -48
- package/src/oidc/core/routes/withRouter.tsx +0 -64
- package/src/oidc/index.ts +0 -5
- package/src/oidc/vanilla/OidcServiceWorker.js +0 -435
- package/src/oidc/vanilla/OidcTrustedDomains.js +0 -16
- package/src/oidc/vanilla/checkSessionIFrame.ts +0 -82
- package/src/oidc/vanilla/index.ts +0 -1
- package/src/oidc/vanilla/initSession.ts +0 -67
- package/src/oidc/vanilla/initWorker.ts +0 -165
- package/src/oidc/vanilla/memoryStorageBackend.ts +0 -33
- package/src/oidc/vanilla/noHashQueryStringUtils.ts +0 -33
- package/src/oidc/vanilla/oidc.ts +0 -1230
- package/src/oidc/vanilla/parseTokens.ts +0 -150
- package/src/oidc/vanilla/route-utils.spec.ts +0 -15
- package/src/oidc/vanilla/route-utils.ts +0 -76
- package/src/oidc/vanilla/timer.ts +0 -165
- package/tsconfig.json +0 -38
package/src/oidc/vanilla/oidc.ts
DELETED
|
@@ -1,1230 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AuthorizationNotifier,
|
|
3
|
-
AuthorizationRequest,
|
|
4
|
-
AuthorizationServiceConfiguration,
|
|
5
|
-
BaseTokenRequestHandler,
|
|
6
|
-
DefaultCrypto,
|
|
7
|
-
FetchRequestor,
|
|
8
|
-
GRANT_TYPE_AUTHORIZATION_CODE,
|
|
9
|
-
GRANT_TYPE_REFRESH_TOKEN,
|
|
10
|
-
RedirectRequestHandler,
|
|
11
|
-
TokenRequest
|
|
12
|
-
} from '@openid/appauth';
|
|
13
|
-
import {HashQueryStringUtils, NoHashQueryStringUtils} from './noHashQueryStringUtils';
|
|
14
|
-
import {initWorkerAsync, sleepAsync} from './initWorker'
|
|
15
|
-
import {MemoryStorageBackend} from "./memoryStorageBackend";
|
|
16
|
-
import {initSession} from "./initSession";
|
|
17
|
-
import timer from './timer';
|
|
18
|
-
|
|
19
|
-
import {CheckSessionIFrame} from "./checkSessionIFrame"
|
|
20
|
-
import {getParseQueryStringFromLocation} from "./route-utils";
|
|
21
|
-
import {AuthorizationServiceConfigurationJson} from "@openid/appauth/src/authorization_service_configuration";
|
|
22
|
-
import {computeTimeLeft, isTokensOidcValid, isTokensValid, parseOriginalTokens, setTokens} from "./parseTokens";
|
|
23
|
-
|
|
24
|
-
const performTokenRequestAsync= async (url, details, extras, oldTokens) => {
|
|
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 tokens = await response.json();
|
|
51
|
-
return {
|
|
52
|
-
success : true,
|
|
53
|
-
data: parseOriginalTokens(tokens, oldTokens)
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const internalFetch = async (url, headers, numberRetry=0) => {
|
|
58
|
-
let response;
|
|
59
|
-
try {
|
|
60
|
-
let controller = new AbortController();
|
|
61
|
-
setTimeout(() => controller.abort(), 10000);
|
|
62
|
-
response = await fetch(url, {...headers, signal: controller.signal});
|
|
63
|
-
} catch (e) {
|
|
64
|
-
if (e.message === 'AbortError'
|
|
65
|
-
|| e.message === 'Network request failed') {
|
|
66
|
-
if(numberRetry <=1) {
|
|
67
|
-
return await internalFetch(url, headers, numberRetry + 1);
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
throw e;
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
console.error(e.message);
|
|
74
|
-
throw e; // rethrow other unexpected errors
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return response;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface OidcAuthorizationServiceConfigurationJson extends AuthorizationServiceConfigurationJson{
|
|
81
|
-
check_session_iframe?: string;
|
|
82
|
-
issuer:string;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export class OidcAuthorizationServiceConfiguration extends AuthorizationServiceConfiguration{
|
|
86
|
-
private check_session_iframe: string;
|
|
87
|
-
private issuer: string;
|
|
88
|
-
|
|
89
|
-
constructor(request: any) {
|
|
90
|
-
super(request);
|
|
91
|
-
this.authorizationEndpoint = request.authorization_endpoint;
|
|
92
|
-
this.tokenEndpoint = request.token_endpoint;
|
|
93
|
-
this.revocationEndpoint = request.revocation_endpoint;
|
|
94
|
-
this.userInfoEndpoint = request.userinfo_endpoint;
|
|
95
|
-
this.check_session_iframe = request.check_session_iframe;
|
|
96
|
-
this.issuer = request.issuer;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
export interface StringMap {
|
|
103
|
-
[key: string]: string;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface loginCallbackResult {
|
|
107
|
-
state: string,
|
|
108
|
-
callbackPath: string,
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export interface AuthorityConfiguration {
|
|
112
|
-
authorization_endpoint: string;
|
|
113
|
-
token_endpoint: string;
|
|
114
|
-
revocation_endpoint: string;
|
|
115
|
-
end_session_endpoint?: string;
|
|
116
|
-
userinfo_endpoint?: string;
|
|
117
|
-
check_session_iframe?:string;
|
|
118
|
-
issuer:string;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export type OidcConfiguration = {
|
|
122
|
-
client_id: string,
|
|
123
|
-
redirect_uri: string,
|
|
124
|
-
silent_redirect_uri?:string,
|
|
125
|
-
silent_login_uri?:string,
|
|
126
|
-
silent_login_timeout?:number,
|
|
127
|
-
scope: string,
|
|
128
|
-
authority: string,
|
|
129
|
-
authority_time_cache_wellknowurl_in_second?: number,
|
|
130
|
-
authority_configuration?: AuthorityConfiguration,
|
|
131
|
-
refresh_time_before_tokens_expiration_in_second?: number,
|
|
132
|
-
token_request_timeout?: number,
|
|
133
|
-
service_worker_relative_url?:string,
|
|
134
|
-
service_worker_only?:boolean,
|
|
135
|
-
extras?:StringMap
|
|
136
|
-
token_request_extras?:StringMap,
|
|
137
|
-
storage?: Storage
|
|
138
|
-
monitor_session?: boolean
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const oidcDatabase = {};
|
|
142
|
-
const oidcFactory = (configuration: OidcConfiguration, name="default") => {
|
|
143
|
-
if(oidcDatabase[name]){
|
|
144
|
-
return oidcDatabase[name];
|
|
145
|
-
}
|
|
146
|
-
oidcDatabase[name] = new Oidc(configuration, name)
|
|
147
|
-
return oidcDatabase[name];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const loginCallbackWithAutoTokensRenewAsync = async (oidc) => {
|
|
151
|
-
const { parsedTokens, state, callbackPath } = await oidc.loginCallbackAsync();
|
|
152
|
-
oidc.timeoutId = autoRenewTokens(oidc, parsedTokens.refreshToken, parsedTokens.expiresAt)
|
|
153
|
-
return { state, callbackPath };
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function renewTokensAndStartTimerAsync(oidc, refreshToken, forceRefresh =false, extras:StringMap=null) {
|
|
157
|
-
const {tokens, status} = await oidc.synchroniseTokensAsync(refreshToken, 0, forceRefresh, extras);
|
|
158
|
-
oidc.tokens = tokens;
|
|
159
|
-
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName);
|
|
160
|
-
if (!serviceWorker) {
|
|
161
|
-
const session = initSession(oidc.configurationName, oidc.configuration.redirect_uri, oidc.configuration.storage);
|
|
162
|
-
await session.setTokens(oidc.tokens);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (!oidc.tokens) {
|
|
166
|
-
await oidc.destroyAsync(status);
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (oidc.timeoutId) {
|
|
171
|
-
oidc.timeoutId = autoRenewTokens(oidc, tokens.refreshToken, oidc.tokens.expiresAt, extras);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const autoRenewTokens = (oidc, refreshToken, expiresAt, extras:StringMap=null) => {
|
|
176
|
-
const refreshTimeBeforeTokensExpirationInSecond = oidc.configuration.refresh_time_before_tokens_expiration_in_second;
|
|
177
|
-
return timer.setTimeout(async () => {
|
|
178
|
-
const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
|
|
179
|
-
const timeInfo = { timeLeft };
|
|
180
|
-
oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
|
|
181
|
-
await renewTokensAndStartTimerAsync(oidc, refreshToken, false, extras);
|
|
182
|
-
}, 1000);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const getLoginSessionKey = (configurationName:string, redirectUri:string) => {
|
|
186
|
-
return `oidc_login.${configurationName}:${redirectUri}`;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const setLoginParams = (configurationName:string, redirectUri:string, data) =>{
|
|
190
|
-
const sessionKey = getLoginSessionKey(configurationName, redirectUri);
|
|
191
|
-
getLoginParamsCache = data
|
|
192
|
-
sessionStorage[sessionKey] = JSON.stringify(data);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
let getLoginParamsCache = null;
|
|
196
|
-
const getLoginParams = (configurationName, redirectUri) => {
|
|
197
|
-
const dataString = sessionStorage[getLoginSessionKey(configurationName, redirectUri)];
|
|
198
|
-
if(!getLoginParamsCache){
|
|
199
|
-
getLoginParamsCache = JSON.parse(dataString);
|
|
200
|
-
}
|
|
201
|
-
return getLoginParamsCache;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const userInfoAsync = async (oidc) => {
|
|
205
|
-
if(oidc.userInfo != null){
|
|
206
|
-
return oidc.userInfo;
|
|
207
|
-
}
|
|
208
|
-
if(!oidc.tokens){
|
|
209
|
-
return null;
|
|
210
|
-
}
|
|
211
|
-
const accessToken = oidc.tokens.accessToken;
|
|
212
|
-
if(!accessToken){
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
// We wait the synchronisation before making a request
|
|
216
|
-
while (oidc.tokens && !isTokensValid(oidc.tokens)){
|
|
217
|
-
await sleepAsync(200);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const oidcServerConfiguration = await oidc.initAsync(oidc.configuration.authority, oidc.configuration.authority_configuration);
|
|
221
|
-
const url = oidcServerConfiguration.userInfoEndpoint;
|
|
222
|
-
const fetchUserInfo = async (accessToken) => {
|
|
223
|
-
const res = await fetch(url, {
|
|
224
|
-
headers: {
|
|
225
|
-
authorization: `Bearer ${accessToken}`,
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
if(res.status != 200 ){
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return res.json();
|
|
234
|
-
};
|
|
235
|
-
const userInfo = await fetchUserInfo(accessToken);
|
|
236
|
-
oidc.userInfo= userInfo;
|
|
237
|
-
return userInfo;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const eventNames = {
|
|
241
|
-
service_worker_not_supported_by_browser: "service_worker_not_supported_by_browser",
|
|
242
|
-
token_aquired: "token_aquired",
|
|
243
|
-
logout_from_another_tab: "logout_from_another_tab",
|
|
244
|
-
logout_from_same_tab: "logout_from_same_tab",
|
|
245
|
-
token_renewed: "token_renewed",
|
|
246
|
-
token_timer: "token_timer",
|
|
247
|
-
loginAsync_begin:"loginAsync_begin",
|
|
248
|
-
loginAsync_error:"loginAsync_error",
|
|
249
|
-
loginCallbackAsync_begin:"loginCallbackAsync_begin",
|
|
250
|
-
loginCallbackAsync_end:"loginCallbackAsync_end",
|
|
251
|
-
loginCallbackAsync_error:"loginCallbackAsync_error",
|
|
252
|
-
refreshTokensAsync_begin: "refreshTokensAsync_begin",
|
|
253
|
-
refreshTokensAsync: "refreshTokensAsync",
|
|
254
|
-
refreshTokensAsync_end: "refreshTokensAsync_end",
|
|
255
|
-
refreshTokensAsync_error: "refreshTokensAsync_error",
|
|
256
|
-
refreshTokensAsync_silent_error: "refreshTokensAsync_silent_error",
|
|
257
|
-
tryKeepExistingSessionAsync_begin: "tryKeepExistingSessionAsync_begin",
|
|
258
|
-
tryKeepExistingSessionAsync_end: "tryKeepExistingSessionAsync_end",
|
|
259
|
-
tryKeepExistingSessionAsync_error: "tryKeepExistingSessionAsync_error",
|
|
260
|
-
silentLoginAsync_begin: "silentLoginAsync_begin",
|
|
261
|
-
silentLoginAsync: "silentLoginAsync",
|
|
262
|
-
silentLoginAsync_end: "silentLoginAsync_end",
|
|
263
|
-
silentLoginAsync_error: "silentLoginAsync_error",
|
|
264
|
-
syncTokensAsync_begin: "syncTokensAsync_begin",
|
|
265
|
-
syncTokensAsync_end: "syncTokensAsync_end",
|
|
266
|
-
syncTokensAsync_error: "syncTokensAsync_error"
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const getRandomInt = (max) => {
|
|
270
|
-
return Math.floor(Math.random() * max);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
const oneHourSecond = 60 * 60;
|
|
274
|
-
let fetchFromIssuerCache = {};
|
|
275
|
-
const fetchFromIssuer = async (openIdIssuerUrl: string, timeCacheSecond = oneHourSecond, storage= window.sessionStorage):
|
|
276
|
-
Promise<OidcAuthorizationServiceConfiguration> => {
|
|
277
|
-
const fullUrl = `${openIdIssuerUrl}/.well-known/openid-configuration`;
|
|
278
|
-
|
|
279
|
-
const localStorageKey = `oidc.server:${openIdIssuerUrl}`;
|
|
280
|
-
if(!fetchFromIssuerCache[localStorageKey]) {
|
|
281
|
-
if(storage) {
|
|
282
|
-
const cacheJson = storage.getItem(localStorageKey);
|
|
283
|
-
if (cacheJson) {
|
|
284
|
-
fetchFromIssuerCache[localStorageKey] = JSON.parse(cacheJson);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
const oneHourMinisecond = 1000 * timeCacheSecond;
|
|
289
|
-
// @ts-ignore
|
|
290
|
-
if(fetchFromIssuerCache[localStorageKey] && (fetchFromIssuerCache[localStorageKey].timestamp + oneHourMinisecond) > Date.now()){
|
|
291
|
-
return new OidcAuthorizationServiceConfiguration(fetchFromIssuerCache[localStorageKey].result);
|
|
292
|
-
}
|
|
293
|
-
const response = await fetch(fullUrl);
|
|
294
|
-
|
|
295
|
-
if (response.status != 200) {
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const result = await response.json();
|
|
300
|
-
|
|
301
|
-
const timestamp = Date.now();
|
|
302
|
-
fetchFromIssuerCache[localStorageKey] = {result, timestamp};
|
|
303
|
-
if(storage) {
|
|
304
|
-
storage.setItem(localStorageKey, JSON.stringify({result, timestamp}));
|
|
305
|
-
}
|
|
306
|
-
return new OidcAuthorizationServiceConfiguration(result);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const buildQueries = (extras:StringMap) => {
|
|
310
|
-
let queries = '';
|
|
311
|
-
if(extras != null){
|
|
312
|
-
for (let [key, value] of Object.entries(extras)) {
|
|
313
|
-
if (queries === ""){
|
|
314
|
-
queries = `?${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
315
|
-
} else {
|
|
316
|
-
queries+= `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
return queries;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
export class Oidc {
|
|
324
|
-
public configuration: OidcConfiguration;
|
|
325
|
-
public userInfo: null;
|
|
326
|
-
public tokens: null;
|
|
327
|
-
public events: Array<any>;
|
|
328
|
-
private timeoutId: NodeJS.Timeout;
|
|
329
|
-
private configurationName: string;
|
|
330
|
-
private checkSessionIFrame: CheckSessionIFrame;
|
|
331
|
-
constructor(configuration:OidcConfiguration, configurationName="default") {
|
|
332
|
-
let silent_login_uri = configuration.silent_login_uri;
|
|
333
|
-
if(configuration.silent_redirect_uri && !configuration.silent_login_uri){
|
|
334
|
-
silent_login_uri = `${configuration.silent_redirect_uri.replace("-callback", "").replace("callback", "")}-login`;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
this.configuration = {...configuration,
|
|
338
|
-
silent_login_uri,
|
|
339
|
-
monitor_session: configuration.monitor_session ?? false,
|
|
340
|
-
refresh_time_before_tokens_expiration_in_second : configuration.refresh_time_before_tokens_expiration_in_second ?? 60,
|
|
341
|
-
silent_login_timeout: configuration.silent_login_timeout ?? 12000,
|
|
342
|
-
};
|
|
343
|
-
this.configurationName= configurationName;
|
|
344
|
-
this.tokens = null
|
|
345
|
-
this.userInfo = null;
|
|
346
|
-
this.events = [];
|
|
347
|
-
this.timeoutId = null;
|
|
348
|
-
this.synchroniseTokensAsync.bind(this);
|
|
349
|
-
this.loginCallbackWithAutoTokensRenewAsync.bind(this);
|
|
350
|
-
this.initAsync.bind(this);
|
|
351
|
-
this.loginCallbackAsync.bind(this);
|
|
352
|
-
this._loginCallbackAsync.bind(this);
|
|
353
|
-
this.subscriveEvents.bind(this);
|
|
354
|
-
this.removeEventSubscription.bind(this);
|
|
355
|
-
this.publishEvent.bind(this);
|
|
356
|
-
this.destroyAsync.bind(this);
|
|
357
|
-
this.logoutAsync.bind(this);
|
|
358
|
-
this.renewTokensAsync.bind(this);
|
|
359
|
-
|
|
360
|
-
this.initAsync(this.configuration.authority, this.configuration.authority_configuration);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
subscriveEvents(func){
|
|
364
|
-
const id = getRandomInt(9999999999999).toString();
|
|
365
|
-
this.events.push({id, func});
|
|
366
|
-
return id;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
removeEventSubscription(id){
|
|
370
|
-
const newEvents = this.events.filter(e => e.id !== id);
|
|
371
|
-
this.events = newEvents;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
publishEvent(eventName, data){
|
|
375
|
-
this.events.forEach(event => {
|
|
376
|
-
event.func(eventName, data)
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
static getOrCreate(configuration, name="default") {
|
|
380
|
-
return oidcFactory(configuration, name);
|
|
381
|
-
}
|
|
382
|
-
static get(name="default") {
|
|
383
|
-
const insideBrowser = (typeof process === 'undefined');
|
|
384
|
-
if(!oidcDatabase.hasOwnProperty(name) && insideBrowser){
|
|
385
|
-
throw Error(`Oidc library does seem initialized.
|
|
386
|
-
Please checkout that you are using OIDC hook inside a <OidcProvider configurationName="${name}"></OidcProvider> compoment.`)
|
|
387
|
-
}
|
|
388
|
-
return oidcDatabase[name];
|
|
389
|
-
}
|
|
390
|
-
static eventNames = eventNames;
|
|
391
|
-
|
|
392
|
-
_silentLoginCallbackFromIFrame(){
|
|
393
|
-
if (this.configuration.silent_redirect_uri && this.configuration.silent_login_uri) {
|
|
394
|
-
const queryParams = getParseQueryStringFromLocation(window.location.href);
|
|
395
|
-
window.top.postMessage(`${this.configurationName}_oidc_tokens:${JSON.stringify({tokens:this.tokens, sessionState:queryParams.session_state})}`, window.location.origin);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
_silentLoginErrorCallbackFromIFrame() {
|
|
399
|
-
if (this.configuration.silent_redirect_uri && this.configuration.silent_login_uri) {
|
|
400
|
-
const queryParams = getParseQueryStringFromLocation(window.location.href);
|
|
401
|
-
window.top.postMessage(`${this.configurationName}_oidc_error:${JSON.stringify({error: queryParams.error})}`, window.location.origin);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
async silentLoginCallBackAsync() {
|
|
406
|
-
try {
|
|
407
|
-
await this.loginCallbackAsync(true);
|
|
408
|
-
this._silentLoginCallbackFromIFrame();
|
|
409
|
-
} catch (error) {
|
|
410
|
-
console.error(error)
|
|
411
|
-
this._silentLoginErrorCallbackFromIFrame();
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
async silentLoginAsync(extras:StringMap=null, state:string=null, scope:string=null) {
|
|
416
|
-
if (!this.configuration.silent_redirect_uri || !this.configuration.silent_login_uri) {
|
|
417
|
-
return Promise.resolve(null);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
try {
|
|
421
|
-
this.publishEvent(eventNames.silentLoginAsync_begin, {});
|
|
422
|
-
const configuration = this.configuration
|
|
423
|
-
let queries = "";
|
|
424
|
-
|
|
425
|
-
if(state){
|
|
426
|
-
if(extras == null){
|
|
427
|
-
extras = {};
|
|
428
|
-
}
|
|
429
|
-
extras.state = state;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if(scope){
|
|
433
|
-
if(extras == null){
|
|
434
|
-
extras = {};
|
|
435
|
-
}
|
|
436
|
-
extras.scope = scope;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
if(extras != null){
|
|
440
|
-
for (let [key, value] of Object.entries(extras)) {
|
|
441
|
-
if (queries === ""){
|
|
442
|
-
queries = `?${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
443
|
-
} else {
|
|
444
|
-
queries+= `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
const link = configuration.silent_login_uri + queries;
|
|
449
|
-
const idx = link.indexOf("/", link.indexOf("//") + 2);
|
|
450
|
-
const iFrameOrigin = link.substr(0, idx);
|
|
451
|
-
const iframe = document.createElement('iframe');
|
|
452
|
-
iframe.width = "0px";
|
|
453
|
-
iframe.height = "0px";
|
|
454
|
-
|
|
455
|
-
iframe.id = `${this.configurationName}_oidc_iframe`;
|
|
456
|
-
iframe.setAttribute("src", link);
|
|
457
|
-
document.body.appendChild(iframe);
|
|
458
|
-
const self = this;
|
|
459
|
-
return new Promise((resolve, reject) => {
|
|
460
|
-
try {
|
|
461
|
-
let isResolved = false;
|
|
462
|
-
window.onmessage = function (e) {
|
|
463
|
-
if (e.origin === iFrameOrigin &&
|
|
464
|
-
e.source === iframe.contentWindow
|
|
465
|
-
) {
|
|
466
|
-
const key = `${self.configurationName}_oidc_tokens:`;
|
|
467
|
-
const key_error = `${self.configurationName}_oidc_error:`;
|
|
468
|
-
const data = e.data;
|
|
469
|
-
if (data && typeof (data) === "string") {
|
|
470
|
-
if (!isResolved) {
|
|
471
|
-
if(data.startsWith(key)) {
|
|
472
|
-
const result = JSON.parse(e.data.replace(key, ''));
|
|
473
|
-
self.publishEvent(eventNames.silentLoginAsync_end, {});
|
|
474
|
-
iframe.remove();
|
|
475
|
-
isResolved = true;
|
|
476
|
-
resolve(result);
|
|
477
|
-
}
|
|
478
|
-
else if(data.startsWith(key_error)) {
|
|
479
|
-
const result = JSON.parse(e.data.replace(key_error, ''));
|
|
480
|
-
self.publishEvent(eventNames.silentLoginAsync_error, result);
|
|
481
|
-
iframe.remove();
|
|
482
|
-
isResolved = true;
|
|
483
|
-
reject(new Error("oidc_"+result.error));
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
const silentSigninTimeout = configuration.silent_login_timeout;
|
|
490
|
-
setTimeout(() => {
|
|
491
|
-
if (!isResolved) {
|
|
492
|
-
self.publishEvent(eventNames.silentLoginAsync_error, {reason: "timeout"});
|
|
493
|
-
iframe.remove();
|
|
494
|
-
isResolved = true;
|
|
495
|
-
reject(new Error("timeout"));
|
|
496
|
-
}
|
|
497
|
-
}, silentSigninTimeout);
|
|
498
|
-
} catch (e) {
|
|
499
|
-
iframe.remove();
|
|
500
|
-
self.publishEvent(eventNames.silentLoginAsync_error, e);
|
|
501
|
-
reject(e);
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
} catch (e) {
|
|
505
|
-
this.publishEvent(eventNames.silentLoginAsync_error, e);
|
|
506
|
-
throw e;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
initPromise = null;
|
|
510
|
-
async initAsync(authority:string, authorityConfiguration:AuthorityConfiguration) {
|
|
511
|
-
if(this.initPromise !== null){
|
|
512
|
-
return this.initPromise;
|
|
513
|
-
}
|
|
514
|
-
const localFuncAsync = async () => {
|
|
515
|
-
if (authorityConfiguration != null) {
|
|
516
|
-
return new OidcAuthorizationServiceConfiguration({
|
|
517
|
-
authorization_endpoint: authorityConfiguration.authorization_endpoint,
|
|
518
|
-
end_session_endpoint: authorityConfiguration.end_session_endpoint,
|
|
519
|
-
revocation_endpoint: authorityConfiguration.revocation_endpoint,
|
|
520
|
-
token_endpoint: authorityConfiguration.token_endpoint,
|
|
521
|
-
userinfo_endpoint: authorityConfiguration.userinfo_endpoint,
|
|
522
|
-
check_session_iframe: authorityConfiguration.check_session_iframe,
|
|
523
|
-
issuer: authorityConfiguration.issuer,
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
const serviceWorker = await initWorkerAsync(this.configuration.service_worker_relative_url, this.configurationName);
|
|
528
|
-
const storage = serviceWorker ? window.localStorage : null;
|
|
529
|
-
return await fetchFromIssuer(authority, this.configuration.authority_time_cache_wellknowurl_in_second ?? 60 * 60, storage);
|
|
530
|
-
}
|
|
531
|
-
this.initPromise = localFuncAsync();
|
|
532
|
-
return this.initPromise.then((result) =>{
|
|
533
|
-
this.initPromise = null;
|
|
534
|
-
return result;
|
|
535
|
-
})
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
tryKeepExistingSessionPromise = null;
|
|
539
|
-
async tryKeepExistingSessionAsync() {
|
|
540
|
-
if(this.tryKeepExistingSessionPromise !== null){
|
|
541
|
-
return this.tryKeepExistingSessionPromise;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
const funcAsync =async () => {
|
|
545
|
-
let serviceWorker
|
|
546
|
-
if (this.tokens != null) {
|
|
547
|
-
return false;
|
|
548
|
-
}
|
|
549
|
-
this.publishEvent(eventNames.tryKeepExistingSessionAsync_begin, {});
|
|
550
|
-
try {
|
|
551
|
-
const configuration = this.configuration;
|
|
552
|
-
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
553
|
-
serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
554
|
-
if (serviceWorker) {
|
|
555
|
-
const {tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "tryKeepExistingSessionAsync");
|
|
556
|
-
if (tokens) {
|
|
557
|
-
serviceWorker.startKeepAliveServiceWorker();
|
|
558
|
-
// @ts-ignore
|
|
559
|
-
this.tokens = tokens;
|
|
560
|
-
// @ts-ignore
|
|
561
|
-
this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt);
|
|
562
|
-
const sessionState = await serviceWorker.getSessionStateAsync();
|
|
563
|
-
// @ts-ignore
|
|
564
|
-
await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
|
|
565
|
-
this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
|
|
566
|
-
success: true,
|
|
567
|
-
message: "tokens inside ServiceWorker are valid"
|
|
568
|
-
});
|
|
569
|
-
return true;
|
|
570
|
-
}
|
|
571
|
-
this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
|
|
572
|
-
success: false,
|
|
573
|
-
message: "no exiting session found"
|
|
574
|
-
});
|
|
575
|
-
} else {
|
|
576
|
-
if (configuration.service_worker_relative_url) {
|
|
577
|
-
this.publishEvent(eventNames.service_worker_not_supported_by_browser, {
|
|
578
|
-
message: "service worker is not supported by this browser"
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
const session = initSession(this.configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
|
|
582
|
-
const {tokens} = await session.initAsync();
|
|
583
|
-
if (tokens) {
|
|
584
|
-
// @ts-ignore
|
|
585
|
-
this.tokens = setTokens(tokens);
|
|
586
|
-
// @ts-ignore
|
|
587
|
-
this.timeoutId = autoRenewTokens(this, tokens.refreshToken, this.tokens.expiresAt);
|
|
588
|
-
const sessionState = session.getSessionState();
|
|
589
|
-
// @ts-ignore
|
|
590
|
-
await this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, configuration.client_id, sessionState);
|
|
591
|
-
this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
|
|
592
|
-
success: true,
|
|
593
|
-
message: `tokens inside storage are valid`
|
|
594
|
-
});
|
|
595
|
-
return true;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
this.publishEvent(eventNames.tryKeepExistingSessionAsync_end, {
|
|
599
|
-
success: false,
|
|
600
|
-
message: serviceWorker ? "service worker sessions not retrieved" : "session storage sessions not retrieved"
|
|
601
|
-
});
|
|
602
|
-
return false;
|
|
603
|
-
} catch (exception) {
|
|
604
|
-
console.error(exception);
|
|
605
|
-
if (serviceWorker) {
|
|
606
|
-
await serviceWorker.clearAsync();
|
|
607
|
-
}
|
|
608
|
-
this.publishEvent(eventNames.tryKeepExistingSessionAsync_error, "tokens inside ServiceWorker are invalid");
|
|
609
|
-
return false;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
this.tryKeepExistingSessionPromise = funcAsync();
|
|
614
|
-
return this.tryKeepExistingSessionPromise.then((result) => {
|
|
615
|
-
this.tryKeepExistingSessionPromise =null;
|
|
616
|
-
return result;
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
loginPromise: Promise<any>=null;
|
|
621
|
-
async loginAsync(callbackPath:string=undefined, extras:StringMap=null, isSilentSignin:boolean=false, scope:string=undefined, silentLoginOnly = false) {
|
|
622
|
-
if(this.loginPromise !== null){
|
|
623
|
-
return this.loginPromise;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
const loginLocalAsync=async () => {
|
|
627
|
-
|
|
628
|
-
const location = window.location;
|
|
629
|
-
const url = callbackPath || location.pathname + (location.search || '') + (location.hash || '');
|
|
630
|
-
|
|
631
|
-
const configuration = this.configuration;
|
|
632
|
-
let state = undefined;
|
|
633
|
-
if(extras && "state" in extras){
|
|
634
|
-
state = extras["state"];
|
|
635
|
-
delete extras["state"];
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
if(silentLoginOnly){
|
|
640
|
-
try {
|
|
641
|
-
const extraFinal = extras ?? configuration.extras ?? {};
|
|
642
|
-
const silentResult = await this.silentLoginAsync({
|
|
643
|
-
...extraFinal,
|
|
644
|
-
prompt: "none"
|
|
645
|
-
}, state, scope);
|
|
646
|
-
|
|
647
|
-
if (silentResult) {
|
|
648
|
-
this.tokens = silentResult.tokens;
|
|
649
|
-
this.publishEvent(eventNames.token_aquired, {});
|
|
650
|
-
// @ts-ignore
|
|
651
|
-
this.timeoutId = autoRenewTokens(this, this.tokens.refreshToken, this.tokens.expiresAt, extras);
|
|
652
|
-
return {};
|
|
653
|
-
}
|
|
654
|
-
}catch (e) {
|
|
655
|
-
return e;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
this.publishEvent(eventNames.loginAsync_begin, {});
|
|
659
|
-
try {
|
|
660
|
-
const redirectUri = isSilentSignin ? configuration.silent_redirect_uri : configuration.redirect_uri;
|
|
661
|
-
if (!scope) {
|
|
662
|
-
scope = configuration.scope;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
const randomString = function(length) {
|
|
666
|
-
let text = "";
|
|
667
|
-
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
668
|
-
for(let i = 0; i < length; i++) {
|
|
669
|
-
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
670
|
-
}
|
|
671
|
-
return text;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
setLoginParams(this.configurationName, redirectUri, {callbackPath: url, extras, state});
|
|
675
|
-
const extraFinal = extras ?? configuration.extras ?? {};
|
|
676
|
-
if(!extraFinal.nonce) {
|
|
677
|
-
extraFinal["nonce"] = randomString(12);
|
|
678
|
-
}
|
|
679
|
-
const nonce = {"nonce":extraFinal.nonce};
|
|
680
|
-
let serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
681
|
-
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
682
|
-
let storage;
|
|
683
|
-
if (serviceWorker) {
|
|
684
|
-
serviceWorker.startKeepAliveServiceWorker();
|
|
685
|
-
await serviceWorker.initAsync(oidcServerConfiguration, "loginAsync");
|
|
686
|
-
await serviceWorker.setNonceAsync(nonce);
|
|
687
|
-
storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, {});
|
|
688
|
-
await storage.setItem("dummy", {});
|
|
689
|
-
|
|
690
|
-
} else {
|
|
691
|
-
const session = initSession(this.configurationName, redirectUri);
|
|
692
|
-
await session.setNonceAsync(nonce);
|
|
693
|
-
storage = new MemoryStorageBackend(session.saveItemsAsync, {});
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
// @ts-ignore
|
|
698
|
-
const queryStringUtil = redirectUri.includes("#") ? new HashQueryStringUtils() : new NoHashQueryStringUtils();
|
|
699
|
-
const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location, new DefaultCrypto());
|
|
700
|
-
const authRequest = new AuthorizationRequest({
|
|
701
|
-
client_id: configuration.client_id,
|
|
702
|
-
redirect_uri: redirectUri,
|
|
703
|
-
scope,
|
|
704
|
-
response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
|
|
705
|
-
state,
|
|
706
|
-
extras: extraFinal
|
|
707
|
-
});
|
|
708
|
-
authorizationHandler.performAuthorizationRequest(oidcServerConfiguration, authRequest);
|
|
709
|
-
} catch (exception) {
|
|
710
|
-
this.publishEvent(eventNames.loginAsync_error, exception);
|
|
711
|
-
throw exception;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
this.loginPromise = loginLocalAsync();
|
|
715
|
-
return this.loginPromise.then(result =>{
|
|
716
|
-
this.loginPromise = null;
|
|
717
|
-
return result;
|
|
718
|
-
});
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
async startCheckSessionAsync(checkSessionIFrameUri, clientId, sessionState, isSilentSignin=false){
|
|
722
|
-
return new Promise((resolve:Function, reject) => {
|
|
723
|
-
if (this.configuration.silent_login_uri && this.configuration.silent_redirect_uri && this.configuration.monitor_session && checkSessionIFrameUri && sessionState && !isSilentSignin) {
|
|
724
|
-
const checkSessionCallback = () => {
|
|
725
|
-
this.checkSessionIFrame.stop();
|
|
726
|
-
|
|
727
|
-
if(this.tokens === null){
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
730
|
-
// @ts-ignore
|
|
731
|
-
const idToken = this.tokens.idToken;
|
|
732
|
-
// @ts-ignore
|
|
733
|
-
const idTokenPayload = this.tokens.idTokenPayload;
|
|
734
|
-
this.silentLoginAsync({
|
|
735
|
-
prompt: "none",
|
|
736
|
-
id_token_hint: idToken,
|
|
737
|
-
scope: "openid"
|
|
738
|
-
}).then((silentSigninResponse) => {
|
|
739
|
-
const iFrameIdTokenPayload = silentSigninResponse.tokens.idTokenPayload;
|
|
740
|
-
if (idTokenPayload.sub === iFrameIdTokenPayload.sub) {
|
|
741
|
-
const sessionState = silentSigninResponse.sessionState;
|
|
742
|
-
this.checkSessionIFrame.start(silentSigninResponse.sessionState);
|
|
743
|
-
if (idTokenPayload.sid === iFrameIdTokenPayload.sid) {
|
|
744
|
-
console.debug("SessionMonitor._callback: Same sub still logged in at OP, restarting check session iframe; session_state:", sessionState);
|
|
745
|
-
} else {
|
|
746
|
-
console.debug("SessionMonitor._callback: Same sub still logged in at OP, session state has changed, restarting check session iframe; session_state:", sessionState);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
else {
|
|
750
|
-
console.debug("SessionMonitor._callback: Different subject signed into OP:", iFrameIdTokenPayload.sub);
|
|
751
|
-
}
|
|
752
|
-
}).catch(async (e) => {
|
|
753
|
-
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
754
|
-
//if(oidc !== this) {
|
|
755
|
-
// @ts-ignore
|
|
756
|
-
await oidc.logoutOtherTabAsync(this.configuration.client_id, idTokenPayload.sub);
|
|
757
|
-
//}
|
|
758
|
-
}
|
|
759
|
-
//await this.destroyAsync();
|
|
760
|
-
//this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor"});
|
|
761
|
-
|
|
762
|
-
});
|
|
763
|
-
};
|
|
764
|
-
|
|
765
|
-
this.checkSessionIFrame = new CheckSessionIFrame(checkSessionCallback, clientId, checkSessionIFrameUri);
|
|
766
|
-
this.checkSessionIFrame.load().then(() => {
|
|
767
|
-
this.checkSessionIFrame.start(sessionState);
|
|
768
|
-
resolve();
|
|
769
|
-
}).catch((e) =>{
|
|
770
|
-
reject(e);
|
|
771
|
-
});
|
|
772
|
-
} else {
|
|
773
|
-
resolve();
|
|
774
|
-
}
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
loginCallbackPromise : Promise<any>=null
|
|
779
|
-
async loginCallbackAsync(isSilenSignin:boolean=false){
|
|
780
|
-
if(this.loginCallbackPromise !== null){
|
|
781
|
-
return this.loginCallbackPromise;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
const loginCallbackLocalAsync= async( ) =>{
|
|
785
|
-
const response = await this._loginCallbackAsync(isSilenSignin);
|
|
786
|
-
// @ts-ignore
|
|
787
|
-
const tokens = response.tokens;
|
|
788
|
-
const parsedTokens = setTokens(tokens);
|
|
789
|
-
this.tokens = parsedTokens;
|
|
790
|
-
const oidc = this;
|
|
791
|
-
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName);
|
|
792
|
-
if (!serviceWorker) {
|
|
793
|
-
const session = initSession(this.configurationName, oidc.configuration.redirect_uri, oidc.configuration.storage);
|
|
794
|
-
await session.setTokens(parsedTokens);
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
this.publishEvent(Oidc.eventNames.token_aquired, parsedTokens);
|
|
798
|
-
// @ts-ignore
|
|
799
|
-
return { parsedTokens, state:response.state, callbackPath : response.callbackPath};
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
this.loginCallbackPromise = loginCallbackLocalAsync();
|
|
803
|
-
return this.loginCallbackPromise.then(result =>{
|
|
804
|
-
this.loginCallbackPromise = null;
|
|
805
|
-
return result;
|
|
806
|
-
})
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
async _loginCallbackAsync(isSilentSignin:boolean=false){
|
|
810
|
-
try {
|
|
811
|
-
this.publishEvent(eventNames.loginCallbackAsync_begin, {});
|
|
812
|
-
const configuration = this.configuration;
|
|
813
|
-
const clientId = configuration.client_id;
|
|
814
|
-
const redirectUri = isSilentSignin ? configuration.silent_redirect_uri : configuration.redirect_uri;
|
|
815
|
-
const authority = configuration.authority;
|
|
816
|
-
const tokenRequestTimeout = configuration.token_request_timeout;
|
|
817
|
-
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
818
|
-
const queryParams = getParseQueryStringFromLocation(window.location.href);
|
|
819
|
-
const sessionState = queryParams.session_state;
|
|
820
|
-
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, this.configurationName);
|
|
821
|
-
let storage = null;
|
|
822
|
-
let nonceData = null;
|
|
823
|
-
if(serviceWorker){
|
|
824
|
-
serviceWorker.startKeepAliveServiceWorker();
|
|
825
|
-
await serviceWorker.initAsync(oidcServerConfiguration, "loginCallbackAsync");
|
|
826
|
-
const items = await serviceWorker.loadItemsAsync();
|
|
827
|
-
storage = new MemoryStorageBackend(serviceWorker.saveItemsAsync, items);
|
|
828
|
-
const dummy =await storage.getItem("dummy");
|
|
829
|
-
if(!dummy){
|
|
830
|
-
throw new Error("Service Worker storage disapear");
|
|
831
|
-
}
|
|
832
|
-
await storage.removeItem("dummy");
|
|
833
|
-
await serviceWorker.setSessionStateAsync(sessionState);
|
|
834
|
-
nonceData = await serviceWorker.getNonceAsync();
|
|
835
|
-
}else{
|
|
836
|
-
const session = initSession(this.configurationName, redirectUri);
|
|
837
|
-
session.setSessionState(sessionState);
|
|
838
|
-
const items = await session.loadItemsAsync();
|
|
839
|
-
storage = new MemoryStorageBackend(session.saveItemsAsync, items);
|
|
840
|
-
nonceData = await session.getNonceAsync();
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
return new Promise((resolve, reject) => {
|
|
844
|
-
// @ts-ignore
|
|
845
|
-
let queryStringUtil = new NoHashQueryStringUtils();
|
|
846
|
-
if(redirectUri.includes("#")) {
|
|
847
|
-
const splithash = window.location.href.split("#");
|
|
848
|
-
if (splithash.length === 2 && splithash[1].includes("?")) {
|
|
849
|
-
queryStringUtil = new HashQueryStringUtils();
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
// @ts-ignore
|
|
853
|
-
const authorizationHandler = new RedirectRequestHandler(storage, queryStringUtil, window.location , new DefaultCrypto());
|
|
854
|
-
const notifier = new AuthorizationNotifier();
|
|
855
|
-
authorizationHandler.setAuthorizationNotifier(notifier);
|
|
856
|
-
|
|
857
|
-
notifier.setAuthorizationListener( (request, response, error) => {
|
|
858
|
-
if (error) {
|
|
859
|
-
reject(error);
|
|
860
|
-
return;
|
|
861
|
-
}
|
|
862
|
-
if (!response) {
|
|
863
|
-
reject("no response");
|
|
864
|
-
return;
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
let extras = null;
|
|
868
|
-
if (request && request.internal) {
|
|
869
|
-
extras = {};
|
|
870
|
-
extras.code_verifier = request.internal.code_verifier;
|
|
871
|
-
if (configuration.token_request_extras) {
|
|
872
|
-
for (let [key, value] of Object.entries(configuration.token_request_extras)) {
|
|
873
|
-
extras[key] = value;
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
const tokenRequest = new TokenRequest({
|
|
879
|
-
client_id: clientId,
|
|
880
|
-
redirect_uri: redirectUri,
|
|
881
|
-
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
|
|
882
|
-
code: response.code,
|
|
883
|
-
refresh_token: undefined,
|
|
884
|
-
extras,
|
|
885
|
-
});
|
|
886
|
-
|
|
887
|
-
let timeoutId = setTimeout(()=>{
|
|
888
|
-
reject("performTokenRequest timeout");
|
|
889
|
-
timeoutId=null;
|
|
890
|
-
}, tokenRequestTimeout ?? 12000);
|
|
891
|
-
try {
|
|
892
|
-
const tokenHandler = new BaseTokenRequestHandler(new FetchRequestor());
|
|
893
|
-
tokenHandler.performTokenRequest(oidcServerConfiguration, tokenRequest).then(async (tokenResponse) => {
|
|
894
|
-
if (timeoutId) {
|
|
895
|
-
clearTimeout(timeoutId);
|
|
896
|
-
this.timeoutId = null;
|
|
897
|
-
const loginParams = getLoginParams(this.configurationName, redirectUri);
|
|
898
|
-
|
|
899
|
-
if (serviceWorker) {
|
|
900
|
-
const {tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
|
|
901
|
-
tokenResponse = tokens;
|
|
902
|
-
}
|
|
903
|
-
if(!isTokensOidcValid(tokenResponse, nonceData.nonce, oidcServerConfiguration)){
|
|
904
|
-
const exception = new Error("Tokens are not OpenID valid");
|
|
905
|
-
if(timeoutId) {
|
|
906
|
-
clearTimeout(timeoutId);
|
|
907
|
-
this.timeoutId=null;
|
|
908
|
-
this.publishEvent(eventNames.loginCallbackAsync_error, exception);
|
|
909
|
-
console.error(exception);
|
|
910
|
-
reject(exception);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// @ts-ignore
|
|
915
|
-
this.startCheckSessionAsync(oidcServerConfiguration.check_session_iframe, clientId, sessionState, isSilentSignin).then(() => {
|
|
916
|
-
this.publishEvent(eventNames.loginCallbackAsync_end, {});
|
|
917
|
-
resolve({
|
|
918
|
-
tokens: tokenResponse,
|
|
919
|
-
state: request.state,
|
|
920
|
-
callbackPath: loginParams.callbackPath,
|
|
921
|
-
});
|
|
922
|
-
});
|
|
923
|
-
}
|
|
924
|
-
});
|
|
925
|
-
} catch (exception) {
|
|
926
|
-
if(timeoutId) {
|
|
927
|
-
clearTimeout(timeoutId);
|
|
928
|
-
this.timeoutId=null;
|
|
929
|
-
this.publishEvent(eventNames.loginCallbackAsync_error, exception);
|
|
930
|
-
console.error(exception);
|
|
931
|
-
reject(exception);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
});
|
|
935
|
-
authorizationHandler.completeAuthorizationRequestIfPossible();
|
|
936
|
-
});
|
|
937
|
-
} catch(exception) {
|
|
938
|
-
console.error(exception);
|
|
939
|
-
this.publishEvent(eventNames.loginCallbackAsync_error, exception);
|
|
940
|
-
throw exception;
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
async synchroniseTokensAsync(refreshToken, index=0, forceRefresh =false, extras:StringMap=null) {
|
|
945
|
-
|
|
946
|
-
if (document.hidden) {
|
|
947
|
-
await sleepAsync(1000);
|
|
948
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message: "wait because document is hidden"});
|
|
949
|
-
return await this.synchroniseTokensAsync(refreshToken, index, forceRefresh);
|
|
950
|
-
}
|
|
951
|
-
let numberTryOnline = 6;
|
|
952
|
-
while (!navigator.onLine && numberTryOnline > 0) {
|
|
953
|
-
await sleepAsync(1000);
|
|
954
|
-
numberTryOnline--;
|
|
955
|
-
this.publishEvent(eventNames.refreshTokensAsync, {message: `wait because navigator is offline try ${numberTryOnline}` });
|
|
956
|
-
}
|
|
957
|
-
if(!extras){
|
|
958
|
-
extras = {}
|
|
959
|
-
}
|
|
960
|
-
const configuration = this.configuration;
|
|
961
|
-
const localsilentLoginAsync= async () => {
|
|
962
|
-
try {
|
|
963
|
-
const loginParams = getLoginParams(this.configurationName, configuration.redirect_uri);
|
|
964
|
-
|
|
965
|
-
const silent_token_response = await this.silentLoginAsync({
|
|
966
|
-
...loginParams.extras,
|
|
967
|
-
...extras,
|
|
968
|
-
prompt: "none"
|
|
969
|
-
}, loginParams.state);
|
|
970
|
-
if (silent_token_response) {
|
|
971
|
-
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
972
|
-
return {tokens:silent_token_response.tokens, status:"LOGGED"};
|
|
973
|
-
}
|
|
974
|
-
} catch (exceptionSilent) {
|
|
975
|
-
console.error(exceptionSilent);
|
|
976
|
-
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exceptionSilent" ,exception: exceptionSilent.message});
|
|
977
|
-
if(exceptionSilent && exceptionSilent.message && exceptionSilent.message.startsWith("oidc")){
|
|
978
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent` });
|
|
979
|
-
return {tokens:null, status:"SESSION_LOST"};
|
|
980
|
-
}
|
|
981
|
-
await sleepAsync(1000);
|
|
982
|
-
throw exceptionSilent;
|
|
983
|
-
}
|
|
984
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token silent return` });
|
|
985
|
-
return {tokens:null, status:"SESSION_LOST"};
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
if (index <=4) {
|
|
989
|
-
try {
|
|
990
|
-
const { status, tokens, nonce } = await this.syncTokensInfoAsync(configuration, this.configurationName, this.tokens, forceRefresh);
|
|
991
|
-
switch (status) {
|
|
992
|
-
case "SESSION_LOST":
|
|
993
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token session lost` });
|
|
994
|
-
return {tokens:null, status:"SESSION_LOST"};
|
|
995
|
-
case "NOT_CONNECTED":
|
|
996
|
-
return {tokens:null, status:null};
|
|
997
|
-
case "TOKENS_VALID":
|
|
998
|
-
return {tokens, status:"LOGGED_IN"};
|
|
999
|
-
case "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID":
|
|
1000
|
-
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
1001
|
-
return {tokens, status:"LOGGED_IN"};
|
|
1002
|
-
case "LOGOUT_FROM_ANOTHER_TAB":
|
|
1003
|
-
this.publishEvent(eventNames.logout_from_another_tab, {"status": "session syncTokensAsync"});
|
|
1004
|
-
return {tokens:null, status:"LOGGED_OUT"};
|
|
1005
|
-
case "REQUIRE_SYNC_TOKENS":
|
|
1006
|
-
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
|
|
1007
|
-
return await localsilentLoginAsync();
|
|
1008
|
-
default:
|
|
1009
|
-
if(!refreshToken)
|
|
1010
|
-
{
|
|
1011
|
-
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, tryNumber: index});
|
|
1012
|
-
return await localsilentLoginAsync();
|
|
1013
|
-
}
|
|
1014
|
-
this.publishEvent(eventNames.refreshTokensAsync_begin, {refreshToken:refreshToken, status, tryNumber: index});
|
|
1015
|
-
const clientId = configuration.client_id;
|
|
1016
|
-
const redirectUri = configuration.redirect_uri;
|
|
1017
|
-
const authority = configuration.authority;
|
|
1018
|
-
const tokenExtras = configuration.token_request_extras ? configuration.token_request_extras : {};
|
|
1019
|
-
let finalExtras = {...tokenExtras, ...extras};
|
|
1020
|
-
|
|
1021
|
-
const details = {
|
|
1022
|
-
client_id: clientId,
|
|
1023
|
-
redirect_uri: redirectUri,
|
|
1024
|
-
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
1025
|
-
refresh_token: tokens.refreshToken,
|
|
1026
|
-
};
|
|
1027
|
-
const oidcServerConfiguration = await this.initAsync(authority, configuration.authority_configuration);
|
|
1028
|
-
const tokenResponse = await performTokenRequestAsync(oidcServerConfiguration.tokenEndpoint, details, finalExtras, tokens);
|
|
1029
|
-
if (tokenResponse.success) {
|
|
1030
|
-
if(!isTokensOidcValid(tokenResponse.data, nonce.nonce, oidcServerConfiguration)){
|
|
1031
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token return not valid tokens` });
|
|
1032
|
-
return {tokens:null, status:"SESSION_LOST"};
|
|
1033
|
-
}
|
|
1034
|
-
this.publishEvent(eventNames.refreshTokensAsync_end, {success: tokenResponse.success});
|
|
1035
|
-
this.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
1036
|
-
return {tokens: tokenResponse.data, status:"LOGGED_IN"};
|
|
1037
|
-
} else {
|
|
1038
|
-
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
1039
|
-
message: "bad request",
|
|
1040
|
-
tokenResponse: tokenResponse
|
|
1041
|
-
});
|
|
1042
|
-
return await this.synchroniseTokensAsync(null, index+1, forceRefresh);
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
} catch (exception) {
|
|
1046
|
-
console.error(exception);
|
|
1047
|
-
this.publishEvent(eventNames.refreshTokensAsync_silent_error, {message: "exception" ,exception: exception.message});
|
|
1048
|
-
return this.synchroniseTokensAsync(refreshToken, index+1, forceRefresh);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
this.publishEvent(eventNames.refreshTokensAsync_error, {message: `refresh token` });
|
|
1053
|
-
return {tokens:null, status:"SESSION_LOST"};
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
async syncTokensInfoAsync(configuration, configurationName, currentTokens, forceRefresh =false) {
|
|
1057
|
-
// 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)
|
|
1058
|
-
//const configuration = this.configuration;
|
|
1059
|
-
const nullNonce = { nonce:null };
|
|
1060
|
-
if (!currentTokens) {
|
|
1061
|
-
return { tokens : null, status: "NOT_CONNECTED", nonce: nullNonce};
|
|
1062
|
-
}
|
|
1063
|
-
let nonce = nullNonce;
|
|
1064
|
-
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
1065
|
-
const serviceWorker = await initWorkerAsync(configuration.service_worker_relative_url, configurationName);
|
|
1066
|
-
if (serviceWorker) {
|
|
1067
|
-
const {status, tokens} = await serviceWorker.initAsync(oidcServerConfiguration, "syncTokensAsync");
|
|
1068
|
-
if (status == "LOGGED_OUT") {
|
|
1069
|
-
return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB", nonce: nullNonce};
|
|
1070
|
-
}else if (status == "SESSIONS_LOST") {
|
|
1071
|
-
return { tokens : null, status: "SESSIONS_LOST", nonce: nullNonce};
|
|
1072
|
-
} else if (!status || !tokens) {
|
|
1073
|
-
return { tokens : null, status: "REQUIRE_SYNC_TOKENS", nonce: nullNonce};
|
|
1074
|
-
} else if(tokens.issuedAt !== currentTokens.issuedAt) {
|
|
1075
|
-
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
|
|
1076
|
-
const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
|
|
1077
|
-
const nonce = await serviceWorker.getNonceAsync();
|
|
1078
|
-
return { tokens : tokens, status, nonce};
|
|
1079
|
-
}
|
|
1080
|
-
nonce = await serviceWorker.getNonceAsync();
|
|
1081
|
-
} else {
|
|
1082
|
-
const session = initSession(configurationName, configuration.redirect_uri, configuration.storage ?? sessionStorage);
|
|
1083
|
-
const { tokens, status } = await session.initAsync();
|
|
1084
|
-
if (!tokens) {
|
|
1085
|
-
return {tokens: null, status: "LOGOUT_FROM_ANOTHER_TAB", nonce: nullNonce};
|
|
1086
|
-
} else if (status == "SESSIONS_LOST") {
|
|
1087
|
-
return { tokens : null, status: "SESSIONS_LOST", nonce: nullNonce};
|
|
1088
|
-
}
|
|
1089
|
-
else if(tokens.issuedAt !== currentTokens.issuedAt){
|
|
1090
|
-
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, tokens.expiresAt);
|
|
1091
|
-
const status = (timeLeft > 0) ? "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID" : "TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID";
|
|
1092
|
-
const nonce = await session.getNonceAsync();
|
|
1093
|
-
return { tokens : tokens, status , nonce };
|
|
1094
|
-
}
|
|
1095
|
-
nonce = await session.getNonceAsync();
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
const timeLeft = computeTimeLeft(configuration.refresh_time_before_tokens_expiration_in_second, currentTokens.expiresAt);
|
|
1099
|
-
const status = (timeLeft > 0) ? "TOKENS_VALID" : "TOKENS_INVALID";
|
|
1100
|
-
if(forceRefresh){
|
|
1101
|
-
return { tokens:currentTokens, status:"FORCE_REFRESH", nonce};
|
|
1102
|
-
}
|
|
1103
|
-
return { tokens:currentTokens, status, nonce};
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
loginCallbackWithAutoTokensRenewPromise:Promise<loginCallbackResult> = null;
|
|
1107
|
-
loginCallbackWithAutoTokensRenewAsync():Promise<loginCallbackResult>{
|
|
1108
|
-
if(this.loginCallbackWithAutoTokensRenewPromise !== null){
|
|
1109
|
-
return this.loginCallbackWithAutoTokensRenewPromise;
|
|
1110
|
-
}
|
|
1111
|
-
this.loginCallbackWithAutoTokensRenewPromise = loginCallbackWithAutoTokensRenewAsync(this);
|
|
1112
|
-
return this.loginCallbackWithAutoTokensRenewPromise.then(result =>{
|
|
1113
|
-
this.loginCallbackWithAutoTokensRenewPromise = null;
|
|
1114
|
-
return result;
|
|
1115
|
-
})
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
userInfoPromise:Promise<any> = null;
|
|
1119
|
-
userInfoAsync(){
|
|
1120
|
-
if(this.userInfoPromise !== null){
|
|
1121
|
-
return this.userInfoPromise;
|
|
1122
|
-
}
|
|
1123
|
-
this.userInfoPromise = userInfoAsync(this);
|
|
1124
|
-
return this.userInfoPromise.then(result =>{
|
|
1125
|
-
this.userInfoPromise = null;
|
|
1126
|
-
return result;
|
|
1127
|
-
})
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
async renewTokensAsync (extras:StringMap=null){
|
|
1131
|
-
if(!this.timeoutId){
|
|
1132
|
-
return;
|
|
1133
|
-
}
|
|
1134
|
-
timer.clearTimeout(this.timeoutId);
|
|
1135
|
-
// @ts-ignore
|
|
1136
|
-
await renewTokensAndStartTimerAsync(this, this.tokens.refreshToken, true, extras);
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
async destroyAsync(status) {
|
|
1140
|
-
timer.clearTimeout(this.timeoutId);
|
|
1141
|
-
this.timeoutId=null;
|
|
1142
|
-
if(this.checkSessionIFrame){
|
|
1143
|
-
this.checkSessionIFrame.stop();
|
|
1144
|
-
}
|
|
1145
|
-
const oidc = this;
|
|
1146
|
-
const serviceWorker = await initWorkerAsync(oidc.configuration.service_worker_relative_url, oidc.configurationName);
|
|
1147
|
-
if (!serviceWorker) {
|
|
1148
|
-
const session = initSession(this.configurationName, oidc.configuration.redirect_uri, oidc.configuration.storage);
|
|
1149
|
-
await session.clearAsync(status);
|
|
1150
|
-
} else{
|
|
1151
|
-
await serviceWorker.clearAsync(status);
|
|
1152
|
-
}
|
|
1153
|
-
this.tokens = null;
|
|
1154
|
-
this.userInfo = null;
|
|
1155
|
-
// this.events = [];
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
async logoutSameTabAsync(clientId, sub){
|
|
1159
|
-
// @ts-ignore
|
|
1160
|
-
if(this.configuration.monitor_session&& this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1161
|
-
this.publishEvent(eventNames.logout_from_same_tab, {"message": sub});
|
|
1162
|
-
await this.destroyAsync("LOGGED_OUT");
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
async logoutOtherTabAsync(clientId, sub){
|
|
1167
|
-
// @ts-ignore
|
|
1168
|
-
if(this.configuration.monitor_session && this.configuration.client_id === clientId && sub && this.tokens && this.tokens.idTokenPayload && this.tokens.idTokenPayload.sub === sub) {
|
|
1169
|
-
await this.destroyAsync("LOGGED_OUT");
|
|
1170
|
-
this.publishEvent(eventNames.logout_from_another_tab, {message : "SessionMonitor", "sub": sub});
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
async logoutAsync(callbackPathOrUrl: string | null | undefined = undefined, extras: StringMap = null) {
|
|
1175
|
-
const configuration = this.configuration;
|
|
1176
|
-
const oidcServerConfiguration = await this.initAsync(configuration.authority, configuration.authority_configuration);
|
|
1177
|
-
if(callbackPathOrUrl && (typeof callbackPathOrUrl !== 'string'))
|
|
1178
|
-
{
|
|
1179
|
-
callbackPathOrUrl = undefined;
|
|
1180
|
-
console.warn('callbackPathOrUrl path is not a string');
|
|
1181
|
-
}
|
|
1182
|
-
const path = (callbackPathOrUrl === null || callbackPathOrUrl === undefined) ? location.pathname + (location.search || '') + (location.hash || '') : callbackPathOrUrl;
|
|
1183
|
-
let isUri = false;
|
|
1184
|
-
if(callbackPathOrUrl) {
|
|
1185
|
-
isUri = callbackPathOrUrl.includes("https://") || callbackPathOrUrl.includes("http://");
|
|
1186
|
-
}
|
|
1187
|
-
const url = isUri ? callbackPathOrUrl : window.location.origin + path;
|
|
1188
|
-
// @ts-ignore
|
|
1189
|
-
const idToken = this.tokens ? this.tokens.idToken : "";
|
|
1190
|
-
// @ts-ignore
|
|
1191
|
-
const sub = this.tokens && this.tokens.idTokenPayload ? this.tokens.idTokenPayload.sub : null;
|
|
1192
|
-
await this.destroyAsync("LOGGED_OUT");
|
|
1193
|
-
for (const [key, oidc] of Object.entries(oidcDatabase)) {
|
|
1194
|
-
if(oidc !== this) {
|
|
1195
|
-
// @ts-ignore
|
|
1196
|
-
await oidc.logoutSameTabAsync(this.configuration.client_id, sub);
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
if(oidcServerConfiguration.endSessionEndpoint) {
|
|
1201
|
-
if(!extras){
|
|
1202
|
-
extras= {
|
|
1203
|
-
id_token_hint: idToken
|
|
1204
|
-
};
|
|
1205
|
-
if(callbackPathOrUrl !== null){
|
|
1206
|
-
extras["post_logout_redirect_uri"] = url;
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
let queryString = "";
|
|
1210
|
-
if(extras){
|
|
1211
|
-
for (let [key, value] of Object.entries(extras)) {
|
|
1212
|
-
if(queryString === "")
|
|
1213
|
-
{
|
|
1214
|
-
queryString += "?";
|
|
1215
|
-
} else{
|
|
1216
|
-
queryString += "&";
|
|
1217
|
-
}
|
|
1218
|
-
queryString +=`${key}=${encodeURIComponent(value)}`;
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
window.location.href = `${oidcServerConfiguration.endSessionEndpoint}${queryString}`;
|
|
1222
|
-
}
|
|
1223
|
-
else{
|
|
1224
|
-
window.location.reload();
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
export default Oidc;
|