@axa-fr/oidc-client-service-worker 7.27.3 → 7.27.4

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.
@@ -1,967 +1,789 @@
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"
1
+ //#region src/constants.ts
2
+ var scriptFilename = "OidcTrustedDomains.js";
3
+ var 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
8
  };
9
- const TokenRenewMode = {
10
- access_token_invalid: "access_token_invalid",
11
- id_token_invalid: "id_token_invalid"
9
+ var 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"
12
13
  };
13
- const openidWellknownUrlEndWith = "/.well-known/openid-configuration";
14
+ //#endregion
15
+ //#region src/jwt.ts
14
16
  function strToUint8(str) {
15
- return new TextEncoder().encode(str);
17
+ return new TextEncoder().encode(str);
16
18
  }
17
19
  function binToUrlBase64(bin) {
18
- return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+/g, "");
20
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+/g, "");
19
21
  }
20
22
  function utf8ToBinaryString(str) {
21
- const escstr = encodeURIComponent(str);
22
- return escstr.replace(/%([0-9A-F]{2})/g, function(match, p1) {
23
- return String.fromCharCode(parseInt(p1, 16));
24
- });
23
+ return encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
24
+ return String.fromCharCode(parseInt(p1, 16));
25
+ });
25
26
  }
26
- const uint8ToUrlBase64 = (uint8) => {
27
- let bin = "";
28
- uint8.forEach(function(code) {
29
- bin += String.fromCharCode(code);
30
- });
31
- return binToUrlBase64(bin);
27
+ var uint8ToUrlBase64 = (uint8) => {
28
+ let bin = "";
29
+ uint8.forEach(function(code) {
30
+ bin += String.fromCharCode(code);
31
+ });
32
+ return binToUrlBase64(bin);
32
33
  };
33
34
  function strToUrlBase64(str) {
34
- return binToUrlBase64(utf8ToBinaryString(str));
35
+ return binToUrlBase64(utf8ToBinaryString(str));
35
36
  }
36
- const defaultDemonstratingProofOfPossessionConfiguration = {
37
- importKeyAlgorithm: {
38
- name: "ECDSA",
39
- namedCurve: "P-256",
40
- hash: { name: "ES256" }
41
- },
42
- signAlgorithm: { name: "ECDSA", hash: { name: "SHA-256" } },
43
- generateKeyAlgorithm: {
44
- name: "ECDSA",
45
- namedCurve: "P-256"
46
- },
47
- digestAlgorithm: { name: "SHA-256" },
48
- jwtHeaderAlgorithm: "ES256"
37
+ var defaultDemonstratingProofOfPossessionConfiguration = {
38
+ importKeyAlgorithm: {
39
+ name: "ECDSA",
40
+ namedCurve: "P-256",
41
+ hash: { name: "ES256" }
42
+ },
43
+ signAlgorithm: {
44
+ name: "ECDSA",
45
+ hash: { name: "SHA-256" }
46
+ },
47
+ generateKeyAlgorithm: {
48
+ name: "ECDSA",
49
+ namedCurve: "P-256"
50
+ },
51
+ digestAlgorithm: { name: "SHA-256" },
52
+ jwtHeaderAlgorithm: "ES256"
49
53
  };
50
- const sign = (w) => async (jwk, headers, claims, demonstratingProofOfPossessionConfiguration, jwtHeaderType = "dpop+jwt") => {
51
- jwk = Object.assign({}, jwk);
52
- headers.typ = jwtHeaderType;
53
- headers.alg = demonstratingProofOfPossessionConfiguration.jwtHeaderAlgorithm;
54
- switch (headers.alg) {
55
- case "ES256":
56
- headers.jwk = { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y };
57
- break;
58
- case "RS256":
59
- headers.jwk = { kty: jwk.kty, n: jwk.n, e: jwk.e, kid: headers.kid };
60
- break;
61
- default:
62
- throw new Error("Unknown or not implemented JWS algorithm");
63
- }
64
- const jws = {
65
- // @ts-ignore
66
- // JWT "headers" really means JWS "protected headers"
67
- protected: strToUrlBase64(JSON.stringify(headers)),
68
- // @ts-ignore
69
- // JWT "claims" are really a JSON-defined JWS "payload"
70
- payload: strToUrlBase64(JSON.stringify(claims))
71
- };
72
- const keyType = demonstratingProofOfPossessionConfiguration.importKeyAlgorithm;
73
- const exportable = true;
74
- const privileges = ["sign"];
75
- const privateKey = await w.crypto.subtle.importKey("jwk", jwk, keyType, exportable, privileges);
76
- const data = strToUint8(`${jws.protected}.${jws.payload}`);
77
- const signatureType = demonstratingProofOfPossessionConfiguration.signAlgorithm;
78
- const signature = await w.crypto.subtle.sign(signatureType, privateKey, data);
79
- jws.signature = uint8ToUrlBase64(new Uint8Array(signature));
80
- return `${jws.protected}.${jws.payload}.${jws.signature}`;
54
+ var sign = (w) => async (jwk, headers, claims, demonstratingProofOfPossessionConfiguration, jwtHeaderType = "dpop+jwt") => {
55
+ jwk = Object.assign({}, jwk);
56
+ headers.typ = jwtHeaderType;
57
+ headers.alg = demonstratingProofOfPossessionConfiguration.jwtHeaderAlgorithm;
58
+ switch (headers.alg) {
59
+ case "ES256":
60
+ headers.jwk = {
61
+ kty: jwk.kty,
62
+ crv: jwk.crv,
63
+ x: jwk.x,
64
+ y: jwk.y
65
+ };
66
+ break;
67
+ case "RS256":
68
+ headers.jwk = {
69
+ kty: jwk.kty,
70
+ n: jwk.n,
71
+ e: jwk.e,
72
+ kid: headers.kid
73
+ };
74
+ break;
75
+ default: throw new Error("Unknown or not implemented JWS algorithm");
76
+ }
77
+ const jws = {
78
+ protected: strToUrlBase64(JSON.stringify(headers)),
79
+ payload: strToUrlBase64(JSON.stringify(claims))
80
+ };
81
+ const keyType = demonstratingProofOfPossessionConfiguration.importKeyAlgorithm;
82
+ const privateKey = await w.crypto.subtle.importKey("jwk", jwk, keyType, true, ["sign"]);
83
+ const data = strToUint8(`${jws.protected}.${jws.payload}`);
84
+ const signatureType = demonstratingProofOfPossessionConfiguration.signAlgorithm;
85
+ const signature = await w.crypto.subtle.sign(signatureType, privateKey, data);
86
+ jws.signature = uint8ToUrlBase64(new Uint8Array(signature));
87
+ return `${jws.protected}.${jws.payload}.${jws.signature}`;
81
88
  };
82
- const JWT = { sign };
83
- const generate = (w) => async (generateKeyAlgorithm) => {
84
- const keyType = generateKeyAlgorithm;
85
- const exportable = true;
86
- const privileges = ["sign", "verify"];
87
- const key = await w.crypto.subtle.generateKey(keyType, exportable, privileges);
88
- return await w.crypto.subtle.exportKey("jwk", key.privateKey);
89
+ var JWT = { sign };
90
+ var generate = (w) => async (generateKeyAlgorithm) => {
91
+ const keyType = generateKeyAlgorithm;
92
+ const key = await w.crypto.subtle.generateKey(keyType, true, ["sign", "verify"]);
93
+ return await w.crypto.subtle.exportKey("jwk", key.privateKey);
89
94
  };
90
- const neuter = (jwk) => {
91
- const copy = Object.assign({}, jwk);
92
- delete copy.d;
93
- copy.key_ops = ["verify"];
94
- return copy;
95
+ var neuter = (jwk) => {
96
+ const copy = Object.assign({}, jwk);
97
+ delete copy.d;
98
+ copy.key_ops = ["verify"];
99
+ return copy;
95
100
  };
96
- const EC = {
97
- generate,
98
- neuter
101
+ var EC = {
102
+ generate,
103
+ neuter
99
104
  };
100
- const thumbprint = (w) => async (jwk, digestAlgorithm) => {
101
- let sortedPub;
102
- switch (jwk.kty) {
103
- case "EC":
104
- sortedPub = '{"crv":"CRV","kty":"EC","x":"X","y":"Y"}'.replace("CRV", jwk.crv).replace("X", jwk.x).replace("Y", jwk.y);
105
- break;
106
- case "RSA":
107
- sortedPub = '{"e":"E","kty":"RSA","n":"N"}'.replace("E", jwk.e).replace("N", jwk.n);
108
- break;
109
- default:
110
- throw new Error("Unknown or not implemented JWK type");
111
- }
112
- const hash = await w.crypto.subtle.digest(digestAlgorithm, strToUint8(sortedPub));
113
- return uint8ToUrlBase64(new Uint8Array(hash));
105
+ var thumbprint = (w) => async (jwk, digestAlgorithm) => {
106
+ let sortedPub;
107
+ switch (jwk.kty) {
108
+ case "EC":
109
+ sortedPub = "{\"crv\":\"CRV\",\"kty\":\"EC\",\"x\":\"X\",\"y\":\"Y\"}".replace("CRV", jwk.crv).replace("X", jwk.x).replace("Y", jwk.y);
110
+ break;
111
+ case "RSA":
112
+ sortedPub = "{\"e\":\"E\",\"kty\":\"RSA\",\"n\":\"N\"}".replace("E", jwk.e).replace("N", jwk.n);
113
+ break;
114
+ default: throw new Error("Unknown or not implemented JWK type");
115
+ }
116
+ const hash = await w.crypto.subtle.digest(digestAlgorithm, strToUint8(sortedPub));
117
+ return uint8ToUrlBase64(new Uint8Array(hash));
114
118
  };
115
- const JWK = { thumbprint };
116
- const generateJwkAsync = (w) => async (generateKeyAlgorithm) => {
117
- const jwk = await EC.generate(w)(generateKeyAlgorithm);
118
- return jwk;
119
+ var JWK = { thumbprint };
120
+ var generateJwkAsync = (w) => async (generateKeyAlgorithm) => {
121
+ return await EC.generate(w)(generateKeyAlgorithm);
119
122
  };
120
- const generateJwtDemonstratingProofOfPossessionAsync = (w) => (demonstratingProofOfPossessionConfiguration) => async (jwk, method = "POST", url, extrasClaims = {}) => {
121
- const claims = {
122
- // https://www.rfc-editor.org/rfc/rfc9449.html#name-concept
123
- jti: btoa(guid()),
124
- htm: method,
125
- htu: url,
126
- iat: Math.round(Date.now() / 1e3),
127
- ...extrasClaims
128
- };
129
- const kid = await JWK.thumbprint(w)(
130
- jwk,
131
- demonstratingProofOfPossessionConfiguration.digestAlgorithm
132
- );
133
- const jwt = await JWT.sign(w)(
134
- jwk,
135
- { kid },
136
- claims,
137
- demonstratingProofOfPossessionConfiguration
138
- );
139
- return jwt;
123
+ var generateJwtDemonstratingProofOfPossessionAsync = (w) => (demonstratingProofOfPossessionConfiguration) => async (jwk, method = "POST", url, extrasClaims = {}) => {
124
+ const claims = {
125
+ jti: btoa(guid()),
126
+ htm: method,
127
+ htu: url,
128
+ iat: Math.round(Date.now() / 1e3),
129
+ ...extrasClaims
130
+ };
131
+ const kid = await JWK.thumbprint(w)(jwk, demonstratingProofOfPossessionConfiguration.digestAlgorithm);
132
+ return await JWT.sign(w)(jwk, { kid }, claims, demonstratingProofOfPossessionConfiguration);
140
133
  };
141
- const guid = () => {
142
- const guidHolder = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
143
- const hex = "0123456789abcdef";
144
- let r = 0;
145
- let guidResponse = "";
146
- for (let i = 0; i < 36; i++) {
147
- if (guidHolder[i] !== "-" && guidHolder[i] !== "4") {
148
- r = Math.random() * 16 | 0;
149
- }
150
- if (guidHolder[i] === "x") {
151
- guidResponse += hex[r];
152
- } else if (guidHolder[i] === "y") {
153
- r &= 3;
154
- r |= 8;
155
- guidResponse += hex[r];
156
- } else {
157
- guidResponse += guidHolder[i];
158
- }
159
- }
160
- return guidResponse;
134
+ var guid = () => {
135
+ const guidHolder = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
136
+ const hex = "0123456789abcdef";
137
+ let r = 0;
138
+ let guidResponse = "";
139
+ for (let i = 0; i < 36; i++) {
140
+ if (guidHolder[i] !== "-" && guidHolder[i] !== "4") r = Math.random() * 16 | 0;
141
+ if (guidHolder[i] === "x") guidResponse += hex[r];
142
+ else if (guidHolder[i] === "y") {
143
+ r &= 3;
144
+ r |= 8;
145
+ guidResponse += hex[r];
146
+ } else guidResponse += guidHolder[i];
147
+ }
148
+ return guidResponse;
161
149
  };
150
+ //#endregion
151
+ //#region src/crypto.ts
162
152
  function textEncodeLite(str) {
163
- const buf = new ArrayBuffer(str.length);
164
- const bufView = new Uint8Array(buf);
165
- for (let i = 0; i < str.length; i++) {
166
- bufView[i] = str.charCodeAt(i);
167
- }
168
- return bufView;
153
+ const buf = new ArrayBuffer(str.length);
154
+ const bufView = new Uint8Array(buf);
155
+ for (let i = 0; i < str.length; i++) bufView[i] = str.charCodeAt(i);
156
+ return bufView;
169
157
  }
170
158
  function base64urlOfHashOfASCIIEncodingAsync(code) {
171
- return new Promise((resolve, reject) => {
172
- crypto.subtle.digest("SHA-256", textEncodeLite(code)).then(
173
- (buffer) => {
174
- return resolve(uint8ToUrlBase64(new Uint8Array(buffer)));
175
- },
176
- (error) => reject(error)
177
- );
178
- });
159
+ return new Promise((resolve, reject) => {
160
+ crypto.subtle.digest("SHA-256", textEncodeLite(code)).then((buffer) => {
161
+ return resolve(uint8ToUrlBase64(new Uint8Array(buffer)));
162
+ }, (error) => reject(error));
163
+ });
179
164
  }
180
- const isDpop = (trustedDomain) => {
181
- if (Array.isArray(trustedDomain)) {
182
- return false;
183
- }
184
- return trustedDomain.demonstratingProofOfPossession ?? false;
165
+ //#endregion
166
+ //#region src/dpop.ts
167
+ var isDpop = (trustedDomain) => {
168
+ if (Array.isArray(trustedDomain)) return false;
169
+ return trustedDomain.demonstratingProofOfPossession ?? false;
185
170
  };
186
- const getDpopConfiguration = (trustedDomain) => {
187
- if (!isDpop(trustedDomain)) {
188
- return null;
189
- }
190
- if (Array.isArray(trustedDomain)) {
191
- return null;
192
- }
193
- return trustedDomain.demonstratingProofOfPossessionConfiguration ?? defaultDemonstratingProofOfPossessionConfiguration;
171
+ var getDpopConfiguration = (trustedDomain) => {
172
+ if (!isDpop(trustedDomain)) return null;
173
+ if (Array.isArray(trustedDomain)) return null;
174
+ return trustedDomain.demonstratingProofOfPossessionConfiguration ?? defaultDemonstratingProofOfPossessionConfiguration;
194
175
  };
195
- const getDpopOnlyWhenDpopHeaderPresent = (trustedDomain) => {
196
- if (!isDpop(trustedDomain)) {
197
- return null;
198
- }
199
- if (Array.isArray(trustedDomain)) {
200
- return null;
201
- }
202
- return trustedDomain.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent ?? true;
176
+ var getDpopOnlyWhenDpopHeaderPresent = (trustedDomain) => {
177
+ if (!isDpop(trustedDomain)) return null;
178
+ if (Array.isArray(trustedDomain)) return null;
179
+ return trustedDomain.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent ?? true;
203
180
  };
181
+ //#endregion
182
+ //#region src/utils/normalizeUrl.ts
204
183
  function normalizeUrl(url) {
205
- try {
206
- return new URL(url).toString();
207
- } catch (error) {
208
- console.error(`Failed to normalize url: ${url}`, error);
209
- return url;
210
- }
184
+ try {
185
+ return new URL(url).toString();
186
+ } catch (error) {
187
+ console.error(`Failed to normalize url: ${url}`, error);
188
+ return url;
189
+ }
211
190
  }
191
+ //#endregion
192
+ //#region src/utils/domains.ts
212
193
  function checkDomain(domains, endpoint) {
213
- if (!endpoint) {
214
- return;
215
- }
216
- const domain = domains.find((domain2) => {
217
- let testable;
218
- if (typeof domain2 === "string") {
219
- testable = new RegExp(`^${domain2}`);
220
- } else {
221
- testable = domain2;
222
- }
223
- return testable.test?.(endpoint);
224
- });
225
- if (!domain) {
226
- throw new Error(
227
- "Domain " + endpoint + " is not trusted, please add domain in " + scriptFilename
228
- );
229
- }
194
+ if (!endpoint) return;
195
+ if (!domains.find((domain) => {
196
+ let testable;
197
+ if (typeof domain === "string") testable = new RegExp(`^${domain}`);
198
+ else testable = domain;
199
+ return testable.test?.(endpoint);
200
+ })) throw new Error("Domain " + endpoint + " is not trusted, please add domain in " + scriptFilename);
230
201
  }
231
- const getDomains = (trustedDomain, type) => {
232
- if (Array.isArray(trustedDomain)) {
233
- return trustedDomain;
234
- }
235
- return trustedDomain[`${type}Domains`] ?? trustedDomain.domains ?? [];
202
+ var getDomains = (trustedDomain, type) => {
203
+ if (Array.isArray(trustedDomain)) return trustedDomain;
204
+ return trustedDomain[`${type}Domains`] ?? trustedDomain.domains ?? [];
236
205
  };
237
- const getCurrentDatabaseDomain = (database2, url, trustedDomains2) => {
238
- if (url.endsWith(openidWellknownUrlEndWith)) {
239
- return null;
240
- }
241
- const datatases = [];
242
- for (const [key, currentDatabase] of Object.entries(database2)) {
243
- const oidcServerConfiguration = currentDatabase.oidcServerConfiguration;
244
- if (!oidcServerConfiguration) {
245
- continue;
246
- }
247
- if (oidcServerConfiguration.tokenEndpoint && url === normalizeUrl(oidcServerConfiguration.tokenEndpoint)) {
248
- continue;
249
- }
250
- if (oidcServerConfiguration.revocationEndpoint && url === normalizeUrl(oidcServerConfiguration.revocationEndpoint)) {
251
- continue;
252
- }
253
- const trustedDomain = trustedDomains2 == null ? [] : trustedDomains2[key.split("#")[0]];
254
- const domains = getDomains(trustedDomain, "accessToken");
255
- const domainsToSendTokens = oidcServerConfiguration.userInfoEndpoint ? [normalizeUrl(oidcServerConfiguration.userInfoEndpoint), ...domains] : [...domains];
256
- let hasToSendToken = false;
257
- if (domainsToSendTokens.find((f) => f === acceptAnyDomainToken)) {
258
- hasToSendToken = true;
259
- } else {
260
- for (let i = 0; i < domainsToSendTokens.length; i++) {
261
- let domain = domainsToSendTokens[i];
262
- if (typeof domain === "string") {
263
- domain = new RegExp(`^${domain}`);
264
- }
265
- if (domain.test?.(url)) {
266
- hasToSendToken = true;
267
- break;
268
- }
269
- }
270
- }
271
- if (hasToSendToken) {
272
- if (currentDatabase.tokens) {
273
- datatases.push(currentDatabase);
274
- }
275
- }
276
- }
277
- return datatases;
206
+ var getCurrentDatabaseDomain = (database, url, trustedDomains) => {
207
+ if (url.endsWith("/.well-known/openid-configuration")) return null;
208
+ const datatases = [];
209
+ for (const [key, currentDatabase] of Object.entries(database)) {
210
+ const oidcServerConfiguration = currentDatabase.oidcServerConfiguration;
211
+ if (!oidcServerConfiguration) continue;
212
+ if (oidcServerConfiguration.tokenEndpoint && url === normalizeUrl(oidcServerConfiguration.tokenEndpoint)) continue;
213
+ if (oidcServerConfiguration.revocationEndpoint && url === normalizeUrl(oidcServerConfiguration.revocationEndpoint)) continue;
214
+ const domains = getDomains(trustedDomains == null ? [] : trustedDomains[key.split("#")[0]], "accessToken");
215
+ const domainsToSendTokens = oidcServerConfiguration.userInfoEndpoint ? [normalizeUrl(oidcServerConfiguration.userInfoEndpoint), ...domains] : [...domains];
216
+ let hasToSendToken = false;
217
+ if (domainsToSendTokens.find((f) => f === "*")) hasToSendToken = true;
218
+ else for (let i = 0; i < domainsToSendTokens.length; i++) {
219
+ let domain = domainsToSendTokens[i];
220
+ if (typeof domain === "string") domain = new RegExp(`^${domain}`);
221
+ if (domain.test?.(url)) {
222
+ hasToSendToken = true;
223
+ break;
224
+ }
225
+ }
226
+ if (hasToSendToken) {
227
+ if (currentDatabase.tokens) datatases.push(currentDatabase);
228
+ }
229
+ }
230
+ return datatases;
278
231
  };
232
+ //#endregion
233
+ //#region src/utils/serializeHeaders.ts
279
234
  function serializeHeaders(headers) {
280
- const headersObj = {};
281
- for (const key of headers.keys()) {
282
- if (headers.has(key)) {
283
- headersObj[key] = headers.get(key);
284
- }
285
- }
286
- return headersObj;
235
+ const headersObj = {};
236
+ for (const key of headers.keys()) if (headers.has(key)) headersObj[key] = headers.get(key);
237
+ return headersObj;
287
238
  }
288
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
239
+ //#endregion
240
+ //#region src/utils/sleep.ts
241
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
242
+ //#endregion
243
+ //#region src/utils/strings.ts
244
+ /**
245
+ * Count occurances of letter in string
246
+ * @param str
247
+ * @param find
248
+ * @returns
249
+ */
289
250
  function countLetter(str, find) {
290
- return str.split(find).length - 1;
251
+ return str.split(find).length - 1;
291
252
  }
292
- const parseJwt = (payload) => {
293
- return JSON.parse(b64DecodeUnicode(payload.replaceAll(/-/g, "+").replaceAll(/_/g, "/")));
253
+ //#endregion
254
+ //#region src/utils/tokens.ts
255
+ var parseJwt = (payload) => {
256
+ return JSON.parse(b64DecodeUnicode(payload.replaceAll(/-/g, "+").replaceAll(/_/g, "/")));
294
257
  };
295
258
  function b64DecodeUnicode(str) {
296
- return decodeURIComponent(
297
- Array.prototype.map.call(atob(str), (c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
298
- );
259
+ return decodeURIComponent(Array.prototype.map.call(atob(str), (c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join(""));
299
260
  }
300
261
  function computeTimeLeft(refreshTimeBeforeTokensExpirationInSecond, expiresAt) {
301
- const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
302
- return Math.round(expiresAt - refreshTimeBeforeTokensExpirationInSecond - currentTimeUnixSecond);
262
+ const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
263
+ return Math.round(expiresAt - refreshTimeBeforeTokensExpirationInSecond - currentTimeUnixSecond);
303
264
  }
304
265
  function isTokensValid(tokens) {
305
- if (!tokens) {
306
- return false;
307
- }
308
- return computeTimeLeft(0, tokens.expiresAt) > 0;
266
+ if (!tokens) return false;
267
+ return computeTimeLeft(0, tokens.expiresAt) > 0;
309
268
  }
310
- const extractTokenPayload = (token) => {
311
- try {
312
- if (!token) {
313
- return null;
314
- }
315
- if (countLetter(token, ".") === 2) {
316
- return parseJwt(token.split(".")[1]);
317
- } else {
318
- return null;
319
- }
320
- } catch (e) {
321
- console.warn(e);
322
- }
323
- return null;
269
+ var extractTokenPayload = (token) => {
270
+ try {
271
+ if (!token) return null;
272
+ if (countLetter(token, ".") === 2) return parseJwt(token.split(".")[1]);
273
+ else return null;
274
+ } catch (e) {
275
+ console.warn(e);
276
+ }
277
+ return null;
324
278
  };
325
- const isTokensOidcValid = (tokens, nonce, oidcServerConfiguration) => {
326
- if (tokens.idTokenPayload) {
327
- const idTokenPayload = tokens.idTokenPayload;
328
- if (idTokenPayload && oidcServerConfiguration.issuer !== idTokenPayload.iss) {
329
- return {
330
- isValid: false,
331
- reason: `Issuer does not match (oidcServerConfiguration issuer) ${oidcServerConfiguration.issuer} !== (idTokenPayload issuer) ${idTokenPayload.iss}`
332
- };
333
- }
334
- const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
335
- if (idTokenPayload && idTokenPayload.exp && idTokenPayload.exp < currentTimeUnixSecond) {
336
- return {
337
- isValid: false,
338
- reason: `Token expired at (idTokenPayload exp) ${idTokenPayload.exp} < (currentTimeUnixSecond) ${currentTimeUnixSecond}`
339
- };
340
- }
341
- const timeInSevenDays = 60 * 60 * 24 * 7;
342
- if (idTokenPayload && idTokenPayload.iat && idTokenPayload.iat + timeInSevenDays < currentTimeUnixSecond) {
343
- return {
344
- isValid: false,
345
- reason: `Token is used from too long time (idTokenPayload iat + timeInSevenDays) ${idTokenPayload.iat + timeInSevenDays} < (currentTimeUnixSecond) ${currentTimeUnixSecond}`
346
- };
347
- }
348
- if (idTokenPayload && nonce && idTokenPayload.nonce && idTokenPayload.nonce !== nonce) {
349
- return {
350
- isValid: false,
351
- reason: `Nonce does not match (nonce) ${nonce} !== (idTokenPayload nonce) ${idTokenPayload.nonce}`
352
- };
353
- }
354
- }
355
- return { isValid: true, reason: "" };
279
+ var isTokensOidcValid = (tokens, nonce, oidcServerConfiguration) => {
280
+ if (tokens.idTokenPayload) {
281
+ const idTokenPayload = tokens.idTokenPayload;
282
+ if (idTokenPayload && oidcServerConfiguration.issuer !== idTokenPayload.iss) return {
283
+ isValid: false,
284
+ reason: `Issuer does not match (oidcServerConfiguration issuer) ${oidcServerConfiguration.issuer} !== (idTokenPayload issuer) ${idTokenPayload.iss}`
285
+ };
286
+ const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
287
+ if (idTokenPayload && idTokenPayload.exp && idTokenPayload.exp < currentTimeUnixSecond) return {
288
+ isValid: false,
289
+ reason: `Token expired at (idTokenPayload exp) ${idTokenPayload.exp} < (currentTimeUnixSecond) ${currentTimeUnixSecond}`
290
+ };
291
+ const timeInSevenDays = 3600 * 24 * 7;
292
+ if (idTokenPayload && idTokenPayload.iat && idTokenPayload.iat + timeInSevenDays < currentTimeUnixSecond) return {
293
+ isValid: false,
294
+ reason: `Token is used from too long time (idTokenPayload iat + timeInSevenDays) ${idTokenPayload.iat + timeInSevenDays} < (currentTimeUnixSecond) ${currentTimeUnixSecond}`
295
+ };
296
+ if (idTokenPayload && nonce && idTokenPayload.nonce && idTokenPayload.nonce !== nonce) return {
297
+ isValid: false,
298
+ reason: `Nonce does not match (nonce) ${nonce} !== (idTokenPayload nonce) ${idTokenPayload.nonce}`
299
+ };
300
+ }
301
+ return {
302
+ isValid: true,
303
+ reason: ""
304
+ };
356
305
  };
357
306
  function extractedIssueAt(tokens, accessTokenPayload, _idTokenPayload) {
358
- if (!tokens.issued_at) {
359
- if (accessTokenPayload && accessTokenPayload.iat) {
360
- return accessTokenPayload.iat;
361
- } else if (_idTokenPayload && _idTokenPayload.iat) {
362
- return _idTokenPayload.iat;
363
- } else {
364
- const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
365
- return currentTimeUnixSecond;
366
- }
367
- } else if (typeof tokens.issued_at == "string") {
368
- return parseInt(tokens.issued_at, 10);
369
- }
370
- return tokens.issued_at;
307
+ if (!tokens.issued_at) if (accessTokenPayload && accessTokenPayload.iat) return accessTokenPayload.iat;
308
+ else if (_idTokenPayload && _idTokenPayload.iat) return _idTokenPayload.iat;
309
+ else return (/* @__PURE__ */ new Date()).getTime() / 1e3;
310
+ else if (typeof tokens.issued_at == "string") return parseInt(tokens.issued_at, 10);
311
+ return tokens.issued_at;
371
312
  }
372
313
  function _hideTokens(tokens, currentDatabaseElement, configurationName) {
373
- if (!tokens.issued_at) {
374
- const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
375
- tokens.issued_at = currentTimeUnixSecond;
376
- } else if (typeof tokens.issued_at == "string") {
377
- tokens.issued_at = parseInt(tokens.issued_at, 10);
378
- }
379
- const accessTokenPayload = extractTokenPayload(tokens.access_token);
380
- const secureTokens = {
381
- ...tokens,
382
- accessTokenPayload
383
- };
384
- if (currentDatabaseElement.hideAccessToken) {
385
- secureTokens.access_token = `${TOKEN.ACCESS_TOKEN}_${configurationName}`;
386
- }
387
- tokens.accessTokenPayload = accessTokenPayload;
388
- const oldTokens = currentDatabaseElement.tokens;
389
- let id_token;
390
- if (oldTokens != null && "id_token" in oldTokens && !("id_token" in tokens)) {
391
- id_token = oldTokens.id_token;
392
- } else {
393
- id_token = tokens.id_token;
394
- }
395
- tokens.id_token = id_token;
396
- let _idTokenPayload = null;
397
- if (id_token) {
398
- _idTokenPayload = extractTokenPayload(id_token);
399
- tokens.idTokenPayload = _idTokenPayload != null ? { ..._idTokenPayload } : null;
400
- if (_idTokenPayload && _idTokenPayload.nonce && currentDatabaseElement.nonce != null) {
401
- const keyNonce = `${TOKEN.NONCE_TOKEN}_${currentDatabaseElement.configurationName}`;
402
- _idTokenPayload.nonce = keyNonce;
403
- }
404
- secureTokens.idTokenPayload = _idTokenPayload;
405
- }
406
- if (tokens.refresh_token) {
407
- secureTokens.refresh_token = `${TOKEN.REFRESH_TOKEN}_${configurationName}`;
408
- }
409
- tokens.issued_at = extractedIssueAt(tokens, accessTokenPayload, _idTokenPayload);
410
- const expireIn = typeof tokens.expires_in == "string" ? parseInt(tokens.expires_in, 10) : tokens.expires_in;
411
- const idTokenExpiresAt = _idTokenPayload && _idTokenPayload.exp ? _idTokenPayload.exp : Number.MAX_VALUE;
412
- const accessTokenExpiresAt = accessTokenPayload && accessTokenPayload.exp ? accessTokenPayload.exp : tokens.issued_at + expireIn;
413
- let expiresAt;
414
- const tokenRenewMode = currentDatabaseElement.oidcConfiguration.token_renew_mode;
415
- if (tokenRenewMode === TokenRenewMode.access_token_invalid) {
416
- expiresAt = accessTokenExpiresAt;
417
- } else if (tokenRenewMode === TokenRenewMode.id_token_invalid) {
418
- expiresAt = idTokenExpiresAt;
419
- } else {
420
- expiresAt = idTokenExpiresAt < accessTokenExpiresAt ? idTokenExpiresAt : accessTokenExpiresAt;
421
- }
422
- secureTokens.expiresAt = expiresAt;
423
- tokens.expiresAt = expiresAt;
424
- const nonce = currentDatabaseElement.nonce ? currentDatabaseElement.nonce.nonce : null;
425
- const { isValid, reason } = isTokensOidcValid(
426
- tokens,
427
- nonce,
428
- currentDatabaseElement.oidcServerConfiguration
429
- );
430
- if (!isValid) {
431
- throw Error(`Tokens are not OpenID valid, reason: ${reason}`);
432
- }
433
- if (oldTokens != null && "refresh_token" in oldTokens && !("refresh_token" in tokens)) {
434
- const refreshToken = oldTokens.refresh_token;
435
- currentDatabaseElement.tokens = {
436
- ...tokens,
437
- refresh_token: refreshToken
438
- };
439
- } else {
440
- currentDatabaseElement.tokens = tokens;
441
- }
442
- currentDatabaseElement.status = "LOGGED_IN";
443
- return secureTokens;
314
+ if (!tokens.issued_at) tokens.issued_at = (/* @__PURE__ */ new Date()).getTime() / 1e3;
315
+ else if (typeof tokens.issued_at == "string") tokens.issued_at = parseInt(tokens.issued_at, 10);
316
+ const accessTokenPayload = extractTokenPayload(tokens.access_token);
317
+ const secureTokens = {
318
+ ...tokens,
319
+ accessTokenPayload
320
+ };
321
+ if (currentDatabaseElement.hideAccessToken) secureTokens.access_token = `${TOKEN.ACCESS_TOKEN}_${configurationName}`;
322
+ tokens.accessTokenPayload = accessTokenPayload;
323
+ const oldTokens = currentDatabaseElement.tokens;
324
+ let id_token;
325
+ if (oldTokens != null && "id_token" in oldTokens && !("id_token" in tokens)) id_token = oldTokens.id_token;
326
+ else id_token = tokens.id_token;
327
+ tokens.id_token = id_token;
328
+ let _idTokenPayload = null;
329
+ if (id_token) {
330
+ _idTokenPayload = extractTokenPayload(id_token);
331
+ tokens.idTokenPayload = _idTokenPayload != null ? { ..._idTokenPayload } : null;
332
+ if (_idTokenPayload && _idTokenPayload.nonce && currentDatabaseElement.nonce != null) {
333
+ const keyNonce = `${TOKEN.NONCE_TOKEN}_${currentDatabaseElement.configurationName}`;
334
+ _idTokenPayload.nonce = keyNonce;
335
+ }
336
+ secureTokens.idTokenPayload = _idTokenPayload;
337
+ }
338
+ if (tokens.refresh_token) secureTokens.refresh_token = `${TOKEN.REFRESH_TOKEN}_${configurationName}`;
339
+ tokens.issued_at = extractedIssueAt(tokens, accessTokenPayload, _idTokenPayload);
340
+ const expireIn = typeof tokens.expires_in == "string" ? parseInt(tokens.expires_in, 10) : tokens.expires_in;
341
+ const idTokenExpiresAt = _idTokenPayload && _idTokenPayload.exp ? _idTokenPayload.exp : Number.MAX_VALUE;
342
+ const accessTokenExpiresAt = accessTokenPayload && accessTokenPayload.exp ? accessTokenPayload.exp : tokens.issued_at + expireIn;
343
+ let expiresAt;
344
+ const tokenRenewMode = currentDatabaseElement.oidcConfiguration.token_renew_mode;
345
+ if (tokenRenewMode === TokenRenewMode.access_token_invalid) expiresAt = accessTokenExpiresAt;
346
+ else if (tokenRenewMode === TokenRenewMode.id_token_invalid) expiresAt = idTokenExpiresAt;
347
+ else expiresAt = idTokenExpiresAt < accessTokenExpiresAt ? idTokenExpiresAt : accessTokenExpiresAt;
348
+ secureTokens.expiresAt = expiresAt;
349
+ tokens.expiresAt = expiresAt;
350
+ const { isValid, reason } = isTokensOidcValid(tokens, currentDatabaseElement.nonce ? currentDatabaseElement.nonce.nonce : null, currentDatabaseElement.oidcServerConfiguration);
351
+ if (!isValid) throw Error(`Tokens are not OpenID valid, reason: ${reason}`);
352
+ if (oldTokens != null && "refresh_token" in oldTokens && !("refresh_token" in tokens)) {
353
+ const refreshToken = oldTokens.refresh_token;
354
+ currentDatabaseElement.tokens = {
355
+ ...tokens,
356
+ refresh_token: refreshToken
357
+ };
358
+ } else currentDatabaseElement.tokens = tokens;
359
+ currentDatabaseElement.status = "LOGGED_IN";
360
+ return secureTokens;
444
361
  }
445
- const demonstratingProofOfPossessionNonceResponseHeader = "DPoP-Nonce";
362
+ var demonstratingProofOfPossessionNonceResponseHeader = "DPoP-Nonce";
446
363
  function hideTokens(currentDatabaseElement) {
447
- const configurationName = currentDatabaseElement.configurationName;
448
- return (response) => {
449
- if (response.status !== 200) {
450
- return response;
451
- }
452
- const newHeaders = new Headers(response.headers);
453
- if (response.headers.has(demonstratingProofOfPossessionNonceResponseHeader)) {
454
- currentDatabaseElement.demonstratingProofOfPossessionNonce = response.headers.get(
455
- demonstratingProofOfPossessionNonceResponseHeader
456
- );
457
- newHeaders.delete(demonstratingProofOfPossessionNonceResponseHeader);
458
- }
459
- return response.json().then((tokens) => {
460
- const secureTokens = _hideTokens(tokens, currentDatabaseElement, configurationName);
461
- const body = JSON.stringify(secureTokens);
462
- return new Response(body, {
463
- status: response.status,
464
- statusText: response.statusText,
465
- headers: newHeaders
466
- });
467
- });
468
- };
364
+ const configurationName = currentDatabaseElement.configurationName;
365
+ return (response) => {
366
+ if (response.status !== 200) return response;
367
+ const newHeaders = new Headers(response.headers);
368
+ if (response.headers.has(demonstratingProofOfPossessionNonceResponseHeader)) {
369
+ currentDatabaseElement.demonstratingProofOfPossessionNonce = response.headers.get(demonstratingProofOfPossessionNonceResponseHeader);
370
+ newHeaders.delete(demonstratingProofOfPossessionNonceResponseHeader);
371
+ }
372
+ return response.json().then((tokens) => {
373
+ const secureTokens = _hideTokens(tokens, currentDatabaseElement, configurationName);
374
+ const body = JSON.stringify(secureTokens);
375
+ return new Response(body, {
376
+ status: response.status,
377
+ statusText: response.statusText,
378
+ headers: newHeaders
379
+ });
380
+ });
381
+ };
469
382
  }
470
- const TOKEN_RENEWAL_TIMEOUT_MS = 5e3;
471
- const TOKEN_RENEWAL_POLL_INTERVAL_MS = 200;
472
- async function waitForValidTokens(config, maxWaitMs = TOKEN_RENEWAL_TIMEOUT_MS, pollIntervalMs = TOKEN_RENEWAL_POLL_INTERVAL_MS) {
473
- const startTime = Date.now();
474
- while (config.tokens && !isTokensValid(config.tokens)) {
475
- if (Date.now() - startTime >= maxWaitMs) {
476
- return new Response(null, {
477
- status: 401,
478
- statusText: "Token expired - service worker renewal timeout"
479
- });
480
- }
481
- await sleep(pollIntervalMs);
482
- }
483
- if (!config.tokens?.access_token) {
484
- return new Response(null, {
485
- status: 401,
486
- statusText: "Missing access token"
487
- });
488
- }
489
- return null;
383
+ //#endregion
384
+ //#region src/utils/waitForValidTokens.ts
385
+ var TOKEN_RENEWAL_TIMEOUT_MS = 5e3;
386
+ /**
387
+ * Polls until the tokens in the given config are valid, or until a timeout elapses.
388
+ *
389
+ * @returns `null` when tokens become valid; a synthetic 401 `Response` on timeout or
390
+ * when the tokens are cleared while waiting (e.g. due to a parallel logout).
391
+ */
392
+ async function waitForValidTokens(config, maxWaitMs = TOKEN_RENEWAL_TIMEOUT_MS, pollIntervalMs = 200) {
393
+ const startTime = Date.now();
394
+ while (config.tokens && !isTokensValid(config.tokens)) {
395
+ if (Date.now() - startTime >= maxWaitMs) return new Response(null, {
396
+ status: 401,
397
+ statusText: "Token expired - service worker renewal timeout"
398
+ });
399
+ await sleep(pollIntervalMs);
400
+ }
401
+ if (!config.tokens?.access_token) return new Response(null, {
402
+ status: 401,
403
+ statusText: "Missing access token"
404
+ });
405
+ return null;
490
406
  }
491
- const getMatchingOidcConfigurations = (database2, url) => {
492
- return Object.values(database2).filter((config) => {
493
- const { oidcServerConfiguration } = config || {};
494
- const { tokenEndpoint, revocationEndpoint } = oidcServerConfiguration || {};
495
- const normalizedUrl = normalizeUrl(url);
496
- return tokenEndpoint && normalizedUrl.startsWith(normalizeUrl(tokenEndpoint)) || revocationEndpoint && normalizedUrl.startsWith(normalizeUrl(revocationEndpoint));
497
- });
407
+ //#endregion
408
+ //#region src/oidcConfig.ts
409
+ var getMatchingOidcConfigurations = (database, url) => {
410
+ return Object.values(database).filter((config) => {
411
+ const { oidcServerConfiguration } = config || {};
412
+ const { tokenEndpoint, revocationEndpoint } = oidcServerConfiguration || {};
413
+ const normalizedUrl = normalizeUrl(url);
414
+ return tokenEndpoint && normalizedUrl.startsWith(normalizeUrl(tokenEndpoint)) || revocationEndpoint && normalizedUrl.startsWith(normalizeUrl(revocationEndpoint));
415
+ });
498
416
  };
417
+ //#endregion
418
+ //#region src/utils/codeVerifier.ts
499
419
  function replaceCodeVerifier(codeVerifier, newCodeVerifier) {
500
- const regex = /[?&]code_verifier=([^&]+)/i;
501
- return codeVerifier.replace(regex, `&code_verifier=${newCodeVerifier}`);
420
+ return codeVerifier.replace(/[?&]code_verifier=([^&]+)/i, `&code_verifier=${newCodeVerifier}`);
502
421
  }
503
- const extractConfigurationNameFromCodeVerifier = (chaine) => {
504
- const regex = /[?&]code_verifier=CODE_VERIFIER_SECURED_BY_OIDC_SERVICE_WORKER_([^&]+)/;
505
- const match = chaine.match(regex);
506
- if (match && match.length > 0) {
507
- return decodeURIComponent(match[1]);
508
- } else {
509
- return "";
510
- }
422
+ var extractConfigurationNameFromCodeVerifier = (chaine) => {
423
+ const match = chaine.match(/[?&]code_verifier=CODE_VERIFIER_SECURED_BY_OIDC_SERVICE_WORKER_([^&]+)/);
424
+ if (match && match.length > 0) return decodeURIComponent(match[1]);
425
+ else return "";
511
426
  };
512
- const version = "7.27.3";
513
- if (typeof trustedTypes !== "undefined" && typeof trustedTypes.createPolicy === "function") {
514
- trustedTypes.createPolicy("default", {
515
- createScriptURL: function(url) {
516
- if (url === scriptFilename) {
517
- return url;
518
- } else {
519
- throw new Error("Untrusted script URL blocked: " + url);
520
- }
521
- }
522
- });
523
- }
524
- const _self = self;
427
+ //#endregion
428
+ //#region src/version.ts
429
+ var version_default = "7.27.4";
430
+ //#endregion
431
+ //#region src/OidcServiceWorker.ts
432
+ if (typeof trustedTypes !== "undefined" && typeof trustedTypes.createPolicy === "function") trustedTypes.createPolicy("default", { createScriptURL: function(url) {
433
+ if (url === "OidcTrustedDomains.js") return url;
434
+ else throw new Error("Untrusted script URL blocked: " + url);
435
+ } });
436
+ var _self = self;
525
437
  _self.importScripts(scriptFilename);
526
- const id = Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3).toString();
438
+ var id = Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3).toString();
527
439
  console.log("init service worker with id", id);
528
- const keepAliveJsonFilename = "OidcKeepAliveServiceWorker.json";
529
- const database = {};
530
- const keepAliveAsync = async (event) => {
531
- const originalRequest = event.request;
532
- const isFromVanilla = originalRequest.headers.has("oidc-vanilla");
533
- const init = { status: 200, statusText: "oidc-service-worker" };
534
- const response = new Response("{}", init);
535
- if (!isFromVanilla) {
536
- const originalRequestUrl = new URL(originalRequest.url);
537
- const minSleepSeconds = Number(originalRequestUrl.searchParams.get("minSleepSeconds")) || 240;
538
- for (let i = 0; i < minSleepSeconds; i++) {
539
- await sleep(1e3 + Math.floor(Math.random() * 1e3));
540
- const cache = await caches.open("oidc_dummy_cache");
541
- await cache.put(event.request, response.clone());
542
- }
543
- }
544
- return response;
440
+ var keepAliveJsonFilename = "OidcKeepAliveServiceWorker.json";
441
+ var database = {};
442
+ /**
443
+ * Keeps the service worker alive by responding with a cached response after a sleep.
444
+ */
445
+ var keepAliveAsync = async (event) => {
446
+ const originalRequest = event.request;
447
+ const isFromVanilla = originalRequest.headers.has("oidc-vanilla");
448
+ const response = new Response("{}", {
449
+ status: 200,
450
+ statusText: "oidc-service-worker"
451
+ });
452
+ if (!isFromVanilla) {
453
+ const originalRequestUrl = new URL(originalRequest.url);
454
+ const minSleepSeconds = Number(originalRequestUrl.searchParams.get("minSleepSeconds")) || 240;
455
+ for (let i = 0; i < minSleepSeconds; i++) {
456
+ await sleep(1e3 + Math.floor(Math.random() * 1e3));
457
+ await (await caches.open("oidc_dummy_cache")).put(event.request, response.clone());
458
+ }
459
+ }
460
+ return response;
545
461
  };
462
+ /**
463
+ * Generates DPoP headers when a DPoP configuration is present.
464
+ */
546
465
  async function generateDpopAsync(originalRequest, currentDatabase, url, extrasClaims = {}) {
547
- const headersExtras = serializeHeaders(originalRequest.headers);
548
- if (currentDatabase?.demonstratingProofOfPossessionConfiguration && currentDatabase.demonstratingProofOfPossessionJwkJson && (!currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent || currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent && headersExtras.dpop)) {
549
- const dpopConfiguration = currentDatabase.demonstratingProofOfPossessionConfiguration;
550
- const jwk = currentDatabase.demonstratingProofOfPossessionJwkJson;
551
- const method = originalRequest.method;
552
- const dpop = await generateJwtDemonstratingProofOfPossessionAsync(self)(dpopConfiguration)(
553
- jwk,
554
- method,
555
- url,
556
- extrasClaims
557
- );
558
- headersExtras.dpop = dpop;
559
- if (currentDatabase.demonstratingProofOfPossessionNonce != null) {
560
- headersExtras.nonce = currentDatabase.demonstratingProofOfPossessionNonce;
561
- }
562
- }
563
- return headersExtras;
466
+ const headersExtras = serializeHeaders(originalRequest.headers);
467
+ if (currentDatabase?.demonstratingProofOfPossessionConfiguration && currentDatabase.demonstratingProofOfPossessionJwkJson && (!currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent || currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent && headersExtras.dpop)) {
468
+ const dpopConfiguration = currentDatabase.demonstratingProofOfPossessionConfiguration;
469
+ const jwk = currentDatabase.demonstratingProofOfPossessionJwkJson;
470
+ const method = originalRequest.method;
471
+ headersExtras.dpop = await generateJwtDemonstratingProofOfPossessionAsync(self)(dpopConfiguration)(jwk, method, url, extrasClaims);
472
+ if (currentDatabase.demonstratingProofOfPossessionNonce != null) headersExtras.nonce = currentDatabase.demonstratingProofOfPossessionNonce;
473
+ }
474
+ return headersExtras;
564
475
  }
565
- const handleFetch = (event) => {
566
- const bypassedDestinations = ["image", "font", "media", "document", "iframe", "script"];
567
- if (bypassedDestinations.includes(event.request.destination)) {
568
- return;
569
- }
570
- event.respondWith(
571
- (async () => {
572
- try {
573
- const originalRequest = event.request;
574
- const url = normalizeUrl(originalRequest.url);
575
- if (url.includes(keepAliveJsonFilename)) {
576
- return keepAliveAsync(event);
577
- }
578
- const currentDatabasesForRequestAccessToken = getCurrentDatabaseDomain(
579
- database,
580
- url,
581
- trustedDomains
582
- );
583
- const authorization = originalRequest.headers.get("authorization");
584
- let authenticationMode = "Bearer";
585
- let key = "default";
586
- if (authorization) {
587
- const split = authorization.split(" ");
588
- authenticationMode = split[0];
589
- if (split[1]?.includes("ACCESS_TOKEN_SECURED_BY_OIDC_SERVICE_WORKER_")) {
590
- key = split[1].split("ACCESS_TOKEN_SECURED_BY_OIDC_SERVICE_WORKER_")[1];
591
- }
592
- }
593
- const currentDatabaseForRequestAccessToken = currentDatabasesForRequestAccessToken?.find(
594
- (c) => c.configurationName.endsWith(key)
595
- );
596
- if (currentDatabaseForRequestAccessToken?.tokens?.access_token) {
597
- const tokenError = await waitForValidTokens(currentDatabaseForRequestAccessToken);
598
- if (tokenError) {
599
- return tokenError;
600
- }
601
- let requestMode = originalRequest.mode;
602
- if (originalRequest.mode !== "navigate" && currentDatabaseForRequestAccessToken.convertAllRequestsToCorsExceptNavigate) {
603
- requestMode = "cors";
604
- }
605
- let headers;
606
- if (originalRequest.mode === "navigate" && !currentDatabaseForRequestAccessToken.setAccessTokenToNavigateRequests) {
607
- headers = {
608
- ...serializeHeaders(originalRequest.headers)
609
- };
610
- } else {
611
- if (authenticationMode.toLowerCase() === "dpop" || !currentDatabaseForRequestAccessToken.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent && currentDatabaseForRequestAccessToken.demonstratingProofOfPossessionConfiguration) {
612
- const claimsExtras = {
613
- ath: await base64urlOfHashOfASCIIEncodingAsync(
614
- currentDatabaseForRequestAccessToken.tokens.access_token
615
- )
616
- };
617
- const dpopHeaders = await generateDpopAsync(
618
- originalRequest,
619
- currentDatabaseForRequestAccessToken,
620
- url,
621
- claimsExtras
622
- );
623
- headers = {
624
- ...dpopHeaders,
625
- authorization: `DPoP ${currentDatabaseForRequestAccessToken.tokens.access_token}`
626
- };
627
- } else {
628
- headers = {
629
- ...serializeHeaders(originalRequest.headers),
630
- authorization: `${authenticationMode} ${currentDatabaseForRequestAccessToken.tokens.access_token}`
631
- };
632
- }
633
- }
634
- let init;
635
- if (originalRequest.mode === "navigate") {
636
- init = {
637
- headers
638
- };
639
- } else {
640
- init = {
641
- headers,
642
- mode: requestMode
643
- };
644
- }
645
- const newRequest = new Request(originalRequest, init);
646
- return fetch(newRequest);
647
- }
648
- if (event.request.method !== "POST") {
649
- return fetch(originalRequest);
650
- }
651
- const currentDatabases = getMatchingOidcConfigurations(database, url);
652
- const numberDatabase = currentDatabases.length;
653
- if (numberDatabase > 0) {
654
- const responsePromise = new Promise((resolve, reject) => {
655
- const clonedRequest = originalRequest.clone();
656
- clonedRequest.text().then(async (actualBody) => {
657
- let currentDatabase = null;
658
- try {
659
- if (actualBody.includes(TOKEN.REFRESH_TOKEN) || actualBody.includes(TOKEN.ACCESS_TOKEN)) {
660
- let headers = serializeHeaders(originalRequest.headers);
661
- let newBody = actualBody;
662
- for (let i = 0; i < numberDatabase; i++) {
663
- const currentDb = currentDatabases[i];
664
- if (currentDb?.tokens) {
665
- const claimsExtras = {
666
- ath: await base64urlOfHashOfASCIIEncodingAsync(
667
- currentDb.tokens.access_token
668
- )
669
- };
670
- headers = await generateDpopAsync(
671
- originalRequest,
672
- currentDb,
673
- url,
674
- claimsExtras
675
- );
676
- const keyRefreshToken = encodeURIComponent(
677
- `${TOKEN.REFRESH_TOKEN}_${currentDb.configurationName}`
678
- );
679
- if (actualBody.includes(keyRefreshToken)) {
680
- newBody = newBody.replace(
681
- keyRefreshToken,
682
- encodeURIComponent(currentDb.tokens.refresh_token)
683
- );
684
- currentDatabase = currentDb;
685
- break;
686
- }
687
- const keyAccessToken = encodeURIComponent(
688
- `${TOKEN.ACCESS_TOKEN}_${currentDb.configurationName}`
689
- );
690
- if (actualBody.includes(keyAccessToken)) {
691
- newBody = newBody.replace(
692
- keyAccessToken,
693
- encodeURIComponent(currentDb.tokens.access_token)
694
- );
695
- currentDatabase = currentDb;
696
- break;
697
- }
698
- }
699
- }
700
- const fetchPromise = fetch(originalRequest, {
701
- body: newBody,
702
- method: clonedRequest.method,
703
- headers,
704
- mode: clonedRequest.mode,
705
- cache: clonedRequest.cache,
706
- redirect: clonedRequest.redirect,
707
- referrer: clonedRequest.referrer,
708
- credentials: clonedRequest.credentials,
709
- integrity: clonedRequest.integrity
710
- });
711
- if (currentDatabase?.oidcServerConfiguration?.revocationEndpoint && url.startsWith(
712
- normalizeUrl(currentDatabase.oidcServerConfiguration.revocationEndpoint)
713
- )) {
714
- const resp = await fetchPromise;
715
- const txt = await resp.text();
716
- resolve(new Response(txt, resp));
717
- return;
718
- }
719
- const hidden = await fetchPromise.then(
720
- hideTokens(currentDatabase)
721
- );
722
- resolve(hidden);
723
- return;
724
- }
725
- const isCodeVerifier = actualBody.includes("code_verifier=");
726
- if (isCodeVerifier) {
727
- const currentLoginCallbackConfigurationName = extractConfigurationNameFromCodeVerifier(actualBody);
728
- if (!currentLoginCallbackConfigurationName || currentLoginCallbackConfigurationName === "") {
729
- throw new Error("No configuration name found in code_verifier");
730
- }
731
- currentDatabase = database[currentLoginCallbackConfigurationName];
732
- let newBody = actualBody;
733
- const codeVerifier = currentDatabase.codeVerifier;
734
- if (codeVerifier != null) {
735
- newBody = replaceCodeVerifier(newBody, codeVerifier);
736
- }
737
- const headersExtras = await generateDpopAsync(
738
- originalRequest,
739
- currentDatabase,
740
- url
741
- );
742
- const resp = await fetch(originalRequest, {
743
- body: newBody,
744
- method: clonedRequest.method,
745
- headers: headersExtras,
746
- mode: clonedRequest.mode,
747
- cache: clonedRequest.cache,
748
- redirect: clonedRequest.redirect,
749
- referrer: clonedRequest.referrer,
750
- credentials: clonedRequest.credentials,
751
- integrity: clonedRequest.integrity
752
- });
753
- const hidden = await hideTokens(currentDatabase)(resp);
754
- resolve(hidden);
755
- return;
756
- }
757
- const normalResp = await fetch(originalRequest, {
758
- body: actualBody,
759
- method: clonedRequest.method,
760
- headers: serializeHeaders(originalRequest.headers),
761
- mode: clonedRequest.mode,
762
- cache: clonedRequest.cache,
763
- redirect: clonedRequest.redirect,
764
- referrer: clonedRequest.referrer,
765
- credentials: clonedRequest.credentials,
766
- integrity: clonedRequest.integrity
767
- });
768
- resolve(normalResp);
769
- } catch (err) {
770
- reject(err);
771
- }
772
- }).catch(reject);
773
- });
774
- return responsePromise;
775
- }
776
- return fetch(originalRequest);
777
- } catch (err) {
778
- console.error("[OidcServiceWorker] handleFetch error:", err);
779
- return new Response("Service Worker Error", { status: 500 });
780
- }
781
- })()
782
- );
476
+ /**
477
+ * Intercepts fetch requests to inject access tokens and handle token endpoints.
478
+ */
479
+ var handleFetch = (event) => {
480
+ if ([
481
+ "image",
482
+ "font",
483
+ "media",
484
+ "document",
485
+ "iframe",
486
+ "script"
487
+ ].includes(event.request.destination)) return;
488
+ event.respondWith((async () => {
489
+ try {
490
+ const originalRequest = event.request;
491
+ const url = normalizeUrl(originalRequest.url);
492
+ if (url.includes(keepAliveJsonFilename)) return keepAliveAsync(event);
493
+ const currentDatabasesForRequestAccessToken = getCurrentDatabaseDomain(database, url, trustedDomains);
494
+ const authorization = originalRequest.headers.get("authorization");
495
+ let authenticationMode = "Bearer";
496
+ let key = "default";
497
+ if (authorization) {
498
+ const split = authorization.split(" ");
499
+ authenticationMode = split[0];
500
+ if (split[1]?.includes("ACCESS_TOKEN_SECURED_BY_OIDC_SERVICE_WORKER_")) key = split[1].split("ACCESS_TOKEN_SECURED_BY_OIDC_SERVICE_WORKER_")[1];
501
+ }
502
+ const currentDatabaseForRequestAccessToken = currentDatabasesForRequestAccessToken?.find((c) => c.configurationName.endsWith(key));
503
+ if (currentDatabaseForRequestAccessToken?.tokens?.access_token) {
504
+ const tokenError = await waitForValidTokens(currentDatabaseForRequestAccessToken);
505
+ if (tokenError) return tokenError;
506
+ let requestMode = originalRequest.mode;
507
+ if (originalRequest.mode !== "navigate" && currentDatabaseForRequestAccessToken.convertAllRequestsToCorsExceptNavigate) requestMode = "cors";
508
+ let headers;
509
+ if (originalRequest.mode === "navigate" && !currentDatabaseForRequestAccessToken.setAccessTokenToNavigateRequests) headers = { ...serializeHeaders(originalRequest.headers) };
510
+ else if (authenticationMode.toLowerCase() === "dpop" || !currentDatabaseForRequestAccessToken.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent && currentDatabaseForRequestAccessToken.demonstratingProofOfPossessionConfiguration) headers = {
511
+ ...await generateDpopAsync(originalRequest, currentDatabaseForRequestAccessToken, url, { ath: await base64urlOfHashOfASCIIEncodingAsync(currentDatabaseForRequestAccessToken.tokens.access_token) }),
512
+ authorization: `DPoP ${currentDatabaseForRequestAccessToken.tokens.access_token}`
513
+ };
514
+ else headers = {
515
+ ...serializeHeaders(originalRequest.headers),
516
+ authorization: `${authenticationMode} ${currentDatabaseForRequestAccessToken.tokens.access_token}`
517
+ };
518
+ let init;
519
+ if (originalRequest.mode === "navigate") init = { headers };
520
+ else init = {
521
+ headers,
522
+ mode: requestMode
523
+ };
524
+ const newRequest = new Request(originalRequest, init);
525
+ return fetch(newRequest);
526
+ }
527
+ if (event.request.method !== "POST") return fetch(originalRequest);
528
+ const currentDatabases = getMatchingOidcConfigurations(database, url);
529
+ const numberDatabase = currentDatabases.length;
530
+ if (numberDatabase > 0) return new Promise((resolve, reject) => {
531
+ const clonedRequest = originalRequest.clone();
532
+ clonedRequest.text().then(async (actualBody) => {
533
+ let currentDatabase = null;
534
+ try {
535
+ if (actualBody.includes(TOKEN.REFRESH_TOKEN) || actualBody.includes(TOKEN.ACCESS_TOKEN)) {
536
+ let headers = serializeHeaders(originalRequest.headers);
537
+ let newBody = actualBody;
538
+ for (let i = 0; i < numberDatabase; i++) {
539
+ const currentDb = currentDatabases[i];
540
+ if (currentDb?.tokens) {
541
+ headers = await generateDpopAsync(originalRequest, currentDb, url, { ath: await base64urlOfHashOfASCIIEncodingAsync(currentDb.tokens.access_token) });
542
+ const keyRefreshToken = encodeURIComponent(`${TOKEN.REFRESH_TOKEN}_${currentDb.configurationName}`);
543
+ if (actualBody.includes(keyRefreshToken)) {
544
+ newBody = newBody.replace(keyRefreshToken, encodeURIComponent(currentDb.tokens.refresh_token));
545
+ currentDatabase = currentDb;
546
+ break;
547
+ }
548
+ const keyAccessToken = encodeURIComponent(`${TOKEN.ACCESS_TOKEN}_${currentDb.configurationName}`);
549
+ if (actualBody.includes(keyAccessToken)) {
550
+ newBody = newBody.replace(keyAccessToken, encodeURIComponent(currentDb.tokens.access_token));
551
+ currentDatabase = currentDb;
552
+ break;
553
+ }
554
+ }
555
+ }
556
+ const fetchPromise = fetch(originalRequest, {
557
+ body: newBody,
558
+ method: clonedRequest.method,
559
+ headers,
560
+ mode: clonedRequest.mode,
561
+ cache: clonedRequest.cache,
562
+ redirect: clonedRequest.redirect,
563
+ referrer: clonedRequest.referrer,
564
+ credentials: clonedRequest.credentials,
565
+ integrity: clonedRequest.integrity
566
+ });
567
+ if (currentDatabase?.oidcServerConfiguration?.revocationEndpoint && url.startsWith(normalizeUrl(currentDatabase.oidcServerConfiguration.revocationEndpoint))) {
568
+ const resp = await fetchPromise;
569
+ const txt = await resp.text();
570
+ resolve(new Response(txt, resp));
571
+ return;
572
+ }
573
+ resolve(await fetchPromise.then(hideTokens(currentDatabase)));
574
+ return;
575
+ }
576
+ if (actualBody.includes("code_verifier=")) {
577
+ const currentLoginCallbackConfigurationName = extractConfigurationNameFromCodeVerifier(actualBody);
578
+ if (!currentLoginCallbackConfigurationName || currentLoginCallbackConfigurationName === "") throw new Error("No configuration name found in code_verifier");
579
+ currentDatabase = database[currentLoginCallbackConfigurationName];
580
+ let newBody = actualBody;
581
+ const codeVerifier = currentDatabase.codeVerifier;
582
+ if (codeVerifier != null) newBody = replaceCodeVerifier(newBody, codeVerifier);
583
+ const headersExtras = await generateDpopAsync(originalRequest, currentDatabase, url);
584
+ const resp = await fetch(originalRequest, {
585
+ body: newBody,
586
+ method: clonedRequest.method,
587
+ headers: headersExtras,
588
+ mode: clonedRequest.mode,
589
+ cache: clonedRequest.cache,
590
+ redirect: clonedRequest.redirect,
591
+ referrer: clonedRequest.referrer,
592
+ credentials: clonedRequest.credentials,
593
+ integrity: clonedRequest.integrity
594
+ });
595
+ resolve(await hideTokens(currentDatabase)(resp));
596
+ return;
597
+ }
598
+ resolve(await fetch(originalRequest, {
599
+ body: actualBody,
600
+ method: clonedRequest.method,
601
+ headers: serializeHeaders(originalRequest.headers),
602
+ mode: clonedRequest.mode,
603
+ cache: clonedRequest.cache,
604
+ redirect: clonedRequest.redirect,
605
+ referrer: clonedRequest.referrer,
606
+ credentials: clonedRequest.credentials,
607
+ integrity: clonedRequest.integrity
608
+ }));
609
+ } catch (err) {
610
+ reject(err);
611
+ }
612
+ }).catch(reject);
613
+ });
614
+ return fetch(originalRequest);
615
+ } catch (err) {
616
+ console.error("[OidcServiceWorker] handleFetch error:", err);
617
+ return new Response("Service Worker Error", { status: 500 });
618
+ }
619
+ })());
783
620
  };
784
- const handleMessage = async (event) => {
785
- const port = event.ports[0];
786
- const data = event.data;
787
- if (event.data?.type === "SKIP_WAITING") {
788
- await _self.skipWaiting();
789
- port?.postMessage?.({});
790
- return;
791
- } else if (event.data.type === "claim") {
792
- _self.clients.claim().then(() => port.postMessage({}));
793
- return;
794
- }
795
- const configurationName = data.configurationName.split("#")[0];
796
- if (trustedDomains == null) {
797
- trustedDomains = {};
798
- }
799
- const trustedDomain = trustedDomains[configurationName];
800
- const allowMultiTabLogin = Array.isArray(trustedDomain) ? false : trustedDomain.allowMultiTabLogin;
801
- const tabId = allowMultiTabLogin ? data.tabId : "default";
802
- const configurationNameWithTabId = `${configurationName}#tabId=${tabId}`;
803
- let currentDatabase = database[configurationNameWithTabId];
804
- if (!currentDatabase) {
805
- const showAccessToken = Array.isArray(trustedDomain) ? false : trustedDomain.showAccessToken;
806
- const doNotSetAccessTokenToNavigateRequests = Array.isArray(trustedDomain) ? true : trustedDomain.setAccessTokenToNavigateRequests;
807
- const convertAllRequestsToCorsExceptNavigate = Array.isArray(trustedDomain) ? false : trustedDomain.convertAllRequestsToCorsExceptNavigate;
808
- database[configurationNameWithTabId] = {
809
- tokens: null,
810
- state: null,
811
- codeVerifier: null,
812
- oidcServerConfiguration: null,
813
- oidcConfiguration: void 0,
814
- nonce: null,
815
- status: null,
816
- configurationName: configurationNameWithTabId,
817
- hideAccessToken: !showAccessToken,
818
- setAccessTokenToNavigateRequests: doNotSetAccessTokenToNavigateRequests ?? true,
819
- convertAllRequestsToCorsExceptNavigate: convertAllRequestsToCorsExceptNavigate ?? false,
820
- demonstratingProofOfPossessionNonce: null,
821
- demonstratingProofOfPossessionJwkJson: null,
822
- demonstratingProofOfPossessionConfiguration: null,
823
- demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent: false,
824
- allowMultiTabLogin: allowMultiTabLogin ?? false
825
- };
826
- currentDatabase = database[configurationNameWithTabId];
827
- if (!trustedDomains[configurationName]) {
828
- trustedDomains[configurationName] = [];
829
- }
830
- }
831
- switch (data.type) {
832
- case "clear":
833
- currentDatabase.tokens = null;
834
- currentDatabase.state = null;
835
- currentDatabase.codeVerifier = null;
836
- currentDatabase.nonce = null;
837
- currentDatabase.demonstratingProofOfPossessionNonce = null;
838
- currentDatabase.demonstratingProofOfPossessionJwkJson = null;
839
- currentDatabase.demonstratingProofOfPossessionConfiguration = null;
840
- currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent = false;
841
- currentDatabase.status = data.data.status;
842
- port.postMessage({ configurationName });
843
- return;
844
- case "init": {
845
- const oidcServerConfiguration = data.data.oidcServerConfiguration;
846
- const domains = getDomains(trustedDomain, "oidc");
847
- if (!domains.some((domain) => domain === acceptAnyDomainToken)) {
848
- [
849
- oidcServerConfiguration.tokenEndpoint,
850
- oidcServerConfiguration.revocationEndpoint,
851
- oidcServerConfiguration.userInfoEndpoint,
852
- oidcServerConfiguration.issuer
853
- ].forEach((u) => {
854
- checkDomain(domains, u);
855
- });
856
- }
857
- currentDatabase.oidcServerConfiguration = oidcServerConfiguration;
858
- currentDatabase.oidcConfiguration = data.data.oidcConfiguration;
859
- if (currentDatabase.demonstratingProofOfPossessionConfiguration == null) {
860
- const demonstratingProofOfPossessionConfiguration = getDpopConfiguration(trustedDomain);
861
- if (demonstratingProofOfPossessionConfiguration != null) {
862
- if (currentDatabase.oidcConfiguration.demonstrating_proof_of_possession) {
863
- console.warn(
864
- "In service worker, demonstrating_proof_of_possession must be configured from trustedDomains file"
865
- );
866
- }
867
- currentDatabase.demonstratingProofOfPossessionConfiguration = demonstratingProofOfPossessionConfiguration;
868
- currentDatabase.demonstratingProofOfPossessionJwkJson = await generateJwkAsync(self)(
869
- demonstratingProofOfPossessionConfiguration.generateKeyAlgorithm
870
- );
871
- currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent = getDpopOnlyWhenDpopHeaderPresent(trustedDomain) ?? false;
872
- }
873
- }
874
- if (!currentDatabase.tokens) {
875
- port.postMessage({
876
- tokens: null,
877
- status: currentDatabase.status,
878
- configurationName,
879
- version
880
- });
881
- } else {
882
- const tokens = { ...currentDatabase.tokens };
883
- if (currentDatabase.hideAccessToken) {
884
- tokens.access_token = `${TOKEN.ACCESS_TOKEN}_${configurationName}#tabId=${tabId}`;
885
- }
886
- if (tokens.refresh_token) {
887
- tokens.refresh_token = `${TOKEN.REFRESH_TOKEN}_${configurationName}#tabId=${tabId}`;
888
- }
889
- if (tokens?.idTokenPayload?.nonce && currentDatabase.nonce != null) {
890
- tokens.idTokenPayload.nonce = `${TOKEN.NONCE_TOKEN}_${configurationName}#tabId=${tabId}`;
891
- }
892
- port.postMessage({
893
- tokens,
894
- status: currentDatabase.status,
895
- configurationName,
896
- version
897
- });
898
- }
899
- return;
900
- }
901
- case "setDemonstratingProofOfPossessionNonce": {
902
- currentDatabase.demonstratingProofOfPossessionNonce = data.data.demonstratingProofOfPossessionNonce;
903
- port.postMessage({ configurationName });
904
- return;
905
- }
906
- case "getDemonstratingProofOfPossessionNonce": {
907
- const demonstratingProofOfPossessionNonce = currentDatabase.demonstratingProofOfPossessionNonce;
908
- port.postMessage({
909
- configurationName,
910
- demonstratingProofOfPossessionNonce
911
- });
912
- return;
913
- }
914
- case "setState": {
915
- currentDatabase.state = data.data.state;
916
- port.postMessage({ configurationName });
917
- return;
918
- }
919
- case "getState": {
920
- const state = currentDatabase.state;
921
- port.postMessage({ configurationName, state });
922
- return;
923
- }
924
- case "setCodeVerifier": {
925
- currentDatabase.codeVerifier = data.data.codeVerifier;
926
- port.postMessage({ configurationName });
927
- return;
928
- }
929
- case "getCodeVerifier": {
930
- const codeVerifier = currentDatabase.codeVerifier != null ? `${TOKEN.CODE_VERIFIER}_${configurationName}#tabId=${tabId}` : null;
931
- port.postMessage({
932
- configurationName,
933
- codeVerifier
934
- });
935
- return;
936
- }
937
- case "setSessionState": {
938
- currentDatabase.sessionState = data.data.sessionState;
939
- port.postMessage({ configurationName });
940
- return;
941
- }
942
- case "getSessionState": {
943
- const sessionState = currentDatabase.sessionState;
944
- port.postMessage({ configurationName, sessionState });
945
- return;
946
- }
947
- case "setNonce": {
948
- const nonce = data.data.nonce;
949
- if (nonce) {
950
- currentDatabase.nonce = nonce;
951
- }
952
- port.postMessage({ configurationName });
953
- return;
954
- }
955
- case "getNonce": {
956
- const keyNonce = `${TOKEN.NONCE_TOKEN}_${configurationName}#tabId=${tabId}`;
957
- const nonce = currentDatabase.nonce ? keyNonce : null;
958
- port.postMessage({ configurationName, nonce });
959
- return;
960
- }
961
- default:
962
- return;
963
- }
621
+ var handleMessage = async (event) => {
622
+ const port = event.ports[0];
623
+ const data = event.data;
624
+ if (event.data?.type === "SKIP_WAITING") {
625
+ await _self.skipWaiting();
626
+ port?.postMessage?.({});
627
+ return;
628
+ } else if (event.data.type === "claim") {
629
+ _self.clients.claim().then(() => port.postMessage({}));
630
+ return;
631
+ }
632
+ const configurationName = data.configurationName.split("#")[0];
633
+ if (trustedDomains == null) trustedDomains = {};
634
+ const trustedDomain = trustedDomains[configurationName];
635
+ const allowMultiTabLogin = Array.isArray(trustedDomain) ? false : trustedDomain.allowMultiTabLogin;
636
+ const tabId = allowMultiTabLogin ? data.tabId : "default";
637
+ const configurationNameWithTabId = `${configurationName}#tabId=${tabId}`;
638
+ let currentDatabase = database[configurationNameWithTabId];
639
+ if (!currentDatabase) {
640
+ const showAccessToken = Array.isArray(trustedDomain) ? false : trustedDomain.showAccessToken;
641
+ const doNotSetAccessTokenToNavigateRequests = Array.isArray(trustedDomain) ? true : trustedDomain.setAccessTokenToNavigateRequests;
642
+ const convertAllRequestsToCorsExceptNavigate = Array.isArray(trustedDomain) ? false : trustedDomain.convertAllRequestsToCorsExceptNavigate;
643
+ database[configurationNameWithTabId] = {
644
+ tokens: null,
645
+ state: null,
646
+ codeVerifier: null,
647
+ oidcServerConfiguration: null,
648
+ oidcConfiguration: void 0,
649
+ nonce: null,
650
+ status: null,
651
+ configurationName: configurationNameWithTabId,
652
+ hideAccessToken: !showAccessToken,
653
+ setAccessTokenToNavigateRequests: doNotSetAccessTokenToNavigateRequests ?? true,
654
+ convertAllRequestsToCorsExceptNavigate: convertAllRequestsToCorsExceptNavigate ?? false,
655
+ demonstratingProofOfPossessionNonce: null,
656
+ demonstratingProofOfPossessionJwkJson: null,
657
+ demonstratingProofOfPossessionConfiguration: null,
658
+ demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent: false,
659
+ allowMultiTabLogin: allowMultiTabLogin ?? false
660
+ };
661
+ currentDatabase = database[configurationNameWithTabId];
662
+ if (!trustedDomains[configurationName]) trustedDomains[configurationName] = [];
663
+ }
664
+ switch (data.type) {
665
+ case "clear":
666
+ currentDatabase.tokens = null;
667
+ currentDatabase.state = null;
668
+ currentDatabase.codeVerifier = null;
669
+ currentDatabase.nonce = null;
670
+ currentDatabase.demonstratingProofOfPossessionNonce = null;
671
+ currentDatabase.demonstratingProofOfPossessionJwkJson = null;
672
+ currentDatabase.demonstratingProofOfPossessionConfiguration = null;
673
+ currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent = false;
674
+ currentDatabase.status = data.data.status;
675
+ port.postMessage({ configurationName });
676
+ return;
677
+ case "init": {
678
+ const oidcServerConfiguration = data.data.oidcServerConfiguration;
679
+ const domains = getDomains(trustedDomain, "oidc");
680
+ if (!domains.some((domain) => domain === "*")) [
681
+ oidcServerConfiguration.tokenEndpoint,
682
+ oidcServerConfiguration.revocationEndpoint,
683
+ oidcServerConfiguration.userInfoEndpoint,
684
+ oidcServerConfiguration.issuer
685
+ ].forEach((u) => {
686
+ checkDomain(domains, u);
687
+ });
688
+ currentDatabase.oidcServerConfiguration = oidcServerConfiguration;
689
+ currentDatabase.oidcConfiguration = data.data.oidcConfiguration;
690
+ if (currentDatabase.demonstratingProofOfPossessionConfiguration == null) {
691
+ const demonstratingProofOfPossessionConfiguration = getDpopConfiguration(trustedDomain);
692
+ if (demonstratingProofOfPossessionConfiguration != null) {
693
+ if (currentDatabase.oidcConfiguration.demonstrating_proof_of_possession) console.warn("In service worker, demonstrating_proof_of_possession must be configured from trustedDomains file");
694
+ currentDatabase.demonstratingProofOfPossessionConfiguration = demonstratingProofOfPossessionConfiguration;
695
+ currentDatabase.demonstratingProofOfPossessionJwkJson = await generateJwkAsync(self)(demonstratingProofOfPossessionConfiguration.generateKeyAlgorithm);
696
+ currentDatabase.demonstratingProofOfPossessionOnlyWhenDpopHeaderPresent = getDpopOnlyWhenDpopHeaderPresent(trustedDomain) ?? false;
697
+ }
698
+ }
699
+ if (!currentDatabase.tokens) port.postMessage({
700
+ tokens: null,
701
+ status: currentDatabase.status,
702
+ configurationName,
703
+ version: version_default
704
+ });
705
+ else {
706
+ const tokens = { ...currentDatabase.tokens };
707
+ if (currentDatabase.hideAccessToken) tokens.access_token = `${TOKEN.ACCESS_TOKEN}_${configurationName}#tabId=${tabId}`;
708
+ if (tokens.refresh_token) tokens.refresh_token = `${TOKEN.REFRESH_TOKEN}_${configurationName}#tabId=${tabId}`;
709
+ if (tokens?.idTokenPayload?.nonce && currentDatabase.nonce != null) tokens.idTokenPayload.nonce = `${TOKEN.NONCE_TOKEN}_${configurationName}#tabId=${tabId}`;
710
+ port.postMessage({
711
+ tokens,
712
+ status: currentDatabase.status,
713
+ configurationName,
714
+ version: version_default
715
+ });
716
+ }
717
+ return;
718
+ }
719
+ case "setDemonstratingProofOfPossessionNonce":
720
+ currentDatabase.demonstratingProofOfPossessionNonce = data.data.demonstratingProofOfPossessionNonce;
721
+ port.postMessage({ configurationName });
722
+ return;
723
+ case "getDemonstratingProofOfPossessionNonce": {
724
+ const demonstratingProofOfPossessionNonce = currentDatabase.demonstratingProofOfPossessionNonce;
725
+ port.postMessage({
726
+ configurationName,
727
+ demonstratingProofOfPossessionNonce
728
+ });
729
+ return;
730
+ }
731
+ case "setState":
732
+ currentDatabase.state = data.data.state;
733
+ port.postMessage({ configurationName });
734
+ return;
735
+ case "getState": {
736
+ const state = currentDatabase.state;
737
+ port.postMessage({
738
+ configurationName,
739
+ state
740
+ });
741
+ return;
742
+ }
743
+ case "setCodeVerifier":
744
+ currentDatabase.codeVerifier = data.data.codeVerifier;
745
+ port.postMessage({ configurationName });
746
+ return;
747
+ case "getCodeVerifier": {
748
+ const codeVerifier = currentDatabase.codeVerifier != null ? `${TOKEN.CODE_VERIFIER}_${configurationName}#tabId=${tabId}` : null;
749
+ port.postMessage({
750
+ configurationName,
751
+ codeVerifier
752
+ });
753
+ return;
754
+ }
755
+ case "setSessionState":
756
+ currentDatabase.sessionState = data.data.sessionState;
757
+ port.postMessage({ configurationName });
758
+ return;
759
+ case "getSessionState": {
760
+ const sessionState = currentDatabase.sessionState;
761
+ port.postMessage({
762
+ configurationName,
763
+ sessionState
764
+ });
765
+ return;
766
+ }
767
+ case "setNonce": {
768
+ const nonce = data.data.nonce;
769
+ if (nonce) currentDatabase.nonce = nonce;
770
+ port.postMessage({ configurationName });
771
+ return;
772
+ }
773
+ case "getNonce": {
774
+ const keyNonce = `${TOKEN.NONCE_TOKEN}_${configurationName}#tabId=${tabId}`;
775
+ const nonce = currentDatabase.nonce ? keyNonce : null;
776
+ port.postMessage({
777
+ configurationName,
778
+ nonce
779
+ });
780
+ return;
781
+ }
782
+ default: return;
783
+ }
964
784
  };
965
785
  _self.addEventListener("fetch", handleFetch);
966
786
  _self.addEventListener("message", handleMessage);
967
- //# sourceMappingURL=OidcServiceWorker.js.map
787
+ //#endregion
788
+
789
+ //# sourceMappingURL=OidcServiceWorker.js.map