@versini/auth-provider 2.3.0 → 3.0.0
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/index.d.ts +2 -1
- package/dist/index.js +206 -213
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -9,15 +9,16 @@ type AuthProviderProps = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
type AuthState = {
|
|
12
|
+
isLoading: boolean;
|
|
12
13
|
isAuthenticated: boolean;
|
|
13
14
|
logoutReason?: string;
|
|
14
15
|
userId?: string;
|
|
16
|
+
idTokenClaims?: any;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
type AuthContextProps = {
|
|
18
20
|
login: (username: string, password: string) => Promise<boolean>;
|
|
19
21
|
logout: () => void;
|
|
20
|
-
getIdTokenClaims: () => Promise<any>;
|
|
21
22
|
} & AuthState;
|
|
22
23
|
|
|
23
24
|
declare const AuthProvider: ({ children, sessionExpiration, clientId, }: AuthProviderProps) => react_jsx_runtime.JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsx as ne } from "react/jsx-runtime";
|
|
2
2
|
import * as I from "react";
|
|
3
|
-
import { useRef as ae, useEffect as
|
|
3
|
+
import { useRef as ae, useEffect as F, createContext as se, useState as ie, useCallback as ce, useContext as ue } from "react";
|
|
4
4
|
/*!
|
|
5
|
-
@versini/auth-provider
|
|
5
|
+
@versini/auth-provider v3.0.0
|
|
6
6
|
© 2024 gizmette.com
|
|
7
7
|
*/
|
|
8
8
|
try {
|
|
9
9
|
window.__VERSINI_AUTH_CLIENT__ || (window.__VERSINI_AUTH_CLIENT__ = {
|
|
10
|
-
version: "
|
|
11
|
-
buildTime: "06/
|
|
10
|
+
version: "3.0.0",
|
|
11
|
+
buildTime: "06/25/2024 08:53 AM EDT",
|
|
12
12
|
homepage: "https://github.com/aversini/auth-client",
|
|
13
13
|
license: "MIT"
|
|
14
14
|
});
|
|
@@ -21,21 +21,21 @@ try {
|
|
|
21
21
|
try {
|
|
22
22
|
window.__VERSINI_AUTH_COMMON__ || (window.__VERSINI_AUTH_COMMON__ = {
|
|
23
23
|
version: "2.3.0",
|
|
24
|
-
buildTime: "06/
|
|
24
|
+
buildTime: "06/25/2024 08:53 AM EDT",
|
|
25
25
|
homepage: "https://github.com/aversini/auth-client",
|
|
26
26
|
license: "MIT"
|
|
27
27
|
});
|
|
28
28
|
} catch {
|
|
29
29
|
}
|
|
30
|
-
const
|
|
31
|
-
function
|
|
30
|
+
const N = crypto, G = (e) => e instanceof CryptoKey, _ = new TextEncoder(), T = new TextDecoder();
|
|
31
|
+
function de(...e) {
|
|
32
32
|
const t = e.reduce((n, { length: a }) => n + a, 0), o = new Uint8Array(t);
|
|
33
33
|
let r = 0;
|
|
34
34
|
for (const n of e)
|
|
35
35
|
o.set(n, r), r += n.length;
|
|
36
36
|
return o;
|
|
37
37
|
}
|
|
38
|
-
const
|
|
38
|
+
const le = (e) => {
|
|
39
39
|
const t = atob(e), o = new Uint8Array(t.length);
|
|
40
40
|
for (let r = 0; r < t.length; r++)
|
|
41
41
|
o[r] = t.charCodeAt(r);
|
|
@@ -44,7 +44,7 @@ const de = (e) => {
|
|
|
44
44
|
let t = e;
|
|
45
45
|
t instanceof Uint8Array && (t = T.decode(t)), t = t.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, "");
|
|
46
46
|
try {
|
|
47
|
-
return
|
|
47
|
+
return le(t);
|
|
48
48
|
} catch {
|
|
49
49
|
throw new TypeError("The input to be decoded is not correctly encoded.");
|
|
50
50
|
}
|
|
@@ -66,7 +66,7 @@ class m extends b {
|
|
|
66
66
|
super(t), this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED", this.claim = r, this.reason = n, this.payload = o;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
class
|
|
69
|
+
class L extends b {
|
|
70
70
|
static get code() {
|
|
71
71
|
return "ERR_JWT_EXPIRED";
|
|
72
72
|
}
|
|
@@ -74,7 +74,7 @@ class $ extends b {
|
|
|
74
74
|
super(t), this.code = "ERR_JWT_EXPIRED", this.claim = r, this.reason = n, this.payload = o;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
class
|
|
77
|
+
class he extends b {
|
|
78
78
|
constructor() {
|
|
79
79
|
super(...arguments), this.code = "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
80
80
|
}
|
|
@@ -98,7 +98,7 @@ let l = class extends b {
|
|
|
98
98
|
return "ERR_JWS_INVALID";
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
|
-
class
|
|
101
|
+
class Y extends b {
|
|
102
102
|
constructor() {
|
|
103
103
|
super(...arguments), this.code = "ERR_JWT_INVALID";
|
|
104
104
|
}
|
|
@@ -106,7 +106,7 @@ class q extends b {
|
|
|
106
106
|
return "ERR_JWT_INVALID";
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
class
|
|
109
|
+
class pe extends b {
|
|
110
110
|
constructor() {
|
|
111
111
|
super(...arguments), this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED", this.message = "signature verification failed";
|
|
112
112
|
}
|
|
@@ -123,7 +123,7 @@ function v(e, t) {
|
|
|
123
123
|
function P(e) {
|
|
124
124
|
return parseInt(e.name.slice(4), 10);
|
|
125
125
|
}
|
|
126
|
-
function
|
|
126
|
+
function fe(e) {
|
|
127
127
|
switch (e) {
|
|
128
128
|
case "ES256":
|
|
129
129
|
return "P-256";
|
|
@@ -135,7 +135,7 @@ function pe(e) {
|
|
|
135
135
|
throw new Error("unreachable");
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
function
|
|
138
|
+
function ye(e, t) {
|
|
139
139
|
if (t.length && !t.some((o) => e.usages.includes(o))) {
|
|
140
140
|
let o = "CryptoKey does not support this operation, its usages must include ";
|
|
141
141
|
if (t.length > 2) {
|
|
@@ -146,7 +146,7 @@ function fe(e, t) {
|
|
|
146
146
|
throw new TypeError(o);
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
-
function
|
|
149
|
+
function me(e, t, ...o) {
|
|
150
150
|
switch (t) {
|
|
151
151
|
case "HS256":
|
|
152
152
|
case "HS384":
|
|
@@ -188,7 +188,7 @@ function ye(e, t, ...o) {
|
|
|
188
188
|
case "ES512": {
|
|
189
189
|
if (!v(e.algorithm, "ECDSA"))
|
|
190
190
|
throw S("ECDSA");
|
|
191
|
-
const r =
|
|
191
|
+
const r = fe(t);
|
|
192
192
|
if (e.algorithm.namedCurve !== r)
|
|
193
193
|
throw S(r, "algorithm.namedCurve");
|
|
194
194
|
break;
|
|
@@ -196,9 +196,9 @@ function ye(e, t, ...o) {
|
|
|
196
196
|
default:
|
|
197
197
|
throw new TypeError("CryptoKey does not support this operation");
|
|
198
198
|
}
|
|
199
|
-
|
|
199
|
+
ye(e, o);
|
|
200
200
|
}
|
|
201
|
-
function
|
|
201
|
+
function q(e, t, ...o) {
|
|
202
202
|
var r;
|
|
203
203
|
if (o.length > 2) {
|
|
204
204
|
const n = o.pop();
|
|
@@ -207,11 +207,11 @@ function z(e, t, ...o) {
|
|
|
207
207
|
o.length === 2 ? e += `one of type ${o[0]} or ${o[1]}.` : e += `of type ${o[0]}.`;
|
|
208
208
|
return t == null ? e += ` Received ${t}` : typeof t == "function" && t.name ? e += ` Received function ${t.name}` : typeof t == "object" && t != null && (r = t.constructor) != null && r.name && (e += ` Received an instance of ${t.constructor.name}`), e;
|
|
209
209
|
}
|
|
210
|
-
const
|
|
211
|
-
function
|
|
212
|
-
return
|
|
210
|
+
const J = (e, ...t) => q("Key must be ", e, ...t);
|
|
211
|
+
function z(e, t, ...o) {
|
|
212
|
+
return q(`Key for the ${e} algorithm must be `, t, ...o);
|
|
213
213
|
}
|
|
214
|
-
const
|
|
214
|
+
const X = (e) => G(e), E = ["CryptoKey"], we = (...e) => {
|
|
215
215
|
const t = e.filter(Boolean);
|
|
216
216
|
if (t.length === 0 || t.length === 1)
|
|
217
217
|
return !0;
|
|
@@ -230,11 +230,11 @@ const Q = (e) => G(e), g = ["CryptoKey"], me = (...e) => {
|
|
|
230
230
|
}
|
|
231
231
|
return !0;
|
|
232
232
|
};
|
|
233
|
-
function
|
|
233
|
+
function Se(e) {
|
|
234
234
|
return typeof e == "object" && e !== null;
|
|
235
235
|
}
|
|
236
236
|
function H(e) {
|
|
237
|
-
if (!
|
|
237
|
+
if (!Se(e) || Object.prototype.toString.call(e) !== "[object Object]")
|
|
238
238
|
return !1;
|
|
239
239
|
if (Object.getPrototypeOf(e) === null)
|
|
240
240
|
return !0;
|
|
@@ -243,34 +243,34 @@ function H(e) {
|
|
|
243
243
|
t = Object.getPrototypeOf(t);
|
|
244
244
|
return Object.getPrototypeOf(e) === t;
|
|
245
245
|
}
|
|
246
|
-
const
|
|
246
|
+
const ge = (e, t) => {
|
|
247
247
|
if (e.startsWith("RS") || e.startsWith("PS")) {
|
|
248
248
|
const { modulusLength: o } = t.algorithm;
|
|
249
249
|
if (typeof o != "number" || o < 2048)
|
|
250
250
|
throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`);
|
|
251
251
|
}
|
|
252
|
-
},
|
|
252
|
+
}, g = (e, t, o = 0) => {
|
|
253
253
|
o === 0 && (t.unshift(t.length), t.unshift(6));
|
|
254
254
|
const r = e.indexOf(t[0], o);
|
|
255
255
|
if (r === -1)
|
|
256
256
|
return !1;
|
|
257
257
|
const n = e.subarray(r, r + t.length);
|
|
258
|
-
return n.length !== t.length ? !1 : n.every((a, s) => a === t[s]) ||
|
|
259
|
-
},
|
|
258
|
+
return n.length !== t.length ? !1 : n.every((a, s) => a === t[s]) || g(e, t, r + 1);
|
|
259
|
+
}, $ = (e) => {
|
|
260
260
|
switch (!0) {
|
|
261
|
-
case
|
|
261
|
+
case g(e, [42, 134, 72, 206, 61, 3, 1, 7]):
|
|
262
262
|
return "P-256";
|
|
263
|
-
case
|
|
263
|
+
case g(e, [43, 129, 4, 0, 34]):
|
|
264
264
|
return "P-384";
|
|
265
|
-
case
|
|
265
|
+
case g(e, [43, 129, 4, 0, 35]):
|
|
266
266
|
return "P-521";
|
|
267
|
-
case
|
|
267
|
+
case g(e, [43, 101, 110]):
|
|
268
268
|
return "X25519";
|
|
269
|
-
case
|
|
269
|
+
case g(e, [43, 101, 111]):
|
|
270
270
|
return "X448";
|
|
271
|
-
case
|
|
271
|
+
case g(e, [43, 101, 112]):
|
|
272
272
|
return "Ed25519";
|
|
273
|
-
case
|
|
273
|
+
case g(e, [43, 101, 113]):
|
|
274
274
|
return "Ed448";
|
|
275
275
|
default:
|
|
276
276
|
throw new k("Invalid or unsupported EC Key Curve or OKP Key Sub Type");
|
|
@@ -311,43 +311,43 @@ const Se = (e, t) => {
|
|
|
311
311
|
case "ECDH-ES+A128KW":
|
|
312
312
|
case "ECDH-ES+A192KW":
|
|
313
313
|
case "ECDH-ES+A256KW": {
|
|
314
|
-
const c =
|
|
314
|
+
const c = $(i);
|
|
315
315
|
a = c.startsWith("P-") ? { name: "ECDH", namedCurve: c } : { name: c }, s = [];
|
|
316
316
|
break;
|
|
317
317
|
}
|
|
318
318
|
case "EdDSA":
|
|
319
|
-
a = { name:
|
|
319
|
+
a = { name: $(i) }, s = ["verify"];
|
|
320
320
|
break;
|
|
321
321
|
default:
|
|
322
322
|
throw new k('Invalid or unsupported "alg" (Algorithm) value');
|
|
323
323
|
}
|
|
324
|
-
return
|
|
325
|
-
},
|
|
326
|
-
async function
|
|
324
|
+
return N.subtle.importKey(t, i, a, !1, s);
|
|
325
|
+
}, Ae = (e, t, o) => Ee(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "spki", e, t);
|
|
326
|
+
async function be(e, t, o) {
|
|
327
327
|
if (e.indexOf("-----BEGIN PUBLIC KEY-----") !== 0)
|
|
328
328
|
throw new TypeError('"spki" must be SPKI formatted string');
|
|
329
|
-
return
|
|
329
|
+
return Ae(e, t);
|
|
330
330
|
}
|
|
331
|
-
const
|
|
331
|
+
const Ie = (e, t) => {
|
|
332
332
|
if (!(t instanceof Uint8Array)) {
|
|
333
|
-
if (!
|
|
334
|
-
throw new TypeError(
|
|
333
|
+
if (!X(t))
|
|
334
|
+
throw new TypeError(z(e, t, ...E, "Uint8Array"));
|
|
335
335
|
if (t.type !== "secret")
|
|
336
|
-
throw new TypeError(`${
|
|
336
|
+
throw new TypeError(`${E.join(" or ")} instances for symmetric algorithms must be of type "secret"`);
|
|
337
337
|
}
|
|
338
|
-
},
|
|
339
|
-
if (!
|
|
340
|
-
throw new TypeError(
|
|
338
|
+
}, _e = (e, t, o) => {
|
|
339
|
+
if (!X(t))
|
|
340
|
+
throw new TypeError(z(e, t, ...E));
|
|
341
341
|
if (t.type === "secret")
|
|
342
|
-
throw new TypeError(`${
|
|
342
|
+
throw new TypeError(`${E.join(" or ")} instances for asymmetric algorithms must not be of type "secret"`);
|
|
343
343
|
if (t.algorithm && o === "verify" && t.type === "private")
|
|
344
|
-
throw new TypeError(`${
|
|
344
|
+
throw new TypeError(`${E.join(" or ")} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
345
345
|
if (t.algorithm && o === "encrypt" && t.type === "private")
|
|
346
|
-
throw new TypeError(`${
|
|
347
|
-
},
|
|
348
|
-
e.startsWith("HS") || e === "dir" || e.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(e) ?
|
|
346
|
+
throw new TypeError(`${E.join(" or ")} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
347
|
+
}, ve = (e, t, o) => {
|
|
348
|
+
e.startsWith("HS") || e === "dir" || e.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(e) ? Ie(e, t) : _e(e, t, o);
|
|
349
349
|
};
|
|
350
|
-
function
|
|
350
|
+
function Re(e, t, o, r, n) {
|
|
351
351
|
if (n.crit !== void 0 && (r == null ? void 0 : r.crit) === void 0)
|
|
352
352
|
throw new e('"crit" (Critical) Header Parameter MUST be integrity protected');
|
|
353
353
|
if (!r || r.crit === void 0)
|
|
@@ -366,13 +366,13 @@ function ve(e, t, o, r, n) {
|
|
|
366
366
|
}
|
|
367
367
|
return new Set(r.crit);
|
|
368
368
|
}
|
|
369
|
-
const
|
|
369
|
+
const Te = (e, t) => {
|
|
370
370
|
if (t !== void 0 && (!Array.isArray(t) || t.some((o) => typeof o != "string")))
|
|
371
371
|
throw new TypeError(`"${e}" option must be an array of strings`);
|
|
372
372
|
if (t)
|
|
373
373
|
return new Set(t);
|
|
374
374
|
};
|
|
375
|
-
function
|
|
375
|
+
function ke(e, t) {
|
|
376
376
|
const o = `SHA-${e.slice(-3)}`;
|
|
377
377
|
switch (e) {
|
|
378
378
|
case "HS256":
|
|
@@ -397,27 +397,27 @@ function Te(e, t) {
|
|
|
397
397
|
throw new k(`alg ${e} is not supported either by JOSE or your javascript runtime`);
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
-
function
|
|
400
|
+
function Ce(e, t, o) {
|
|
401
401
|
if (G(t))
|
|
402
|
-
return
|
|
402
|
+
return me(t, e, o), t;
|
|
403
403
|
if (t instanceof Uint8Array) {
|
|
404
404
|
if (!e.startsWith("HS"))
|
|
405
|
-
throw new TypeError(
|
|
406
|
-
return
|
|
405
|
+
throw new TypeError(J(t, ...E));
|
|
406
|
+
return N.subtle.importKey("raw", t, { hash: `SHA-${e.slice(-3)}`, name: "HMAC" }, !1, [o]);
|
|
407
407
|
}
|
|
408
|
-
throw new TypeError(
|
|
408
|
+
throw new TypeError(J(t, ...E, "Uint8Array"));
|
|
409
409
|
}
|
|
410
|
-
const
|
|
411
|
-
const n = await
|
|
412
|
-
|
|
413
|
-
const a =
|
|
410
|
+
const Pe = async (e, t, o, r) => {
|
|
411
|
+
const n = await Ce(e, t, "verify");
|
|
412
|
+
ge(e, n);
|
|
413
|
+
const a = ke(e, n.algorithm);
|
|
414
414
|
try {
|
|
415
|
-
return await
|
|
415
|
+
return await N.subtle.verify(a, n, o, r);
|
|
416
416
|
} catch {
|
|
417
417
|
return !1;
|
|
418
418
|
}
|
|
419
419
|
};
|
|
420
|
-
async function
|
|
420
|
+
async function Oe(e, t, o) {
|
|
421
421
|
if (!H(e))
|
|
422
422
|
throw new l("Flattened JWS must be an object");
|
|
423
423
|
if (e.protected === void 0 && e.header === void 0)
|
|
@@ -433,42 +433,42 @@ async function Pe(e, t, o) {
|
|
|
433
433
|
let r = {};
|
|
434
434
|
if (e.protected)
|
|
435
435
|
try {
|
|
436
|
-
const
|
|
437
|
-
r = JSON.parse(T.decode(
|
|
436
|
+
const f = C(e.protected);
|
|
437
|
+
r = JSON.parse(T.decode(f));
|
|
438
438
|
} catch {
|
|
439
439
|
throw new l("JWS Protected Header is invalid");
|
|
440
440
|
}
|
|
441
|
-
if (!
|
|
441
|
+
if (!we(r, e.header))
|
|
442
442
|
throw new l("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
443
443
|
const n = {
|
|
444
444
|
...r,
|
|
445
445
|
...e.header
|
|
446
|
-
}, a =
|
|
446
|
+
}, a = Re(l, /* @__PURE__ */ new Map([["b64", !0]]), o == null ? void 0 : o.crit, r, n);
|
|
447
447
|
let s = !0;
|
|
448
448
|
if (a.has("b64") && (s = r.b64, typeof s != "boolean"))
|
|
449
449
|
throw new l('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
|
|
450
450
|
const { alg: i } = n;
|
|
451
451
|
if (typeof i != "string" || !i)
|
|
452
452
|
throw new l('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
453
|
-
const c = o &&
|
|
453
|
+
const c = o && Te("algorithms", o.algorithms);
|
|
454
454
|
if (c && !c.has(i))
|
|
455
|
-
throw new
|
|
455
|
+
throw new he('"alg" (Algorithm) Header Parameter value not allowed');
|
|
456
456
|
if (s) {
|
|
457
457
|
if (typeof e.payload != "string")
|
|
458
458
|
throw new l("JWS Payload must be a string");
|
|
459
459
|
} else if (typeof e.payload != "string" && !(e.payload instanceof Uint8Array))
|
|
460
460
|
throw new l("JWS Payload must be a string or an Uint8Array instance");
|
|
461
|
-
let
|
|
462
|
-
typeof t == "function" && (t = await t(r, e),
|
|
463
|
-
const w =
|
|
464
|
-
let
|
|
461
|
+
let h = !1;
|
|
462
|
+
typeof t == "function" && (t = await t(r, e), h = !0), ve(i, t, "verify");
|
|
463
|
+
const w = de(_.encode(e.protected ?? ""), _.encode("."), typeof e.payload == "string" ? _.encode(e.payload) : e.payload);
|
|
464
|
+
let p;
|
|
465
465
|
try {
|
|
466
|
-
|
|
466
|
+
p = C(e.signature);
|
|
467
467
|
} catch {
|
|
468
468
|
throw new l("Failed to base64url decode the signature");
|
|
469
469
|
}
|
|
470
|
-
if (!await
|
|
471
|
-
throw new
|
|
470
|
+
if (!await Pe(i, t, p, w))
|
|
471
|
+
throw new pe();
|
|
472
472
|
let u;
|
|
473
473
|
if (s)
|
|
474
474
|
try {
|
|
@@ -479,19 +479,19 @@ async function Pe(e, t, o) {
|
|
|
479
479
|
else
|
|
480
480
|
typeof e.payload == "string" ? u = _.encode(e.payload) : u = e.payload;
|
|
481
481
|
const y = { payload: u };
|
|
482
|
-
return e.protected !== void 0 && (y.protectedHeader = r), e.header !== void 0 && (y.unprotectedHeader = e.header),
|
|
482
|
+
return e.protected !== void 0 && (y.protectedHeader = r), e.header !== void 0 && (y.unprotectedHeader = e.header), h ? { ...y, key: t } : y;
|
|
483
483
|
}
|
|
484
|
-
async function
|
|
484
|
+
async function De(e, t, o) {
|
|
485
485
|
if (e instanceof Uint8Array && (e = T.decode(e)), typeof e != "string")
|
|
486
486
|
throw new l("Compact JWS must be a string or Uint8Array");
|
|
487
487
|
const { 0: r, 1: n, 2: a, length: s } = e.split(".");
|
|
488
488
|
if (s !== 3)
|
|
489
489
|
throw new l("Invalid Compact JWS");
|
|
490
|
-
const i = await
|
|
490
|
+
const i = await Oe({ payload: n, protected: r, signature: a }, t, o), c = { payload: i.payload, protectedHeader: i.protectedHeader };
|
|
491
491
|
return typeof t == "function" ? { ...c, key: i.key } : c;
|
|
492
492
|
}
|
|
493
|
-
const
|
|
494
|
-
const t =
|
|
493
|
+
const He = (e) => Math.floor(e.getTime() / 1e3), Q = 60, Z = Q * 60, U = Z * 24, Ne = U * 7, Ue = U * 365.25, Le = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i, K = (e) => {
|
|
494
|
+
const t = Le.exec(e);
|
|
495
495
|
if (!t || t[4] && t[1])
|
|
496
496
|
throw new TypeError("Invalid time period format");
|
|
497
497
|
const o = parseFloat(t[2]), r = t[3].toLowerCase();
|
|
@@ -509,108 +509,108 @@ const De = (e) => Math.floor(e.getTime() / 1e3), Z = 60, ee = Z * 60, J = ee * 2
|
|
|
509
509
|
case "min":
|
|
510
510
|
case "mins":
|
|
511
511
|
case "m":
|
|
512
|
-
n = Math.round(o *
|
|
512
|
+
n = Math.round(o * Q);
|
|
513
513
|
break;
|
|
514
514
|
case "hour":
|
|
515
515
|
case "hours":
|
|
516
516
|
case "hr":
|
|
517
517
|
case "hrs":
|
|
518
518
|
case "h":
|
|
519
|
-
n = Math.round(o *
|
|
519
|
+
n = Math.round(o * Z);
|
|
520
520
|
break;
|
|
521
521
|
case "day":
|
|
522
522
|
case "days":
|
|
523
523
|
case "d":
|
|
524
|
-
n = Math.round(o *
|
|
524
|
+
n = Math.round(o * U);
|
|
525
525
|
break;
|
|
526
526
|
case "week":
|
|
527
527
|
case "weeks":
|
|
528
528
|
case "w":
|
|
529
|
-
n = Math.round(o *
|
|
529
|
+
n = Math.round(o * Ne);
|
|
530
530
|
break;
|
|
531
531
|
default:
|
|
532
|
-
n = Math.round(o *
|
|
532
|
+
n = Math.round(o * Ue);
|
|
533
533
|
break;
|
|
534
534
|
}
|
|
535
535
|
return t[1] === "-" || t[4] === "ago" ? -n : n;
|
|
536
|
-
},
|
|
536
|
+
}, W = (e) => e.toLowerCase().replace(/^application\//, ""), Je = (e, t) => typeof e == "string" ? t.includes(e) : Array.isArray(e) ? t.some(Set.prototype.has.bind(new Set(e))) : !1, $e = (e, t, o = {}) => {
|
|
537
537
|
let r;
|
|
538
538
|
try {
|
|
539
539
|
r = JSON.parse(T.decode(t));
|
|
540
540
|
} catch {
|
|
541
541
|
}
|
|
542
542
|
if (!H(r))
|
|
543
|
-
throw new
|
|
543
|
+
throw new Y("JWT Claims Set must be a top-level JSON object");
|
|
544
544
|
const { typ: n } = o;
|
|
545
|
-
if (n && (typeof e.typ != "string" ||
|
|
545
|
+
if (n && (typeof e.typ != "string" || W(e.typ) !== W(n)))
|
|
546
546
|
throw new m('unexpected "typ" JWT header value', r, "typ", "check_failed");
|
|
547
|
-
const { requiredClaims: a = [], issuer: s, subject: i, audience: c, maxTokenAge:
|
|
548
|
-
|
|
549
|
-
for (const
|
|
550
|
-
if (!(
|
|
551
|
-
throw new m(`missing required "${
|
|
547
|
+
const { requiredClaims: a = [], issuer: s, subject: i, audience: c, maxTokenAge: h } = o, w = [...a];
|
|
548
|
+
h !== void 0 && w.push("iat"), c !== void 0 && w.push("aud"), i !== void 0 && w.push("sub"), s !== void 0 && w.push("iss");
|
|
549
|
+
for (const f of new Set(w.reverse()))
|
|
550
|
+
if (!(f in r))
|
|
551
|
+
throw new m(`missing required "${f}" claim`, r, f, "missing");
|
|
552
552
|
if (s && !(Array.isArray(s) ? s : [s]).includes(r.iss))
|
|
553
553
|
throw new m('unexpected "iss" claim value', r, "iss", "check_failed");
|
|
554
554
|
if (i && r.sub !== i)
|
|
555
555
|
throw new m('unexpected "sub" claim value', r, "sub", "check_failed");
|
|
556
556
|
if (c && !Je(r.aud, typeof c == "string" ? [c] : c))
|
|
557
557
|
throw new m('unexpected "aud" claim value', r, "aud", "check_failed");
|
|
558
|
-
let
|
|
558
|
+
let p;
|
|
559
559
|
switch (typeof o.clockTolerance) {
|
|
560
560
|
case "string":
|
|
561
|
-
|
|
561
|
+
p = K(o.clockTolerance);
|
|
562
562
|
break;
|
|
563
563
|
case "number":
|
|
564
|
-
|
|
564
|
+
p = o.clockTolerance;
|
|
565
565
|
break;
|
|
566
566
|
case "undefined":
|
|
567
|
-
|
|
567
|
+
p = 0;
|
|
568
568
|
break;
|
|
569
569
|
default:
|
|
570
570
|
throw new TypeError("Invalid clockTolerance option type");
|
|
571
571
|
}
|
|
572
|
-
const { currentDate: u } = o, y =
|
|
573
|
-
if ((r.iat !== void 0 ||
|
|
572
|
+
const { currentDate: u } = o, y = He(u || /* @__PURE__ */ new Date());
|
|
573
|
+
if ((r.iat !== void 0 || h) && typeof r.iat != "number")
|
|
574
574
|
throw new m('"iat" claim must be a number', r, "iat", "invalid");
|
|
575
575
|
if (r.nbf !== void 0) {
|
|
576
576
|
if (typeof r.nbf != "number")
|
|
577
577
|
throw new m('"nbf" claim must be a number', r, "nbf", "invalid");
|
|
578
|
-
if (r.nbf > y +
|
|
578
|
+
if (r.nbf > y + p)
|
|
579
579
|
throw new m('"nbf" claim timestamp check failed', r, "nbf", "check_failed");
|
|
580
580
|
}
|
|
581
581
|
if (r.exp !== void 0) {
|
|
582
582
|
if (typeof r.exp != "number")
|
|
583
583
|
throw new m('"exp" claim must be a number', r, "exp", "invalid");
|
|
584
|
-
if (r.exp <= y -
|
|
585
|
-
throw new
|
|
586
|
-
}
|
|
587
|
-
if (
|
|
588
|
-
const
|
|
589
|
-
if (
|
|
590
|
-
throw new
|
|
591
|
-
if (
|
|
584
|
+
if (r.exp <= y - p)
|
|
585
|
+
throw new L('"exp" claim timestamp check failed', r, "exp", "check_failed");
|
|
586
|
+
}
|
|
587
|
+
if (h) {
|
|
588
|
+
const f = y - r.iat, oe = typeof h == "number" ? h : K(h);
|
|
589
|
+
if (f - p > oe)
|
|
590
|
+
throw new L('"iat" claim timestamp check failed (too far in the past)', r, "iat", "check_failed");
|
|
591
|
+
if (f < 0 - p)
|
|
592
592
|
throw new m('"iat" claim timestamp check failed (it should be in the past)', r, "iat", "check_failed");
|
|
593
593
|
}
|
|
594
594
|
return r;
|
|
595
595
|
};
|
|
596
|
-
async function
|
|
596
|
+
async function Ke(e, t, o) {
|
|
597
597
|
var r;
|
|
598
|
-
const n = await
|
|
598
|
+
const n = await De(e, t, o);
|
|
599
599
|
if ((r = n.protectedHeader.crit) != null && r.includes("b64") && n.protectedHeader.b64 === !1)
|
|
600
|
-
throw new
|
|
600
|
+
throw new Y("JWTs MUST NOT use unencoded payload");
|
|
601
601
|
const a = { payload: $e(n.protectedHeader, n.payload, o), protectedHeader: n.protectedHeader };
|
|
602
602
|
return typeof t == "function" ? { ...a, key: n.key } : a;
|
|
603
603
|
}
|
|
604
|
-
const
|
|
604
|
+
const We = {
|
|
605
605
|
ID_TOKEN: "id_token"
|
|
606
|
-
},
|
|
606
|
+
}, xe = {
|
|
607
607
|
CLIENT_ID: "X-Auth-ClientId"
|
|
608
608
|
}, A = {
|
|
609
609
|
ALG: "RS256",
|
|
610
610
|
USER_ID_KEY: "_id",
|
|
611
611
|
TOKEN_ID_KEY: "__raw",
|
|
612
612
|
ISSUER: "gizmette.com"
|
|
613
|
-
},
|
|
613
|
+
}, je = `-----BEGIN PUBLIC KEY-----
|
|
614
614
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsF6i3Jd9fY/3COqCw/m7
|
|
615
615
|
w5PKyTYLGAI2I6SIIdpe6i6DOCbEkmDz7LdVsBqwNtVi8gvWYIj+8ol6rU3qu1v5
|
|
616
616
|
i1Jd45GSK4kzkVdgCmQZbM5ak0KI99q5wsrAIzUd+LRJ2HRvWtr5IYdsIiXaQjle
|
|
@@ -618,10 +618,10 @@ aMwPFOIcJH+rKfFgNcHLcaS5syp7zU1ANwZ+trgR+DifBr8TLVkBynmNeTyhDm2+
|
|
|
618
618
|
l0haqjMk0UoNPPE8iYBWUHQJJE1Dqstj65d6Eh5g64Pao25y4cmYJbKjiblIGEkE
|
|
619
619
|
sjqybA9mARAqh9k/eiIopecWSiffNQTwVQVd2I9ZH3BalhEXHlqFgrjz51kFqg81
|
|
620
620
|
awIDAQAB
|
|
621
|
-
-----END PUBLIC KEY-----`,
|
|
621
|
+
-----END PUBLIC KEY-----`, ee = async (e, t) => {
|
|
622
622
|
try {
|
|
623
|
-
const o = A.ALG, r = await
|
|
624
|
-
return await
|
|
623
|
+
const o = A.ALG, r = await be(je, o);
|
|
624
|
+
return await Ke(e, r, {
|
|
625
625
|
issuer: A.ISSUER,
|
|
626
626
|
audience: t
|
|
627
627
|
});
|
|
@@ -632,26 +632,26 @@ awIDAQAB
|
|
|
632
632
|
function te(e, t) {
|
|
633
633
|
window.dispatchEvent(new StorageEvent("storage", { key: e, newValue: t }));
|
|
634
634
|
}
|
|
635
|
-
const
|
|
635
|
+
const x = (e, t) => {
|
|
636
636
|
const o = JSON.stringify(
|
|
637
637
|
typeof t == "function" ? t() : t
|
|
638
638
|
);
|
|
639
639
|
window.localStorage.setItem(e, o), te(e, o);
|
|
640
|
-
},
|
|
640
|
+
}, Me = (e) => {
|
|
641
641
|
window.localStorage.removeItem(e), te(e, null);
|
|
642
|
-
},
|
|
643
|
-
function
|
|
642
|
+
}, j = (e) => window.localStorage.getItem(e), Ve = (e) => (window.addEventListener("storage", e), () => window.removeEventListener("storage", e));
|
|
643
|
+
function Be({
|
|
644
644
|
key: e,
|
|
645
645
|
initialValue: t
|
|
646
646
|
}) {
|
|
647
|
-
const o = () =>
|
|
648
|
-
|
|
647
|
+
const o = () => j(e), r = I.useSyncExternalStore(
|
|
648
|
+
Ve,
|
|
649
649
|
o
|
|
650
650
|
), n = I.useCallback(
|
|
651
651
|
(i) => {
|
|
652
652
|
try {
|
|
653
653
|
const c = typeof i == "function" ? i(JSON.parse(r)) : i;
|
|
654
|
-
c == null ?
|
|
654
|
+
c == null ? Me(e) : x(e, c);
|
|
655
655
|
} catch (c) {
|
|
656
656
|
console.warn(c);
|
|
657
657
|
}
|
|
@@ -664,49 +664,49 @@ function Ve({
|
|
|
664
664
|
}, [n]);
|
|
665
665
|
return I.useEffect(() => {
|
|
666
666
|
try {
|
|
667
|
-
|
|
667
|
+
j(e) === null && typeof t < "u" && x(e, t);
|
|
668
668
|
} catch (i) {
|
|
669
669
|
console.warn(i);
|
|
670
670
|
}
|
|
671
671
|
}, [e, t]), [r ? JSON.parse(r) : null, n, a, s];
|
|
672
672
|
}
|
|
673
|
-
const
|
|
673
|
+
const O = "Oops! It looks like your session has expired. For your security, please log in again to continue.", Fe = "Your session has been successfully terminated.", Ge = "Login failed. Please try again.", Ye = "You forgot to wrap your component in <AuthProvider>.", M = {
|
|
674
674
|
dev: "https://auth.gizmette.local.com:3003",
|
|
675
675
|
prod: "https://mylogin.gizmette.com"
|
|
676
|
-
},
|
|
676
|
+
}, qe = "@@auth@@";
|
|
677
677
|
var d = [];
|
|
678
|
-
for (var
|
|
679
|
-
d.push((
|
|
680
|
-
function
|
|
678
|
+
for (var D = 0; D < 256; ++D)
|
|
679
|
+
d.push((D + 256).toString(16).slice(1));
|
|
680
|
+
function ze(e, t = 0) {
|
|
681
681
|
return (d[e[t + 0]] + d[e[t + 1]] + d[e[t + 2]] + d[e[t + 3]] + "-" + d[e[t + 4]] + d[e[t + 5]] + "-" + d[e[t + 6]] + d[e[t + 7]] + "-" + d[e[t + 8]] + d[e[t + 9]] + "-" + d[e[t + 10]] + d[e[t + 11]] + d[e[t + 12]] + d[e[t + 13]] + d[e[t + 14]] + d[e[t + 15]]).toLowerCase();
|
|
682
682
|
}
|
|
683
|
-
var R,
|
|
684
|
-
function
|
|
683
|
+
var R, Xe = new Uint8Array(16);
|
|
684
|
+
function Qe() {
|
|
685
685
|
if (!R && (R = typeof crypto < "u" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto), !R))
|
|
686
686
|
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
687
|
-
return R(
|
|
687
|
+
return R(Xe);
|
|
688
688
|
}
|
|
689
|
-
var
|
|
690
|
-
const
|
|
691
|
-
randomUUID:
|
|
689
|
+
var Ze = typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
690
|
+
const V = {
|
|
691
|
+
randomUUID: Ze
|
|
692
692
|
};
|
|
693
|
-
function
|
|
694
|
-
if (
|
|
695
|
-
return
|
|
693
|
+
function et(e, t, o) {
|
|
694
|
+
if (V.randomUUID && !t && !e)
|
|
695
|
+
return V.randomUUID();
|
|
696
696
|
e = e || {};
|
|
697
|
-
var r = e.random || (e.rng ||
|
|
698
|
-
return r[6] = r[6] & 15 | 64, r[8] = r[8] & 63 | 128,
|
|
697
|
+
var r = e.random || (e.rng || Qe)();
|
|
698
|
+
return r[6] = r[6] & 15 | 64, r[8] = r[8] & 63 | 128, ze(r);
|
|
699
699
|
}
|
|
700
|
-
const
|
|
700
|
+
const tt = process.env.NODE_ENV === "production", rt = !tt, ot = async ({ params: e = {} }) => {
|
|
701
701
|
try {
|
|
702
|
-
const t =
|
|
703
|
-
|
|
702
|
+
const t = et(), o = await fetch(
|
|
703
|
+
rt ? `${M.dev}/authenticate` : `${M.prod}/authenticate`,
|
|
704
704
|
{
|
|
705
705
|
credentials: "include",
|
|
706
706
|
method: "POST",
|
|
707
707
|
headers: {
|
|
708
708
|
"Content-Type": "application/json",
|
|
709
|
-
[
|
|
709
|
+
[xe.CLIENT_ID]: `${e.clientId}`
|
|
710
710
|
},
|
|
711
711
|
body: JSON.stringify({ ...e, nonce: t })
|
|
712
712
|
}
|
|
@@ -722,22 +722,22 @@ const Ze = process.env.NODE_ENV === "production", et = !Ze, tt = async ({ params
|
|
|
722
722
|
} catch (t) {
|
|
723
723
|
return console.error(t), { status: 500, data: [] };
|
|
724
724
|
}
|
|
725
|
-
},
|
|
725
|
+
}, nt = async ({
|
|
726
726
|
username: e,
|
|
727
727
|
password: t,
|
|
728
728
|
clientId: o,
|
|
729
729
|
sessionExpiration: r
|
|
730
730
|
}) => {
|
|
731
731
|
try {
|
|
732
|
-
const n = await
|
|
732
|
+
const n = await ot({
|
|
733
733
|
params: {
|
|
734
|
-
type:
|
|
734
|
+
type: We.ID_TOKEN,
|
|
735
735
|
username: e,
|
|
736
736
|
password: t,
|
|
737
737
|
sessionExpiration: r,
|
|
738
738
|
clientId: o
|
|
739
739
|
}
|
|
740
|
-
}), a = await
|
|
740
|
+
}), a = await ee(n.data.idToken, o);
|
|
741
741
|
return a && a.payload[A.USER_ID_KEY] !== "" ? {
|
|
742
742
|
idToken: n.data.idToken,
|
|
743
743
|
userId: a.payload[A.USER_ID_KEY],
|
|
@@ -751,90 +751,83 @@ const Ze = process.env.NODE_ENV === "production", et = !Ze, tt = async ({ params
|
|
|
751
751
|
};
|
|
752
752
|
}
|
|
753
753
|
};
|
|
754
|
-
function
|
|
754
|
+
function at(e) {
|
|
755
755
|
const t = ae();
|
|
756
|
-
return
|
|
756
|
+
return F(() => {
|
|
757
757
|
t.current = e;
|
|
758
758
|
}), t.current;
|
|
759
759
|
}
|
|
760
|
-
const
|
|
761
|
-
throw new Error(
|
|
760
|
+
const B = () => {
|
|
761
|
+
throw new Error(Ye);
|
|
762
762
|
}, re = se({
|
|
763
763
|
isAuthenticated: !1,
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
logoutReason: ""
|
|
768
|
-
|
|
764
|
+
isLoading: !1,
|
|
765
|
+
login: B,
|
|
766
|
+
logout: B,
|
|
767
|
+
logoutReason: "",
|
|
768
|
+
idTokenClaims: null
|
|
769
|
+
}), ut = ({
|
|
769
770
|
children: e,
|
|
770
771
|
sessionExpiration: t,
|
|
771
772
|
clientId: o
|
|
772
773
|
}) => {
|
|
773
|
-
const [r, n, , a] =
|
|
774
|
-
key: `${
|
|
774
|
+
const [r, n, , a] = Be({
|
|
775
|
+
key: `${qe}::${o}::@@user@@`
|
|
775
776
|
}), [s, i] = ie({
|
|
776
|
-
|
|
777
|
+
isLoading: !0,
|
|
778
|
+
isAuthenticated: !1,
|
|
777
779
|
logoutReason: "",
|
|
778
|
-
userId: ""
|
|
779
|
-
|
|
780
|
-
|
|
780
|
+
userId: "",
|
|
781
|
+
idTokenClaims: null
|
|
782
|
+
}), c = at(r) || "", h = ce(
|
|
783
|
+
(u) => {
|
|
784
|
+
i({
|
|
785
|
+
isLoading: !1,
|
|
786
|
+
isAuthenticated: !1,
|
|
787
|
+
logoutReason: u || O,
|
|
788
|
+
userId: "",
|
|
789
|
+
idTokenClaims: null
|
|
790
|
+
}), a();
|
|
791
|
+
},
|
|
792
|
+
[a]
|
|
793
|
+
);
|
|
794
|
+
F(() => {
|
|
781
795
|
c !== r && r !== null && (async () => {
|
|
782
796
|
try {
|
|
783
|
-
const u = await
|
|
797
|
+
const u = await ee(r, o);
|
|
784
798
|
u && u.payload[A.USER_ID_KEY] !== "" ? i({
|
|
799
|
+
isLoading: !1,
|
|
785
800
|
isAuthenticated: !0,
|
|
786
801
|
logoutReason: "",
|
|
787
|
-
userId: u.payload[A.USER_ID_KEY]
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
});
|
|
802
|
+
userId: u.payload[A.USER_ID_KEY],
|
|
803
|
+
idTokenClaims: {
|
|
804
|
+
...u == null ? void 0 : u.payload,
|
|
805
|
+
[A.TOKEN_ID_KEY]: r
|
|
806
|
+
}
|
|
807
|
+
}) : h(O);
|
|
793
808
|
} catch {
|
|
794
|
-
|
|
795
|
-
isAuthenticated: !1,
|
|
796
|
-
logoutReason: V,
|
|
797
|
-
userId: ""
|
|
798
|
-
});
|
|
809
|
+
h(O);
|
|
799
810
|
}
|
|
800
811
|
})();
|
|
801
|
-
}, [r, c, o]);
|
|
802
|
-
const
|
|
803
|
-
const
|
|
812
|
+
}, [r, c, o, h]);
|
|
813
|
+
const w = async (u, y) => {
|
|
814
|
+
const f = await nt({
|
|
804
815
|
username: u,
|
|
805
816
|
password: y,
|
|
806
817
|
clientId: o,
|
|
807
818
|
sessionExpiration: t
|
|
808
819
|
});
|
|
809
|
-
return
|
|
820
|
+
return f.status ? (n(f.idToken), i({
|
|
821
|
+
isLoading: !1,
|
|
810
822
|
isAuthenticated: !0,
|
|
811
|
-
userId:
|
|
812
|
-
}), !0) : !1;
|
|
813
|
-
},
|
|
814
|
-
|
|
815
|
-
isAuthenticated: !1,
|
|
816
|
-
logoutReason: Be,
|
|
817
|
-
userId: ""
|
|
818
|
-
}), a();
|
|
819
|
-
}, h = async () => {
|
|
820
|
-
if (s.isAuthenticated)
|
|
821
|
-
try {
|
|
822
|
-
const u = await N(r, o);
|
|
823
|
-
return { ...u == null ? void 0 : u.payload, [A.TOKEN_ID_KEY]: r };
|
|
824
|
-
} catch {
|
|
825
|
-
return {};
|
|
826
|
-
}
|
|
827
|
-
return {};
|
|
823
|
+
userId: f.userId
|
|
824
|
+
}), !0) : (h(Ge), !1);
|
|
825
|
+
}, p = () => {
|
|
826
|
+
h(Fe);
|
|
828
827
|
};
|
|
829
|
-
return /* @__PURE__ */ ne(
|
|
830
|
-
|
|
831
|
-
{
|
|
832
|
-
value: { ...s, login: f, logout: w, getIdTokenClaims: h },
|
|
833
|
-
children: e
|
|
834
|
-
}
|
|
835
|
-
);
|
|
836
|
-
}, ct = (e = re) => ce(e);
|
|
828
|
+
return /* @__PURE__ */ ne(re.Provider, { value: { ...s, login: w, logout: p }, children: e });
|
|
829
|
+
}, dt = (e = re) => ue(e);
|
|
837
830
|
export {
|
|
838
|
-
|
|
839
|
-
|
|
831
|
+
ut as AuthProvider,
|
|
832
|
+
dt as useAuth
|
|
840
833
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versini/auth-provider",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"publishConfig": {
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"jose": "5.4.1",
|
|
50
50
|
"uuid": "10.0.0"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "b9b733518d3e78c87fbb366cb4e5668a7a928cdd"
|
|
53
53
|
}
|