@axa-fr/oidc-client 6.26.6
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 +209 -0
- package/bin/post-install.mjs +58 -0
- package/dist/OidcServiceWorker.js +561 -0
- package/dist/OidcTrustedDomains.js +27 -0
- package/dist/cache.d.ts +3 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/checkSession.d.ts +4 -0
- package/dist/checkSession.d.ts.map +1 -0
- package/dist/checkSessionIFrame.d.ts +17 -0
- package/dist/checkSessionIFrame.d.ts.map +1 -0
- package/dist/crypto.d.ts +4 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/events.d.ts +29 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1236 -0
- package/dist/index.umd.cjs +2 -0
- package/dist/iniWorker.spec.d.ts +2 -0
- package/dist/iniWorker.spec.d.ts.map +1 -0
- package/dist/initSession.d.ts +22 -0
- package/dist/initSession.d.ts.map +1 -0
- package/dist/initWorker.d.ts +30 -0
- package/dist/initWorker.d.ts.map +1 -0
- package/dist/login.d.ts +8 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/logout.d.ts +8 -0
- package/dist/logout.d.ts.map +1 -0
- package/dist/logout.spec.d.ts +1 -0
- package/dist/logout.spec.d.ts.map +1 -0
- package/dist/oidc.d.ts +101 -0
- package/dist/oidc.d.ts.map +1 -0
- package/dist/parseTokens.d.ts +37 -0
- package/dist/parseTokens.d.ts.map +1 -0
- package/dist/parseTokens.spec.d.ts +2 -0
- package/dist/parseTokens.spec.d.ts.map +1 -0
- package/dist/renewTokens.d.ts +4 -0
- package/dist/renewTokens.d.ts.map +1 -0
- package/dist/requests.d.ts +33 -0
- package/dist/requests.d.ts.map +1 -0
- package/dist/requests.spec.d.ts +2 -0
- package/dist/requests.spec.d.ts.map +1 -0
- package/dist/route-utils.d.ts +13 -0
- package/dist/route-utils.d.ts.map +1 -0
- package/dist/route-utils.spec.d.ts +2 -0
- package/dist/route-utils.spec.d.ts.map +1 -0
- package/dist/silentLogin.d.ts +10 -0
- package/dist/silentLogin.d.ts.map +1 -0
- package/dist/timer.d.ts +13 -0
- package/dist/timer.d.ts.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/user.d.ts +2 -0
- package/dist/user.d.ts.map +1 -0
- package/dist/vanillaOidc.d.ts +85 -0
- package/dist/vanillaOidc.d.ts.map +1 -0
- package/package.json +60 -0
- package/src/cache.ts +26 -0
- package/src/checkSession.ts +60 -0
- package/src/checkSessionIFrame.ts +83 -0
- package/src/crypto.ts +61 -0
- package/src/events.ts +28 -0
- package/src/index.ts +10 -0
- package/src/iniWorker.spec.ts +21 -0
- package/src/initSession.ts +89 -0
- package/src/initWorker.ts +321 -0
- package/src/login.ts +174 -0
- package/src/logout.spec.ts +65 -0
- package/src/logout.ts +101 -0
- package/src/oidc.ts +613 -0
- package/src/parseTokens.spec.ts +50 -0
- package/src/parseTokens.ts +194 -0
- package/src/renewTokens.ts +37 -0
- package/src/requests.spec.ts +9 -0
- package/src/requests.ts +169 -0
- package/src/route-utils.spec.ts +24 -0
- package/src/route-utils.ts +79 -0
- package/src/silentLogin.ts +144 -0
- package/src/timer.ts +163 -0
- package/src/types.ts +41 -0
- package/src/user.ts +40 -0
- package/src/vanillaOidc.ts +108 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
const scriptFilename = "OidcTrustedDomains.js";
|
|
2
|
+
const acceptAnyDomainToken = "*";
|
|
3
|
+
const TOKEN = {
|
|
4
|
+
REFRESH_TOKEN: "REFRESH_TOKEN_SECURED_BY_OIDC_SERVICE_WORKER",
|
|
5
|
+
ACCESS_TOKEN: "ACCESS_TOKEN_SECURED_BY_OIDC_SERVICE_WORKER",
|
|
6
|
+
NONCE_TOKEN: "NONCE_SECURED_BY_OIDC_SERVICE_WORKER",
|
|
7
|
+
CODE_VERIFIER: "CODE_VERIFIER_SECURED_BY_OIDC_SERVICE_WORKER"
|
|
8
|
+
};
|
|
9
|
+
const TokenRenewMode = {
|
|
10
|
+
access_token_or_id_token_invalid: "access_token_or_id_token_invalid",
|
|
11
|
+
access_token_invalid: "access_token_invalid",
|
|
12
|
+
id_token_invalid: "id_token_invalid"
|
|
13
|
+
};
|
|
14
|
+
const openidWellknownUrlEndWith = "/.well-known/openid-configuration";
|
|
15
|
+
function checkDomain(domains, endpoint) {
|
|
16
|
+
if (!endpoint) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const domain = domains.find((domain2) => {
|
|
20
|
+
var _a;
|
|
21
|
+
let testable;
|
|
22
|
+
if (typeof domain2 === "string") {
|
|
23
|
+
testable = new RegExp(`^${domain2}`);
|
|
24
|
+
} else {
|
|
25
|
+
testable = domain2;
|
|
26
|
+
}
|
|
27
|
+
return (_a = testable.test) == null ? void 0 : _a.call(testable, endpoint);
|
|
28
|
+
});
|
|
29
|
+
if (!domain) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
"Domain " + endpoint + " is not trusted, please add domain in " + scriptFilename
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const getDomains = (trustedDomain, type) => {
|
|
36
|
+
if (Array.isArray(trustedDomain)) {
|
|
37
|
+
return trustedDomain;
|
|
38
|
+
}
|
|
39
|
+
return trustedDomain[`${type}Domains`] ?? trustedDomain.domains ?? [];
|
|
40
|
+
};
|
|
41
|
+
const getCurrentDatabaseDomain = (database2, url, trustedDomains2) => {
|
|
42
|
+
var _a;
|
|
43
|
+
if (url.endsWith(openidWellknownUrlEndWith)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
for (const [key, currentDatabase] of Object.entries(database2)) {
|
|
47
|
+
const oidcServerConfiguration = currentDatabase.oidcServerConfiguration;
|
|
48
|
+
if (!oidcServerConfiguration) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (oidcServerConfiguration.tokenEndpoint && url === oidcServerConfiguration.tokenEndpoint) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (oidcServerConfiguration.revocationEndpoint && url === oidcServerConfiguration.revocationEndpoint) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const trustedDomain = trustedDomains2 == null ? [] : trustedDomains2[key];
|
|
58
|
+
const domains = getDomains(trustedDomain, "accessToken");
|
|
59
|
+
const domainsToSendTokens = oidcServerConfiguration.userInfoEndpoint ? [oidcServerConfiguration.userInfoEndpoint, ...domains] : [...domains];
|
|
60
|
+
let hasToSendToken = false;
|
|
61
|
+
if (domainsToSendTokens.find((f) => f === acceptAnyDomainToken)) {
|
|
62
|
+
hasToSendToken = true;
|
|
63
|
+
} else {
|
|
64
|
+
for (let i = 0; i < domainsToSendTokens.length; i++) {
|
|
65
|
+
let domain = domainsToSendTokens[i];
|
|
66
|
+
if (typeof domain === "string") {
|
|
67
|
+
domain = new RegExp(`^${domain}`);
|
|
68
|
+
}
|
|
69
|
+
if ((_a = domain.test) == null ? void 0 : _a.call(domain, url)) {
|
|
70
|
+
hasToSendToken = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (hasToSendToken) {
|
|
76
|
+
if (!currentDatabase.tokens) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return currentDatabase;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
};
|
|
84
|
+
function serializeHeaders(headers) {
|
|
85
|
+
const headersObj = {};
|
|
86
|
+
for (const key of headers.keys()) {
|
|
87
|
+
if (headers.has(key)) {
|
|
88
|
+
headersObj[key] = headers.get(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return headersObj;
|
|
92
|
+
}
|
|
93
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
94
|
+
function countLetter(str, find) {
|
|
95
|
+
return str.split(find).length - 1;
|
|
96
|
+
}
|
|
97
|
+
function parseJwt(token) {
|
|
98
|
+
return JSON.parse(
|
|
99
|
+
b64DecodeUnicode(token.split(".")[1].replace("-", "+").replace("_", "/"))
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
function b64DecodeUnicode(str) {
|
|
103
|
+
return decodeURIComponent(
|
|
104
|
+
Array.prototype.map.call(
|
|
105
|
+
atob(str),
|
|
106
|
+
(c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)
|
|
107
|
+
).join("")
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
function computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt) {
|
|
111
|
+
const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
112
|
+
return Math.round(
|
|
113
|
+
expiresAt - refreshTimeBeforeTokensExpirationInSecond - currentTimeUnixSecond
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
function isTokensValid(tokens) {
|
|
117
|
+
if (!tokens) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return computeTimeLeft(0, tokens.expiresAt) > 0;
|
|
121
|
+
}
|
|
122
|
+
const extractTokenPayload = (token) => {
|
|
123
|
+
try {
|
|
124
|
+
if (!token) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
if (countLetter(token, ".") === 2) {
|
|
128
|
+
return parseJwt(token);
|
|
129
|
+
} else {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
} catch (e) {
|
|
133
|
+
console.warn(e);
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
const isTokensOidcValid = (tokens, nonce, oidcServerConfiguration) => {
|
|
138
|
+
if (tokens.idTokenPayload) {
|
|
139
|
+
const idTokenPayload = tokens.idTokenPayload;
|
|
140
|
+
if (oidcServerConfiguration.issuer !== idTokenPayload.iss) {
|
|
141
|
+
return { isValid: false, reason: "Issuer does not match" };
|
|
142
|
+
}
|
|
143
|
+
const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
144
|
+
if (idTokenPayload.exp && idTokenPayload.exp < currentTimeUnixSecond) {
|
|
145
|
+
return { isValid: false, reason: "Token expired" };
|
|
146
|
+
}
|
|
147
|
+
const timeInSevenDays = 60 * 60 * 24 * 7;
|
|
148
|
+
if (idTokenPayload.iat && idTokenPayload.iat + timeInSevenDays < currentTimeUnixSecond) {
|
|
149
|
+
return { isValid: false, reason: "Token is used from too long time" };
|
|
150
|
+
}
|
|
151
|
+
if (nonce && idTokenPayload.nonce && idTokenPayload.nonce !== nonce) {
|
|
152
|
+
return { isValid: false, reason: "Nonce does not match" };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { isValid: true, reason: "" };
|
|
156
|
+
};
|
|
157
|
+
function _hideTokens(tokens, currentDatabaseElement, configurationName) {
|
|
158
|
+
if (!tokens.issued_at) {
|
|
159
|
+
const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
160
|
+
tokens.issued_at = currentTimeUnixSecond;
|
|
161
|
+
}
|
|
162
|
+
const accessTokenPayload = extractTokenPayload(tokens.access_token);
|
|
163
|
+
const secureTokens = {
|
|
164
|
+
...tokens,
|
|
165
|
+
accessTokenPayload
|
|
166
|
+
};
|
|
167
|
+
if (currentDatabaseElement.hideAccessToken) {
|
|
168
|
+
secureTokens.access_token = TOKEN.ACCESS_TOKEN + "_" + configurationName;
|
|
169
|
+
}
|
|
170
|
+
tokens.accessTokenPayload = accessTokenPayload;
|
|
171
|
+
let _idTokenPayload = null;
|
|
172
|
+
if (tokens.id_token) {
|
|
173
|
+
_idTokenPayload = extractTokenPayload(tokens.id_token);
|
|
174
|
+
tokens.idTokenPayload = { ..._idTokenPayload };
|
|
175
|
+
if (_idTokenPayload.nonce && currentDatabaseElement.nonce != null) {
|
|
176
|
+
const keyNonce = TOKEN.NONCE_TOKEN + "_" + currentDatabaseElement.configurationName;
|
|
177
|
+
_idTokenPayload.nonce = keyNonce;
|
|
178
|
+
}
|
|
179
|
+
secureTokens.idTokenPayload = _idTokenPayload;
|
|
180
|
+
}
|
|
181
|
+
if (tokens.refresh_token) {
|
|
182
|
+
secureTokens.refresh_token = TOKEN.REFRESH_TOKEN + "_" + configurationName;
|
|
183
|
+
}
|
|
184
|
+
const idTokenExpiresAt = _idTokenPayload && _idTokenPayload.exp ? _idTokenPayload.exp : Number.MAX_VALUE;
|
|
185
|
+
const accessTokenExpiresAt = accessTokenPayload && accessTokenPayload.exp ? accessTokenPayload.exp : tokens.issued_at + tokens.expires_in;
|
|
186
|
+
let expiresAt;
|
|
187
|
+
const tokenRenewMode = currentDatabaseElement.oidcConfiguration.token_renew_mode;
|
|
188
|
+
if (tokenRenewMode === TokenRenewMode.access_token_invalid) {
|
|
189
|
+
expiresAt = accessTokenExpiresAt;
|
|
190
|
+
} else if (tokenRenewMode === TokenRenewMode.id_token_invalid) {
|
|
191
|
+
expiresAt = idTokenExpiresAt;
|
|
192
|
+
} else {
|
|
193
|
+
expiresAt = idTokenExpiresAt < accessTokenExpiresAt ? idTokenExpiresAt : accessTokenExpiresAt;
|
|
194
|
+
}
|
|
195
|
+
secureTokens.expiresAt = expiresAt;
|
|
196
|
+
tokens.expiresAt = expiresAt;
|
|
197
|
+
const nonce = currentDatabaseElement.nonce ? currentDatabaseElement.nonce.nonce : null;
|
|
198
|
+
const { isValid, reason } = isTokensOidcValid(
|
|
199
|
+
tokens,
|
|
200
|
+
nonce,
|
|
201
|
+
currentDatabaseElement.oidcServerConfiguration
|
|
202
|
+
);
|
|
203
|
+
if (!isValid) {
|
|
204
|
+
throw Error(`Tokens are not OpenID valid, reason: ${reason}`);
|
|
205
|
+
}
|
|
206
|
+
if (currentDatabaseElement.tokens != null && "refresh_token" in currentDatabaseElement.tokens && !("refresh_token" in tokens)) {
|
|
207
|
+
const refreshToken = currentDatabaseElement.tokens.refresh_token;
|
|
208
|
+
currentDatabaseElement.tokens = {
|
|
209
|
+
...tokens,
|
|
210
|
+
refresh_token: refreshToken
|
|
211
|
+
};
|
|
212
|
+
} else {
|
|
213
|
+
currentDatabaseElement.tokens = tokens;
|
|
214
|
+
}
|
|
215
|
+
currentDatabaseElement.status = "LOGGED_IN";
|
|
216
|
+
return secureTokens;
|
|
217
|
+
}
|
|
218
|
+
function hideTokens(currentDatabaseElement) {
|
|
219
|
+
const configurationName = currentDatabaseElement.configurationName;
|
|
220
|
+
return (response) => {
|
|
221
|
+
if (response.status !== 200) {
|
|
222
|
+
return response;
|
|
223
|
+
}
|
|
224
|
+
return response.json().then((tokens) => {
|
|
225
|
+
const secureTokens = _hideTokens(tokens, currentDatabaseElement, configurationName);
|
|
226
|
+
const body = JSON.stringify(secureTokens);
|
|
227
|
+
return new Response(body, response);
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function replaceCodeVerifier(codeVerifier, newCodeVerifier) {
|
|
232
|
+
const regex = /code_verifier=[A-Za-z0-9_-]+/i;
|
|
233
|
+
return codeVerifier.replace(regex, `code_verifier=${newCodeVerifier}`);
|
|
234
|
+
}
|
|
235
|
+
const _self = self;
|
|
236
|
+
_self.importScripts(scriptFilename);
|
|
237
|
+
const id = Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3).toString();
|
|
238
|
+
const keepAliveJsonFilename = "OidcKeepAliveServiceWorker.json";
|
|
239
|
+
const handleInstall = (event) => {
|
|
240
|
+
console.log("[OidcServiceWorker] service worker installed " + id);
|
|
241
|
+
event.waitUntil(_self.skipWaiting());
|
|
242
|
+
};
|
|
243
|
+
const handleActivate = (event) => {
|
|
244
|
+
console.log("[OidcServiceWorker] service worker activated " + id);
|
|
245
|
+
event.waitUntil(_self.clients.claim());
|
|
246
|
+
};
|
|
247
|
+
let currentLoginCallbackConfigurationName = null;
|
|
248
|
+
const database = {
|
|
249
|
+
default: {
|
|
250
|
+
configurationName: "default",
|
|
251
|
+
tokens: null,
|
|
252
|
+
status: null,
|
|
253
|
+
state: null,
|
|
254
|
+
codeVerifier: null,
|
|
255
|
+
nonce: null,
|
|
256
|
+
oidcServerConfiguration: null,
|
|
257
|
+
hideAccessToken: true
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
const getCurrentDatabasesTokenEndpoint = (database2, url) => {
|
|
261
|
+
const databases = [];
|
|
262
|
+
for (const [, value] of Object.entries(database2)) {
|
|
263
|
+
if (value.oidcServerConfiguration != null && url.startsWith(value.oidcServerConfiguration.tokenEndpoint)) {
|
|
264
|
+
databases.push(value);
|
|
265
|
+
} else if (value.oidcServerConfiguration != null && value.oidcServerConfiguration.revocationEndpoint && url.startsWith(value.oidcServerConfiguration.revocationEndpoint)) {
|
|
266
|
+
databases.push(value);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return databases;
|
|
270
|
+
};
|
|
271
|
+
const keepAliveAsync = async (event) => {
|
|
272
|
+
const originalRequest = event.request;
|
|
273
|
+
const isFromVanilla = originalRequest.headers.has("oidc-vanilla");
|
|
274
|
+
const init = { status: 200, statusText: "oidc-service-worker" };
|
|
275
|
+
const response = new Response("{}", init);
|
|
276
|
+
if (!isFromVanilla) {
|
|
277
|
+
const originalRequestUrl = new URL(originalRequest.url);
|
|
278
|
+
const minSleepSeconds = Number(originalRequestUrl.searchParams.get("minSleepSeconds")) || 240;
|
|
279
|
+
for (let i = 0; i < minSleepSeconds; i++) {
|
|
280
|
+
await sleep(1e3 + Math.floor(Math.random() * 1e3));
|
|
281
|
+
const cache = await caches.open("oidc_dummy_cache");
|
|
282
|
+
await cache.put(event.request, response.clone());
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return response;
|
|
286
|
+
};
|
|
287
|
+
const handleFetch = async (event) => {
|
|
288
|
+
const originalRequest = event.request;
|
|
289
|
+
const url = originalRequest.url;
|
|
290
|
+
if (originalRequest.url.includes(keepAliveJsonFilename)) {
|
|
291
|
+
event.respondWith(keepAliveAsync(event));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const currentDatabaseForRequestAccessToken = getCurrentDatabaseDomain(
|
|
295
|
+
database,
|
|
296
|
+
originalRequest.url,
|
|
297
|
+
trustedDomains
|
|
298
|
+
);
|
|
299
|
+
if (currentDatabaseForRequestAccessToken && currentDatabaseForRequestAccessToken.tokens && currentDatabaseForRequestAccessToken.tokens.access_token) {
|
|
300
|
+
while (currentDatabaseForRequestAccessToken.tokens && !isTokensValid(currentDatabaseForRequestAccessToken.tokens)) {
|
|
301
|
+
await sleep(200);
|
|
302
|
+
}
|
|
303
|
+
const newRequest = originalRequest.mode === "navigate" ? new Request(originalRequest, {
|
|
304
|
+
headers: {
|
|
305
|
+
...serializeHeaders(originalRequest.headers),
|
|
306
|
+
authorization: "Bearer " + currentDatabaseForRequestAccessToken.tokens.access_token
|
|
307
|
+
}
|
|
308
|
+
}) : new Request(originalRequest, {
|
|
309
|
+
headers: {
|
|
310
|
+
...serializeHeaders(originalRequest.headers),
|
|
311
|
+
authorization: "Bearer " + currentDatabaseForRequestAccessToken.tokens.access_token
|
|
312
|
+
},
|
|
313
|
+
mode: currentDatabaseForRequestAccessToken.oidcConfiguration.service_worker_convert_all_requests_to_cors ? "cors" : originalRequest.mode
|
|
314
|
+
});
|
|
315
|
+
event.waitUntil(event.respondWith(fetch(newRequest)));
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (event.request.method !== "POST") {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
let currentDatabase = null;
|
|
322
|
+
const currentDatabases = getCurrentDatabasesTokenEndpoint(
|
|
323
|
+
database,
|
|
324
|
+
originalRequest.url
|
|
325
|
+
);
|
|
326
|
+
const numberDatabase = currentDatabases.length;
|
|
327
|
+
if (numberDatabase > 0) {
|
|
328
|
+
const maPromesse = new Promise((resolve, reject) => {
|
|
329
|
+
const clonedRequest = originalRequest.clone();
|
|
330
|
+
const response = clonedRequest.text().then((actualBody) => {
|
|
331
|
+
if (actualBody.includes(TOKEN.REFRESH_TOKEN) || actualBody.includes(TOKEN.ACCESS_TOKEN)) {
|
|
332
|
+
let newBody = actualBody;
|
|
333
|
+
for (let i = 0; i < numberDatabase; i++) {
|
|
334
|
+
const currentDb = currentDatabases[i];
|
|
335
|
+
if (currentDb && currentDb.tokens != null) {
|
|
336
|
+
const keyRefreshToken = TOKEN.REFRESH_TOKEN + "_" + currentDb.configurationName;
|
|
337
|
+
if (actualBody.includes(keyRefreshToken)) {
|
|
338
|
+
newBody = newBody.replace(
|
|
339
|
+
keyRefreshToken,
|
|
340
|
+
encodeURIComponent(currentDb.tokens.refresh_token)
|
|
341
|
+
);
|
|
342
|
+
currentDatabase = currentDb;
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
const keyAccessToken = TOKEN.ACCESS_TOKEN + "_" + currentDb.configurationName;
|
|
346
|
+
if (actualBody.includes(keyAccessToken)) {
|
|
347
|
+
newBody = newBody.replace(
|
|
348
|
+
keyAccessToken,
|
|
349
|
+
encodeURIComponent(currentDb.tokens.access_token)
|
|
350
|
+
);
|
|
351
|
+
currentDatabase = currentDb;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const fetchPromise = fetch(originalRequest, {
|
|
357
|
+
body: newBody,
|
|
358
|
+
method: clonedRequest.method,
|
|
359
|
+
headers: {
|
|
360
|
+
...serializeHeaders(originalRequest.headers)
|
|
361
|
+
},
|
|
362
|
+
mode: clonedRequest.mode,
|
|
363
|
+
cache: clonedRequest.cache,
|
|
364
|
+
redirect: clonedRequest.redirect,
|
|
365
|
+
referrer: clonedRequest.referrer,
|
|
366
|
+
credentials: clonedRequest.credentials,
|
|
367
|
+
integrity: clonedRequest.integrity
|
|
368
|
+
});
|
|
369
|
+
if (currentDatabase && currentDatabase.oidcServerConfiguration != null && currentDatabase.oidcServerConfiguration.revocationEndpoint && url.startsWith(
|
|
370
|
+
currentDatabase.oidcServerConfiguration.revocationEndpoint
|
|
371
|
+
)) {
|
|
372
|
+
return fetchPromise.then(async (response2) => {
|
|
373
|
+
const text = await response2.text();
|
|
374
|
+
return new Response(text, response2);
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
return fetchPromise.then(hideTokens(currentDatabase));
|
|
378
|
+
} else if (actualBody.includes("code_verifier=") && currentLoginCallbackConfigurationName) {
|
|
379
|
+
currentDatabase = database[currentLoginCallbackConfigurationName];
|
|
380
|
+
currentLoginCallbackConfigurationName = null;
|
|
381
|
+
let newBody = actualBody;
|
|
382
|
+
if (currentDatabase && currentDatabase.codeVerifier != null) {
|
|
383
|
+
newBody = replaceCodeVerifier(newBody, currentDatabase.codeVerifier);
|
|
384
|
+
}
|
|
385
|
+
return fetch(originalRequest, {
|
|
386
|
+
body: newBody,
|
|
387
|
+
method: clonedRequest.method,
|
|
388
|
+
headers: {
|
|
389
|
+
...serializeHeaders(originalRequest.headers)
|
|
390
|
+
},
|
|
391
|
+
mode: clonedRequest.mode,
|
|
392
|
+
cache: clonedRequest.cache,
|
|
393
|
+
redirect: clonedRequest.redirect,
|
|
394
|
+
referrer: clonedRequest.referrer,
|
|
395
|
+
credentials: clonedRequest.credentials,
|
|
396
|
+
integrity: clonedRequest.integrity
|
|
397
|
+
}).then(hideTokens(currentDatabase));
|
|
398
|
+
}
|
|
399
|
+
return fetch(originalRequest, {
|
|
400
|
+
body: actualBody,
|
|
401
|
+
method: clonedRequest.method,
|
|
402
|
+
headers: {
|
|
403
|
+
...serializeHeaders(originalRequest.headers)
|
|
404
|
+
},
|
|
405
|
+
mode: clonedRequest.mode,
|
|
406
|
+
cache: clonedRequest.cache,
|
|
407
|
+
redirect: clonedRequest.redirect,
|
|
408
|
+
referrer: clonedRequest.referrer,
|
|
409
|
+
credentials: clonedRequest.credentials,
|
|
410
|
+
integrity: clonedRequest.integrity
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
response.then((r) => {
|
|
414
|
+
resolve(r);
|
|
415
|
+
}).catch((err) => {
|
|
416
|
+
reject(err);
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
event.waitUntil(event.respondWith(maPromesse));
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
const trustedDomainsShowAccessToken = {};
|
|
423
|
+
const handleMessage = (event) => {
|
|
424
|
+
const port = event.ports[0];
|
|
425
|
+
const data = event.data;
|
|
426
|
+
const configurationName = data.configurationName;
|
|
427
|
+
let currentDatabase = database[configurationName];
|
|
428
|
+
if (trustedDomains == null) {
|
|
429
|
+
trustedDomains = {};
|
|
430
|
+
}
|
|
431
|
+
if (!currentDatabase) {
|
|
432
|
+
if (trustedDomainsShowAccessToken[configurationName] === void 0) {
|
|
433
|
+
const trustedDomain = trustedDomains[configurationName];
|
|
434
|
+
trustedDomainsShowAccessToken[configurationName] = Array.isArray(trustedDomain) ? false : trustedDomain.showAccessToken;
|
|
435
|
+
}
|
|
436
|
+
database[configurationName] = {
|
|
437
|
+
tokens: null,
|
|
438
|
+
state: null,
|
|
439
|
+
codeVerifier: null,
|
|
440
|
+
oidcServerConfiguration: null,
|
|
441
|
+
oidcConfiguration: void 0,
|
|
442
|
+
nonce: null,
|
|
443
|
+
status: null,
|
|
444
|
+
configurationName,
|
|
445
|
+
hideAccessToken: !trustedDomainsShowAccessToken[configurationName]
|
|
446
|
+
};
|
|
447
|
+
currentDatabase = database[configurationName];
|
|
448
|
+
if (!trustedDomains[configurationName]) {
|
|
449
|
+
trustedDomains[configurationName] = [];
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
switch (data.type) {
|
|
453
|
+
case "clear":
|
|
454
|
+
currentDatabase.tokens = null;
|
|
455
|
+
currentDatabase.state = null;
|
|
456
|
+
currentDatabase.codeVerifier = null;
|
|
457
|
+
currentDatabase.status = data.data.status;
|
|
458
|
+
port.postMessage({ configurationName });
|
|
459
|
+
return;
|
|
460
|
+
case "init": {
|
|
461
|
+
const oidcServerConfiguration = data.data.oidcServerConfiguration;
|
|
462
|
+
const trustedDomain = trustedDomains[configurationName];
|
|
463
|
+
const domains = getDomains(trustedDomain, "oidc");
|
|
464
|
+
if (!domains.find((f) => f === acceptAnyDomainToken)) {
|
|
465
|
+
[
|
|
466
|
+
oidcServerConfiguration.tokenEndpoint,
|
|
467
|
+
oidcServerConfiguration.revocationEndpoint,
|
|
468
|
+
oidcServerConfiguration.userInfoEndpoint,
|
|
469
|
+
oidcServerConfiguration.issuer
|
|
470
|
+
].forEach((url) => {
|
|
471
|
+
checkDomain(domains, url);
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
currentDatabase.oidcServerConfiguration = oidcServerConfiguration;
|
|
475
|
+
currentDatabase.oidcConfiguration = data.data.oidcConfiguration;
|
|
476
|
+
const where = data.data.where;
|
|
477
|
+
if (where === "loginCallbackAsync" || where === "tryKeepExistingSessionAsync") {
|
|
478
|
+
currentLoginCallbackConfigurationName = configurationName;
|
|
479
|
+
} else {
|
|
480
|
+
currentLoginCallbackConfigurationName = null;
|
|
481
|
+
}
|
|
482
|
+
if (!currentDatabase.tokens) {
|
|
483
|
+
port.postMessage({
|
|
484
|
+
tokens: null,
|
|
485
|
+
status: currentDatabase.status,
|
|
486
|
+
configurationName
|
|
487
|
+
});
|
|
488
|
+
} else {
|
|
489
|
+
const tokens = {
|
|
490
|
+
...currentDatabase.tokens
|
|
491
|
+
};
|
|
492
|
+
if (currentDatabase.hideAccessToken) {
|
|
493
|
+
tokens.access_token = TOKEN.ACCESS_TOKEN + "_" + configurationName;
|
|
494
|
+
}
|
|
495
|
+
if (tokens.refresh_token) {
|
|
496
|
+
tokens.refresh_token = TOKEN.REFRESH_TOKEN + "_" + configurationName;
|
|
497
|
+
}
|
|
498
|
+
if (tokens.idTokenPayload && tokens.idTokenPayload.nonce && currentDatabase.nonce != null) {
|
|
499
|
+
tokens.idTokenPayload.nonce = TOKEN.NONCE_TOKEN + "_" + configurationName;
|
|
500
|
+
}
|
|
501
|
+
port.postMessage({
|
|
502
|
+
tokens,
|
|
503
|
+
status: currentDatabase.status,
|
|
504
|
+
configurationName
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
case "setState":
|
|
510
|
+
currentDatabase.state = data.data.state;
|
|
511
|
+
port.postMessage({ configurationName });
|
|
512
|
+
return;
|
|
513
|
+
case "getState": {
|
|
514
|
+
const state = currentDatabase.state;
|
|
515
|
+
port.postMessage({ configurationName, state });
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
case "setCodeVerifier":
|
|
519
|
+
currentDatabase.codeVerifier = data.data.codeVerifier;
|
|
520
|
+
port.postMessage({ configurationName });
|
|
521
|
+
return;
|
|
522
|
+
case "getCodeVerifier": {
|
|
523
|
+
port.postMessage({
|
|
524
|
+
configurationName,
|
|
525
|
+
codeVerifier: currentDatabase.codeVerifier != null ? TOKEN.CODE_VERIFIER + "_" + configurationName : null
|
|
526
|
+
});
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
case "setSessionState":
|
|
530
|
+
currentDatabase.sessionState = data.data.sessionState;
|
|
531
|
+
port.postMessage({ configurationName });
|
|
532
|
+
return;
|
|
533
|
+
case "getSessionState": {
|
|
534
|
+
const sessionState = currentDatabase.sessionState;
|
|
535
|
+
port.postMessage({ configurationName, sessionState });
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
case "setNonce": {
|
|
539
|
+
const nonce = data.data.nonce;
|
|
540
|
+
if (nonce) {
|
|
541
|
+
currentDatabase.nonce = nonce;
|
|
542
|
+
}
|
|
543
|
+
port.postMessage({ configurationName });
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
case "getNonce": {
|
|
547
|
+
const keyNonce = TOKEN.NONCE_TOKEN + "_" + configurationName;
|
|
548
|
+
const nonce = currentDatabase.nonce ? keyNonce : null;
|
|
549
|
+
port.postMessage({ configurationName, nonce });
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
default:
|
|
553
|
+
currentDatabase.items = { ...data.data };
|
|
554
|
+
port.postMessage({ configurationName });
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
_self.addEventListener("install", handleInstall);
|
|
558
|
+
_self.addEventListener("activate", handleActivate);
|
|
559
|
+
_self.addEventListener("fetch", handleFetch);
|
|
560
|
+
_self.addEventListener("message", handleMessage);
|
|
561
|
+
//# sourceMappingURL=OidcServiceWorker.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Add bellow trusted domains, access tokens will automatically injected to be send to
|
|
2
|
+
// trusted domain can also be a path like https://www.myapi.com/users,
|
|
3
|
+
// then all subroute like https://www.myapi.com/useers/1 will be authorized to send access_token to.
|
|
4
|
+
|
|
5
|
+
// Domains used by OIDC server must be also declared here
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
7
|
+
const trustedDomains = {
|
|
8
|
+
default: ['https://demo.duendesoftware.com', 'https://kdhttps.auth0.com'],
|
|
9
|
+
config_classic: ['https://demo.duendesoftware.com'],
|
|
10
|
+
config_without_silent_login: ['https://demo.duendesoftware.com'],
|
|
11
|
+
config_without_refresh_token: ['https://demo.duendesoftware.com'],
|
|
12
|
+
config_without_refresh_token_silent_login: ['https://demo.duendesoftware.com'],
|
|
13
|
+
config_google: ['https://oauth2.googleapis.com', 'https://openidconnect.googleapis.com'],
|
|
14
|
+
config_with_hash: ['https://demo.duendesoftware.com'],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Service worker will continue to give access token to the JavaScript client
|
|
18
|
+
// Ideal to hide refresh token from client JavaScript, but to retrieve access_token for some
|
|
19
|
+
// scenarios which require it. For example, to send it via websocket connection.
|
|
20
|
+
trustedDomains.config_show_access_token = { domains : ["https://demo.duendesoftware.com"], showAccessToken: true };
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
// This example defines domains used by OIDC server separately from domains to which access tokens will be injected.
|
|
24
|
+
trustedDomains.config_separate_oidc_access_token_domains = {
|
|
25
|
+
oidcDomains: ["https://demo.duendesoftware.com"],
|
|
26
|
+
accessTokenDomains: ["https://myapi"]
|
|
27
|
+
};
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/src/cache.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,uEAexB,CAAC;AAEF,eAAO,MAAM,QAAQ,gEAMpB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CheckSessionIFrame } from './checkSessionIFrame.js';
|
|
2
|
+
import { OidcConfiguration } from './types.js';
|
|
3
|
+
export declare const startCheckSessionAsync: (oidc: any, oidcDatabase: any, configuration: OidcConfiguration) => (checkSessionIFrameUri: any, clientId: any, sessionState: any, isSilentSignin?: boolean) => Promise<CheckSessionIFrame>;
|
|
4
|
+
//# sourceMappingURL=checkSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkSession.d.ts","sourceRoot":"","sources":["../src/src/checkSession.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/C,eAAO,MAAM,sBAAsB,SAAS,GAAG,gBAAe,GAAG,iBAAiB,iBAAiB,4HAsDlG,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class CheckSessionIFrame {
|
|
2
|
+
private readonly _client_id;
|
|
3
|
+
private readonly _callback;
|
|
4
|
+
private _url;
|
|
5
|
+
private readonly _interval;
|
|
6
|
+
private readonly _stopOnError;
|
|
7
|
+
private readonly _frame_origin;
|
|
8
|
+
private readonly _frame;
|
|
9
|
+
private _boundMessageEvent;
|
|
10
|
+
private _timer;
|
|
11
|
+
constructor(callback: any, client_id: any, url: any, interval?: number, stopOnError?: boolean);
|
|
12
|
+
load(): Promise<void>;
|
|
13
|
+
_message(e: any): void;
|
|
14
|
+
start(session_state: any): void;
|
|
15
|
+
stop(): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=checkSessionIFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkSessionIFrame.d.ts","sourceRoot":"","sources":["../src/src/checkSessionIFrame.ts"],"names":[],"mappings":"AAIA,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAM;IAChC,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,kBAAkB,CAAM;IAChC,OAAO,CAAC,MAAM,CAAS;gBACX,QAAQ,KAAA,EAAE,SAAS,KAAA,EAAE,GAAG,KAAA,EAAE,QAAQ,SAAkB,EAAE,WAAW,UAAO;IAoBpF,IAAI;IAWJ,QAAQ,CAAC,CAAC,KAAA;IAoBV,KAAK,CAAC,aAAa,KAAA;IAUnB,IAAI;CAOP"}
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/src/crypto.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,cAAc,SAAU,MAAM,WAYxC,CAAC;AAEJ,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,cAQzC;AACC,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,QAAQ,MAAM,CAcnE,CAAC"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const eventNames: {
|
|
2
|
+
service_worker_not_supported_by_browser: string;
|
|
3
|
+
token_aquired: string;
|
|
4
|
+
logout_from_another_tab: string;
|
|
5
|
+
logout_from_same_tab: string;
|
|
6
|
+
token_renewed: string;
|
|
7
|
+
token_timer: string;
|
|
8
|
+
loginAsync_begin: string;
|
|
9
|
+
loginAsync_error: string;
|
|
10
|
+
loginCallbackAsync_begin: string;
|
|
11
|
+
loginCallbackAsync_end: string;
|
|
12
|
+
loginCallbackAsync_error: string;
|
|
13
|
+
refreshTokensAsync_begin: string;
|
|
14
|
+
refreshTokensAsync: string;
|
|
15
|
+
refreshTokensAsync_end: string;
|
|
16
|
+
refreshTokensAsync_error: string;
|
|
17
|
+
refreshTokensAsync_silent_error: string;
|
|
18
|
+
tryKeepExistingSessionAsync_begin: string;
|
|
19
|
+
tryKeepExistingSessionAsync_end: string;
|
|
20
|
+
tryKeepExistingSessionAsync_error: string;
|
|
21
|
+
silentLoginAsync_begin: string;
|
|
22
|
+
silentLoginAsync: string;
|
|
23
|
+
silentLoginAsync_end: string;
|
|
24
|
+
silentLoginAsync_error: string;
|
|
25
|
+
syncTokensAsync_begin: string;
|
|
26
|
+
syncTokensAsync_end: string;
|
|
27
|
+
syncTokensAsync_error: string;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/src/events.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BtB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { getFetchDefault } from './oidc.js';
|
|
2
|
+
export { TokenRenewMode } from './parseTokens.js';
|
|
3
|
+
export { getParseQueryStringFromLocation, getPath } from './route-utils';
|
|
4
|
+
export type { AuthorityConfiguration, Fetch, OidcConfiguration, StringMap, } from './types.js';
|
|
5
|
+
export { type OidcUserInfo, VanillaOidc } from './vanillaOidc.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,+BAA+B,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EACV,sBAAsB,EACtB,KAAK,EACL,iBAAiB,EACjB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|