@axa-fr/oidc-client 7.22.18 → 7.22.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -39
- package/bin/copy-service-worker-files.mjs +24 -17
- package/dist/OidcTrustedDomains.js +14 -12
- package/dist/cache.d.ts.map +1 -1
- package/dist/checkSession.d.ts +1 -1
- package/dist/checkSession.d.ts.map +1 -1
- package/dist/checkSessionIFrame.d.ts.map +1 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/fetch.d.ts +2 -1
- package/dist/fetch.d.ts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +935 -601
- package/dist/index.umd.cjs +2 -2
- package/dist/initSession.d.ts +1 -1
- package/dist/initSession.d.ts.map +1 -1
- package/dist/initWorker.d.ts +2 -2
- package/dist/initWorker.d.ts.map +1 -1
- package/dist/initWorkerOption.d.ts.map +1 -1
- package/dist/jwt.d.ts +2 -2
- package/dist/jwt.d.ts.map +1 -1
- package/dist/keepSession.d.ts.map +1 -1
- package/dist/location.d.ts.map +1 -1
- package/dist/login.d.ts +1 -1
- package/dist/login.d.ts.map +1 -1
- package/dist/logout.d.ts +1 -1
- package/dist/logout.d.ts.map +1 -1
- package/dist/oidc.d.ts +1 -1
- package/dist/oidc.d.ts.map +1 -1
- package/dist/oidcClient.d.ts +2 -2
- package/dist/oidcClient.d.ts.map +1 -1
- package/dist/parseTokens.d.ts.map +1 -1
- package/dist/renewTokens.d.ts.map +1 -1
- package/dist/requests.d.ts +1 -1
- package/dist/requests.d.ts.map +1 -1
- package/dist/silentLogin.d.ts.map +1 -1
- package/dist/timer.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/user.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/cache.ts +21 -18
- package/src/checkSession.ts +89 -54
- package/src/checkSessionIFrame.ts +70 -69
- package/src/crypto.ts +27 -25
- package/src/events.ts +28 -28
- package/src/fetch.ts +40 -21
- package/src/index.ts +6 -17
- package/src/iniWorker.spec.ts +26 -16
- package/src/initSession.ts +115 -113
- package/src/initWorker.ts +299 -212
- package/src/initWorkerOption.ts +121 -114
- package/src/jwt.ts +150 -136
- package/src/keepSession.ts +100 -81
- package/src/location.ts +24 -26
- package/src/login.ts +246 -189
- package/src/logout.spec.ts +131 -76
- package/src/logout.ts +130 -115
- package/src/oidc.ts +426 -337
- package/src/oidcClient.ts +129 -105
- package/src/parseTokens.spec.ts +198 -179
- package/src/parseTokens.ts +221 -186
- package/src/renewTokens.ts +397 -284
- package/src/requests.spec.ts +5 -7
- package/src/requests.ts +142 -114
- package/src/route-utils.spec.ts +17 -19
- package/src/route-utils.ts +29 -26
- package/src/silentLogin.ts +145 -127
- package/src/timer.ts +10 -11
- package/src/types.ts +56 -46
- package/src/user.ts +17 -12
- package/src/version.ts +1 -1
package/src/renewTokens.ts
CHANGED
|
@@ -1,339 +1,452 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { eventNames } from './events';
|
|
2
|
+
import { initSession } from './initSession.js';
|
|
3
|
+
import { initWorkerAsync, sleepAsync } from './initWorker.js';
|
|
3
4
|
import Oidc from './oidc.js';
|
|
4
|
-
import {computeTimeLeft, isTokensOidcValid, setTokens, Tokens} from './parseTokens.js';
|
|
5
|
+
import { computeTimeLeft, isTokensOidcValid, setTokens, Tokens } from './parseTokens.js';
|
|
6
|
+
import { performTokenRequestAsync } from './requests';
|
|
7
|
+
import { _silentLoginAsync } from './silentLogin';
|
|
5
8
|
import timer from './timer.js';
|
|
6
|
-
import {OidcConfiguration, StringMap, TokenAutomaticRenewMode} from './types.js';
|
|
7
|
-
import {_silentLoginAsync} from "./silentLogin";
|
|
8
|
-
import {performTokenRequestAsync} from "./requests";
|
|
9
|
-
import {eventNames} from "./events";
|
|
9
|
+
import { OidcConfiguration, StringMap, TokenAutomaticRenewMode } from './types.js';
|
|
10
10
|
|
|
11
|
-
async function syncTokens(oidc:Oidc, forceRefresh: boolean, extras: StringMap) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
async function syncTokens(oidc: Oidc, forceRefresh: boolean, extras: StringMap) {
|
|
12
|
+
const updateTokens = tokens => {
|
|
13
|
+
oidc.tokens = tokens;
|
|
14
|
+
};
|
|
15
|
+
const { tokens, status } = await synchroniseTokensAsync(oidc)(
|
|
16
|
+
0,
|
|
17
|
+
forceRefresh,
|
|
18
|
+
extras,
|
|
19
|
+
updateTokens,
|
|
20
|
+
);
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
const serviceWorker = await initWorkerAsync(oidc.configuration, oidc.configurationName);
|
|
23
|
+
if (!serviceWorker) {
|
|
24
|
+
const session = initSession(oidc.configurationName, oidc.configuration.storage);
|
|
25
|
+
await session.setTokens(oidc.tokens);
|
|
26
|
+
}
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
if (!oidc.tokens) {
|
|
29
|
+
await oidc.destroyAsync(status);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return tokens;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
const loadLatestTokensAsync = async (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
const loadLatestTokensAsync = async (
|
|
36
|
+
oidc: Oidc,
|
|
37
|
+
configuration: OidcConfiguration,
|
|
38
|
+
): Promise<Tokens> => {
|
|
39
|
+
const serviceWorker = await initWorkerAsync(configuration, oidc.configurationName);
|
|
40
|
+
if (serviceWorker) {
|
|
41
|
+
const oidcServerConfiguration = await oidc.initAsync(
|
|
42
|
+
configuration.authority,
|
|
43
|
+
configuration.authority_configuration,
|
|
44
|
+
);
|
|
45
|
+
const { tokens } = await serviceWorker.initAsync(
|
|
46
|
+
oidcServerConfiguration,
|
|
47
|
+
'tryKeepExistingSessionAsync',
|
|
48
|
+
configuration,
|
|
49
|
+
);
|
|
50
|
+
return tokens;
|
|
51
|
+
} else {
|
|
52
|
+
const session = initSession(oidc.configurationName, configuration.storage ?? sessionStorage);
|
|
53
|
+
let { tokens } = await session.initAsync();
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
tokens = setTokens(tokens, oidc.tokens, configuration.token_renew_mode);
|
|
56
|
+
return tokens;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
44
59
|
|
|
45
|
-
export async function renewTokensAndStartTimerAsync(
|
|
60
|
+
export async function renewTokensAndStartTimerAsync(
|
|
61
|
+
oidc,
|
|
62
|
+
forceRefresh = false,
|
|
63
|
+
extras: StringMap = null,
|
|
64
|
+
) {
|
|
65
|
+
const configuration = oidc.configuration;
|
|
66
|
+
const lockResourcesName = `${configuration.client_id}_${oidc.configurationName}_${configuration.authority}`;
|
|
46
67
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if(!lock){
|
|
58
|
-
oidc.publishEvent(Oidc.eventNames.syncTokensAsync_lock_not_available, { lock: 'lock not available' });
|
|
59
|
-
return await loadLatestTokensAsync(oidc, configuration);
|
|
60
|
-
}
|
|
61
|
-
return await syncTokens(oidc, forceRefresh, extras);
|
|
68
|
+
let tokens: null;
|
|
69
|
+
const serviceWorker = await initWorkerAsync(oidc.configuration, oidc.configurationName);
|
|
70
|
+
|
|
71
|
+
if (configuration?.storage === window?.sessionStorage && !serviceWorker) {
|
|
72
|
+
tokens = await syncTokens(oidc, forceRefresh, extras);
|
|
73
|
+
} else {
|
|
74
|
+
tokens = await navigator.locks.request(lockResourcesName, { ifAvailable: true }, async lock => {
|
|
75
|
+
if (!lock) {
|
|
76
|
+
oidc.publishEvent(Oidc.eventNames.syncTokensAsync_lock_not_available, {
|
|
77
|
+
lock: 'lock not available',
|
|
62
78
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
return await loadLatestTokensAsync(oidc, configuration);
|
|
80
|
+
}
|
|
81
|
+
return await syncTokens(oidc, forceRefresh, extras);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!tokens) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (oidc.timeoutId) {
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
oidc.timeoutId = autoRenewTokens(oidc, oidc.tokens.expiresAt, extras);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return oidc.tokens;
|
|
76
95
|
}
|
|
77
96
|
|
|
78
|
-
export const autoRenewTokens = (oidc:Oidc, expiresAt, extras:StringMap = null) => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
export const autoRenewTokens = (oidc: Oidc, expiresAt, extras: StringMap = null) => {
|
|
98
|
+
const refreshTimeBeforeTokensExpirationInSecond =
|
|
99
|
+
oidc.configuration.refresh_time_before_tokens_expiration_in_second;
|
|
100
|
+
return timer.setTimeout(async () => {
|
|
101
|
+
const timeLeft = computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt);
|
|
102
|
+
const timeInfo = { timeLeft };
|
|
103
|
+
oidc.publishEvent(Oidc.eventNames.token_timer, timeInfo);
|
|
104
|
+
await renewTokensAndStartTimerAsync(oidc, false, extras);
|
|
105
|
+
}, 1000);
|
|
86
106
|
};
|
|
87
107
|
|
|
88
|
-
export const synchroniseTokensStatus ={
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
export const synchroniseTokensStatus = {
|
|
109
|
+
FORCE_REFRESH: 'FORCE_REFRESH',
|
|
110
|
+
SESSION_LOST: 'SESSION_LOST',
|
|
111
|
+
NOT_CONNECTED: 'NOT_CONNECTED',
|
|
112
|
+
TOKENS_VALID: 'TOKENS_VALID',
|
|
113
|
+
TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID: 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID',
|
|
114
|
+
LOGOUT_FROM_ANOTHER_TAB: 'LOGOUT_FROM_ANOTHER_TAB',
|
|
115
|
+
REQUIRE_SYNC_TOKENS: 'REQUIRE_SYNC_TOKENS',
|
|
96
116
|
};
|
|
97
117
|
|
|
98
|
-
export const syncTokensInfoAsync =
|
|
118
|
+
export const syncTokensInfoAsync =
|
|
119
|
+
(oidc: Oidc) =>
|
|
120
|
+
async (
|
|
121
|
+
configuration: OidcConfiguration,
|
|
122
|
+
configurationName: string,
|
|
123
|
+
currentTokens: Tokens,
|
|
124
|
+
forceRefresh = false,
|
|
125
|
+
) => {
|
|
99
126
|
// 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)
|
|
100
127
|
// const configuration = this.configuration;
|
|
101
128
|
const nullNonce = { nonce: null };
|
|
102
129
|
if (!currentTokens) {
|
|
103
|
-
|
|
130
|
+
return { tokens: null, status: 'NOT_CONNECTED', nonce: nullNonce };
|
|
104
131
|
}
|
|
105
132
|
let nonce = nullNonce;
|
|
106
|
-
const oidcServerConfiguration = await oidc.initAsync(
|
|
133
|
+
const oidcServerConfiguration = await oidc.initAsync(
|
|
134
|
+
configuration.authority,
|
|
135
|
+
configuration.authority_configuration,
|
|
136
|
+
);
|
|
107
137
|
const serviceWorker = await initWorkerAsync(configuration, configurationName);
|
|
108
138
|
if (serviceWorker) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
139
|
+
const { status, tokens } = await serviceWorker.initAsync(
|
|
140
|
+
oidcServerConfiguration,
|
|
141
|
+
'syncTokensAsync',
|
|
142
|
+
configuration,
|
|
143
|
+
);
|
|
144
|
+
if (status === 'LOGGED_OUT') {
|
|
145
|
+
return { tokens: null, status: 'LOGOUT_FROM_ANOTHER_TAB', nonce: nullNonce };
|
|
146
|
+
} else if (status === 'SESSIONS_LOST') {
|
|
147
|
+
return { tokens: null, status: 'SESSIONS_LOST', nonce: nullNonce };
|
|
148
|
+
} else if (!status || !tokens) {
|
|
149
|
+
return { tokens: null, status: 'REQUIRE_SYNC_TOKENS', nonce: nullNonce };
|
|
150
|
+
} else if (tokens.issuedAt !== currentTokens.issuedAt) {
|
|
151
|
+
const timeLeft = computeTimeLeft(
|
|
152
|
+
configuration.refresh_time_before_tokens_expiration_in_second,
|
|
153
|
+
tokens.expiresAt,
|
|
154
|
+
);
|
|
155
|
+
const status =
|
|
156
|
+
timeLeft > 0
|
|
157
|
+
? 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID'
|
|
158
|
+
: 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID';
|
|
159
|
+
const nonce = await serviceWorker.getNonceAsync();
|
|
160
|
+
return { tokens, status, nonce };
|
|
161
|
+
}
|
|
162
|
+
nonce = await serviceWorker.getNonceAsync();
|
|
123
163
|
} else {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
164
|
+
const session = initSession(configurationName, configuration.storage ?? sessionStorage);
|
|
165
|
+
const initAsyncResponse = await session.initAsync();
|
|
166
|
+
let { tokens } = initAsyncResponse;
|
|
167
|
+
const { status } = initAsyncResponse;
|
|
168
|
+
if (tokens) {
|
|
169
|
+
tokens = setTokens(tokens, oidc.tokens, configuration.token_renew_mode);
|
|
170
|
+
}
|
|
171
|
+
if (!tokens) {
|
|
172
|
+
return { tokens: null, status: 'LOGOUT_FROM_ANOTHER_TAB', nonce: nullNonce };
|
|
173
|
+
} else if (status === 'SESSIONS_LOST') {
|
|
174
|
+
return { tokens: null, status: 'SESSIONS_LOST', nonce: nullNonce };
|
|
175
|
+
} else if (tokens.issuedAt !== currentTokens.issuedAt) {
|
|
176
|
+
const timeLeft = computeTimeLeft(
|
|
177
|
+
configuration.refresh_time_before_tokens_expiration_in_second,
|
|
178
|
+
tokens.expiresAt,
|
|
179
|
+
);
|
|
180
|
+
const status =
|
|
181
|
+
timeLeft > 0
|
|
182
|
+
? 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID'
|
|
183
|
+
: 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_INVALID';
|
|
184
|
+
const nonce = await session.getNonceAsync();
|
|
185
|
+
return { tokens, status, nonce };
|
|
186
|
+
}
|
|
187
|
+
nonce = await session.getNonceAsync();
|
|
140
188
|
}
|
|
141
189
|
|
|
142
|
-
const timeLeft = computeTimeLeft(
|
|
143
|
-
|
|
190
|
+
const timeLeft = computeTimeLeft(
|
|
191
|
+
configuration.refresh_time_before_tokens_expiration_in_second,
|
|
192
|
+
currentTokens.expiresAt,
|
|
193
|
+
);
|
|
194
|
+
const status = timeLeft > 0 ? 'TOKENS_VALID' : 'TOKENS_INVALID';
|
|
144
195
|
if (forceRefresh) {
|
|
145
|
-
|
|
196
|
+
return { tokens: currentTokens, status: 'FORCE_REFRESH', nonce };
|
|
146
197
|
}
|
|
147
198
|
return { tokens: currentTokens, status, nonce };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const synchroniseTokensAsync = (oidc:Oidc) => async (index = 0, forceRefresh = false, extras:StringMap = null, updateTokens) =>{
|
|
199
|
+
};
|
|
152
200
|
|
|
201
|
+
const synchroniseTokensAsync =
|
|
202
|
+
(oidc: Oidc) =>
|
|
203
|
+
async (index = 0, forceRefresh = false, extras: StringMap = null, updateTokens) => {
|
|
153
204
|
if (!navigator.onLine && document.hidden) {
|
|
154
|
-
|
|
205
|
+
return { tokens: oidc.tokens, status: 'GIVE_UP' };
|
|
155
206
|
}
|
|
156
207
|
let numberTryOnline = 6;
|
|
157
208
|
while (!navigator.onLine && numberTryOnline > 0) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
209
|
+
await sleepAsync({ milliseconds: 1000 });
|
|
210
|
+
numberTryOnline--;
|
|
211
|
+
oidc.publishEvent(eventNames.refreshTokensAsync, {
|
|
212
|
+
message: `wait because navigator is offline try ${numberTryOnline}`,
|
|
213
|
+
});
|
|
161
214
|
}
|
|
162
|
-
const isDocumentHidden = document.hidden;
|
|
163
215
|
const nextIndex = index + 1;
|
|
164
216
|
if (!extras) {
|
|
165
|
-
|
|
217
|
+
extras = {};
|
|
166
218
|
}
|
|
167
219
|
const configuration = oidc.configuration;
|
|
168
220
|
|
|
169
|
-
const silentLoginAsync = (extras: StringMap, state:string=null, scope:string = null) => {
|
|
170
|
-
|
|
221
|
+
const silentLoginAsync = (extras: StringMap, state: string = null, scope: string = null) => {
|
|
222
|
+
return _silentLoginAsync(
|
|
223
|
+
oidc.configurationName,
|
|
224
|
+
oidc.configuration,
|
|
225
|
+
oidc.publishEvent.bind(oidc),
|
|
226
|
+
)(extras, state, scope);
|
|
171
227
|
};
|
|
172
228
|
const localsilentLoginAsync = async () => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return { tokens: silent_token_response.tokens, status: 'LOGGED' };
|
|
201
|
-
|
|
202
|
-
} catch (exceptionSilent: any) {
|
|
203
|
-
console.error(exceptionSilent);
|
|
204
|
-
oidc.publishEvent(eventNames.refreshTokensAsync_silent_error, { message: 'exceptionSilent', exception: exceptionSilent.message });
|
|
205
|
-
return await synchroniseTokensAsync(oidc)(nextIndex, forceRefresh, extras, updateTokens);
|
|
229
|
+
try {
|
|
230
|
+
let loginParams;
|
|
231
|
+
const serviceWorker = await initWorkerAsync(configuration, oidc.configurationName);
|
|
232
|
+
if (serviceWorker) {
|
|
233
|
+
loginParams = serviceWorker.getLoginParams();
|
|
234
|
+
} else {
|
|
235
|
+
const session = initSession(oidc.configurationName, configuration.storage);
|
|
236
|
+
loginParams = session.getLoginParams();
|
|
237
|
+
}
|
|
238
|
+
const silent_token_response = await silentLoginAsync({
|
|
239
|
+
...loginParams.extras,
|
|
240
|
+
...extras,
|
|
241
|
+
prompt: 'none',
|
|
242
|
+
});
|
|
243
|
+
if (!silent_token_response) {
|
|
244
|
+
updateTokens(null);
|
|
245
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_error, {
|
|
246
|
+
message: 'refresh token silent not active',
|
|
247
|
+
});
|
|
248
|
+
return { tokens: null, status: 'SESSION_LOST' };
|
|
249
|
+
}
|
|
250
|
+
if (silent_token_response.error) {
|
|
251
|
+
updateTokens(null);
|
|
252
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_error, {
|
|
253
|
+
message: 'refresh token silent',
|
|
254
|
+
});
|
|
255
|
+
return { tokens: null, status: 'SESSION_LOST' };
|
|
206
256
|
}
|
|
257
|
+
|
|
258
|
+
updateTokens(silent_token_response.tokens);
|
|
259
|
+
oidc.publishEvent(Oidc.eventNames.token_renewed, {});
|
|
260
|
+
return { tokens: silent_token_response.tokens, status: 'LOGGED' };
|
|
261
|
+
} catch (exceptionSilent: any) {
|
|
262
|
+
console.error(exceptionSilent);
|
|
263
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
264
|
+
message: 'exceptionSilent',
|
|
265
|
+
exception: exceptionSilent.message,
|
|
266
|
+
});
|
|
267
|
+
return await synchroniseTokensAsync(oidc)(nextIndex, forceRefresh, extras, updateTokens);
|
|
268
|
+
}
|
|
207
269
|
};
|
|
208
|
-
|
|
270
|
+
|
|
209
271
|
try {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
272
|
+
const { status, tokens, nonce } = await syncTokensInfoAsync(oidc)(
|
|
273
|
+
configuration,
|
|
274
|
+
oidc.configurationName,
|
|
275
|
+
oidc.tokens,
|
|
276
|
+
forceRefresh,
|
|
277
|
+
);
|
|
278
|
+
switch (status) {
|
|
279
|
+
case synchroniseTokensStatus.SESSION_LOST:
|
|
280
|
+
updateTokens(null);
|
|
281
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_error, {
|
|
282
|
+
message: 'refresh token session lost',
|
|
283
|
+
});
|
|
284
|
+
return { tokens: null, status: 'SESSION_LOST' };
|
|
285
|
+
case synchroniseTokensStatus.NOT_CONNECTED:
|
|
286
|
+
updateTokens(null);
|
|
287
|
+
return { tokens: null, status: null };
|
|
288
|
+
case synchroniseTokensStatus.TOKENS_VALID:
|
|
289
|
+
updateTokens(tokens);
|
|
290
|
+
return { tokens, status: 'LOGGED_IN' };
|
|
291
|
+
case synchroniseTokensStatus.TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID:
|
|
292
|
+
updateTokens(tokens);
|
|
293
|
+
oidc.publishEvent(Oidc.eventNames.token_renewed, {
|
|
294
|
+
reason: 'TOKEN_UPDATED_BY_ANOTHER_TAB_TOKENS_VALID',
|
|
295
|
+
});
|
|
296
|
+
return { tokens, status: 'LOGGED_IN' };
|
|
297
|
+
case synchroniseTokensStatus.LOGOUT_FROM_ANOTHER_TAB:
|
|
298
|
+
updateTokens(null);
|
|
299
|
+
oidc.publishEvent(eventNames.logout_from_another_tab, {
|
|
300
|
+
status: 'session syncTokensAsync',
|
|
301
|
+
});
|
|
302
|
+
return { tokens: null, status: 'LOGGED_OUT' };
|
|
303
|
+
case synchroniseTokensStatus.REQUIRE_SYNC_TOKENS:
|
|
304
|
+
if (
|
|
305
|
+
configuration.token_automatic_renew_mode ==
|
|
306
|
+
TokenAutomaticRenewMode.AutomaticOnlyWhenFetchExecuted &&
|
|
307
|
+
synchroniseTokensStatus.FORCE_REFRESH !== status
|
|
308
|
+
) {
|
|
309
|
+
oidc.publishEvent(eventNames.tokensInvalidAndWaitingActionsToRefresh, {});
|
|
310
|
+
return { tokens: oidc.tokens, status: 'GIVE_UP' };
|
|
311
|
+
}
|
|
231
312
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
313
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_begin, { tryNumber: index });
|
|
314
|
+
return await localsilentLoginAsync();
|
|
315
|
+
default: {
|
|
316
|
+
if (
|
|
317
|
+
configuration.token_automatic_renew_mode ==
|
|
318
|
+
TokenAutomaticRenewMode.AutomaticOnlyWhenFetchExecuted &&
|
|
319
|
+
synchroniseTokensStatus.FORCE_REFRESH !== status
|
|
320
|
+
) {
|
|
321
|
+
oidc.publishEvent(eventNames.tokensInvalidAndWaitingActionsToRefresh, {});
|
|
322
|
+
return { tokens: oidc.tokens, status: 'GIVE_UP' };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_begin, {
|
|
326
|
+
refreshToken: tokens.refreshToken,
|
|
327
|
+
status,
|
|
328
|
+
tryNumber: index,
|
|
329
|
+
});
|
|
330
|
+
if (!tokens.refreshToken) {
|
|
331
|
+
return await localsilentLoginAsync();
|
|
332
|
+
}
|
|
250
333
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
334
|
+
const clientId = configuration.client_id;
|
|
335
|
+
const redirectUri = configuration.redirect_uri;
|
|
336
|
+
const authority = configuration.authority;
|
|
337
|
+
const tokenExtras = configuration.token_request_extras
|
|
338
|
+
? configuration.token_request_extras
|
|
339
|
+
: {};
|
|
340
|
+
const finalExtras = { ...tokenExtras };
|
|
256
341
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
342
|
+
for (const [key, value] of Object.entries(extras)) {
|
|
343
|
+
if (key.endsWith(':token_request')) {
|
|
344
|
+
finalExtras[key.replace(':token_request', '')] = value;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const localFunctionAsync = async () => {
|
|
348
|
+
const details = {
|
|
349
|
+
client_id: clientId,
|
|
350
|
+
redirect_uri: redirectUri,
|
|
351
|
+
grant_type: 'refresh_token',
|
|
352
|
+
refresh_token: tokens.refreshToken,
|
|
353
|
+
};
|
|
354
|
+
const oidcServerConfiguration = await oidc.initAsync(
|
|
355
|
+
authority,
|
|
356
|
+
configuration.authority_configuration,
|
|
357
|
+
);
|
|
358
|
+
const timeoutMs = document.hidden ? 10000 : 30000 * 10;
|
|
359
|
+
const url = oidcServerConfiguration.tokenEndpoint;
|
|
360
|
+
const headersExtras = {};
|
|
361
|
+
if (configuration.demonstrating_proof_of_possession) {
|
|
362
|
+
headersExtras['DPoP'] = await oidc.generateDemonstrationOfProofOfPossessionAsync(
|
|
363
|
+
tokens.accessToken,
|
|
364
|
+
url,
|
|
365
|
+
'POST',
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
const tokenResponse = await performTokenRequestAsync(oidc.getFetch())(
|
|
369
|
+
url,
|
|
370
|
+
details,
|
|
371
|
+
finalExtras,
|
|
372
|
+
tokens,
|
|
373
|
+
headersExtras,
|
|
374
|
+
configuration.token_renew_mode,
|
|
375
|
+
timeoutMs,
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
if (tokenResponse.success) {
|
|
379
|
+
const { isValid, reason } = isTokensOidcValid(
|
|
380
|
+
tokenResponse.data,
|
|
381
|
+
nonce.nonce,
|
|
382
|
+
oidcServerConfiguration,
|
|
383
|
+
);
|
|
384
|
+
if (!isValid) {
|
|
385
|
+
updateTokens(null);
|
|
386
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_error, {
|
|
387
|
+
message: `refresh token return not valid tokens, reason: ${reason}`,
|
|
388
|
+
});
|
|
389
|
+
return { tokens: null, status: 'SESSION_LOST' };
|
|
390
|
+
}
|
|
391
|
+
updateTokens(tokenResponse.data);
|
|
392
|
+
if (tokenResponse.demonstratingProofOfPossessionNonce) {
|
|
393
|
+
const serviceWorker = await initWorkerAsync(configuration, oidc.configurationName);
|
|
394
|
+
if (serviceWorker) {
|
|
395
|
+
await serviceWorker.setDemonstratingProofOfPossessionNonce(
|
|
396
|
+
tokenResponse.demonstratingProofOfPossessionNonce,
|
|
397
|
+
);
|
|
398
|
+
} else {
|
|
399
|
+
const session = initSession(oidc.configurationName, configuration.storage);
|
|
400
|
+
await session.setDemonstratingProofOfPossessionNonce(
|
|
401
|
+
tokenResponse.demonstratingProofOfPossessionNonce,
|
|
402
|
+
);
|
|
261
403
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
configuration.token_renew_mode,
|
|
282
|
-
timeoutMs);
|
|
404
|
+
}
|
|
405
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_end, {
|
|
406
|
+
success: tokenResponse.success,
|
|
407
|
+
});
|
|
408
|
+
oidc.publishEvent(Oidc.eventNames.token_renewed, { reason: 'REFRESH_TOKEN' });
|
|
409
|
+
return { tokens: tokenResponse.data, status: 'LOGGED_IN' };
|
|
410
|
+
} else {
|
|
411
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
412
|
+
message: 'bad request',
|
|
413
|
+
tokenResponse,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
if (tokenResponse.status >= 400 && tokenResponse.status < 500) {
|
|
417
|
+
updateTokens(null);
|
|
418
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_error, {
|
|
419
|
+
message: `session lost: ${tokenResponse.status}`,
|
|
420
|
+
});
|
|
421
|
+
return { tokens: null, status: 'SESSION_LOST' };
|
|
422
|
+
}
|
|
283
423
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
updateTokens(tokenResponse.data);
|
|
292
|
-
if(tokenResponse.demonstratingProofOfPossessionNonce) {
|
|
293
|
-
const serviceWorker = await initWorkerAsync(configuration, oidc.configurationName);
|
|
294
|
-
if(serviceWorker){
|
|
295
|
-
await serviceWorker.setDemonstratingProofOfPossessionNonce(tokenResponse.demonstratingProofOfPossessionNonce);
|
|
296
|
-
} else {
|
|
297
|
-
const session = initSession(oidc.configurationName, configuration.storage);
|
|
298
|
-
await session.setDemonstratingProofOfPossessionNonce(tokenResponse.demonstratingProofOfPossessionNonce);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
oidc.publishEvent(eventNames.refreshTokensAsync_end, { success: tokenResponse.success });
|
|
302
|
-
oidc.publishEvent(Oidc.eventNames.token_renewed, { reason: 'REFRESH_TOKEN' });
|
|
303
|
-
return { tokens: tokenResponse.data, status: 'LOGGED_IN' };
|
|
304
|
-
} else {
|
|
305
|
-
oidc.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
306
|
-
message: 'bad request',
|
|
307
|
-
tokenResponse,
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
if (tokenResponse.status >= 400 && tokenResponse.status < 500) {
|
|
311
|
-
updateTokens(null);
|
|
312
|
-
oidc.publishEvent(eventNames.refreshTokensAsync_error, { message: `session lost: ${tokenResponse.status}` });
|
|
313
|
-
return { tokens: null, status: 'SESSION_LOST' };
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return await synchroniseTokensAsync(oidc)(nextIndex, forceRefresh, extras, updateTokens);
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
return await localFunctionAsync();
|
|
424
|
+
return await synchroniseTokensAsync(oidc)(
|
|
425
|
+
nextIndex,
|
|
426
|
+
forceRefresh,
|
|
427
|
+
extras,
|
|
428
|
+
updateTokens,
|
|
429
|
+
);
|
|
320
430
|
}
|
|
431
|
+
};
|
|
432
|
+
return await localFunctionAsync();
|
|
321
433
|
}
|
|
434
|
+
}
|
|
322
435
|
} catch (exception: any) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
436
|
+
console.error(exception);
|
|
437
|
+
oidc.publishEvent(eventNames.refreshTokensAsync_silent_error, {
|
|
438
|
+
message: 'exception',
|
|
439
|
+
exception: exception.message,
|
|
440
|
+
});
|
|
441
|
+
// we need to break the loop or errors, as direct call of synchroniseTokensAsync
|
|
442
|
+
// inside of synchroniseTokensAsync will cause an infinite loop and kill the browser stack
|
|
443
|
+
// so we need to brake calls chain and delay next call
|
|
444
|
+
return new Promise((resolve, reject) => {
|
|
445
|
+
setTimeout(() => {
|
|
446
|
+
synchroniseTokensAsync(oidc)(nextIndex, forceRefresh, extras, updateTokens)
|
|
447
|
+
.then(resolve)
|
|
448
|
+
.catch(reject);
|
|
449
|
+
}, 1000);
|
|
450
|
+
});
|
|
338
451
|
}
|
|
339
|
-
}
|
|
452
|
+
};
|