@axa-fr/oidc-client-service-worker 7.27.2 → 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.
- package/dist/OidcServiceWorker.js +723 -901
- package/dist/OidcServiceWorker.js.map +1 -1
- package/dist/src/types.d.ts +0 -3
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/serializeHeaders.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/package.json +8 -8
- package/src/types.ts +0 -5
- package/src/utils/serializeHeaders.ts +1 -3
- package/src/version.ts +1 -1
|
@@ -1,967 +1,789 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/jwt.ts
|
|
14
16
|
function strToUint8(str) {
|
|
15
|
-
|
|
17
|
+
return new TextEncoder().encode(str);
|
|
16
18
|
}
|
|
17
19
|
function binToUrlBase64(bin) {
|
|
18
|
-
|
|
20
|
+
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+/g, "");
|
|
19
21
|
}
|
|
20
22
|
function utf8ToBinaryString(str) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
35
|
+
return binToUrlBase64(utf8ToBinaryString(str));
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
var EC = {
|
|
102
|
+
generate,
|
|
103
|
+
neuter
|
|
99
104
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return jwk;
|
|
119
|
+
var JWK = { thumbprint };
|
|
120
|
+
var generateJwkAsync = (w) => async (generateKeyAlgorithm) => {
|
|
121
|
+
return await EC.generate(w)(generateKeyAlgorithm);
|
|
119
122
|
};
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
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
|
-
|
|
251
|
+
return str.split(find).length - 1;
|
|
291
252
|
}
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
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
|
-
|
|
302
|
-
|
|
262
|
+
const currentTimeUnixSecond = (/* @__PURE__ */ new Date()).getTime() / 1e3;
|
|
263
|
+
return Math.round(expiresAt - refreshTimeBeforeTokensExpirationInSecond - currentTimeUnixSecond);
|
|
303
264
|
}
|
|
304
265
|
function isTokensValid(tokens) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
return computeTimeLeft(0, tokens.expiresAt) > 0;
|
|
266
|
+
if (!tokens) return false;
|
|
267
|
+
return computeTimeLeft(0, tokens.expiresAt) > 0;
|
|
309
268
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
-
|
|
362
|
+
var demonstratingProofOfPossessionNonceResponseHeader = "DPoP-Nonce";
|
|
446
363
|
function hideTokens(currentDatabaseElement) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
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
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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
|
-
|
|
501
|
-
return codeVerifier.replace(regex, `&code_verifier=${newCodeVerifier}`);
|
|
420
|
+
return codeVerifier.replace(/[?&]code_verifier=([^&]+)/i, `&code_verifier=${newCodeVerifier}`);
|
|
502
421
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
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
|
-
|
|
438
|
+
var id = Math.round((/* @__PURE__ */ new Date()).getTime() / 1e3).toString();
|
|
527
439
|
console.log("init service worker with id", id);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
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
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
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
|
-
//#
|
|
787
|
+
//#endregion
|
|
788
|
+
|
|
789
|
+
//# sourceMappingURL=OidcServiceWorker.js.map
|