@ahoo-wang/fetcher-cosec 3.4.6 → 3.5.1
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.es.js +123 -40
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/jwtToken.d.ts +147 -16
- package/dist/jwtToken.d.ts.map +1 -1
- package/dist/tokenStorage.d.ts +48 -2
- package/dist/tokenStorage.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.es.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { REQUEST_BODY_INTERCEPTOR_ORDER as w, FetcherError as D, ResultExtractors as U } from "@ahoo-wang/fetcher";
|
|
2
2
|
import { nanoid as y } from "nanoid";
|
|
3
3
|
import { KeyStorage as f, typedIdentitySerializer as C } from "@ahoo-wang/fetcher-storage";
|
|
4
|
-
import { BroadcastTypedEventBus as O, SerialTypedEventBus as
|
|
4
|
+
import { BroadcastTypedEventBus as O, SerialTypedEventBus as g } from "@ahoo-wang/fetcher-eventbus";
|
|
5
5
|
const a = class a {
|
|
6
6
|
};
|
|
7
7
|
a.DEVICE_ID = "CoSec-Device-Id", a.APP_ID = "CoSec-App-Id", a.AUTHORIZATION = "Authorization", a.REQUEST_ID = "CoSec-Request-Id";
|
|
8
|
-
let
|
|
8
|
+
let o = a;
|
|
9
9
|
const u = class u {
|
|
10
10
|
};
|
|
11
11
|
u.UNAUTHORIZED = 401, u.FORBIDDEN = 403;
|
|
@@ -27,14 +27,14 @@ class m {
|
|
|
27
27
|
return y();
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
const
|
|
30
|
+
const _ = new m(), b = "CoSecRequestInterceptor", N = w + 1e3, k = "Ignore-Refresh-Token";
|
|
31
31
|
class M {
|
|
32
32
|
/**
|
|
33
33
|
* Creates a new CoSecRequestInterceptor instance.
|
|
34
34
|
* @param options - The CoSec configuration options including appId, deviceIdStorage, and tokenManager
|
|
35
35
|
*/
|
|
36
36
|
constructor(e) {
|
|
37
|
-
this.name = b, this.order =
|
|
37
|
+
this.name = b, this.order = N, this.options = e;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Intercept requests to add CoSec authentication headers.
|
|
@@ -59,11 +59,11 @@ class M {
|
|
|
59
59
|
* It will attempt to refresh the token before adding the Authorization header to the request.
|
|
60
60
|
*/
|
|
61
61
|
async intercept(e) {
|
|
62
|
-
const t =
|
|
63
|
-
o
|
|
62
|
+
const t = _.generateId(), r = this.options.deviceIdStorage.getOrCreate(), n = e.ensureRequestHeaders();
|
|
63
|
+
n[o.APP_ID] = this.options.appId, n[o.DEVICE_ID] = r, n[o.REQUEST_ID] = t;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
const z = "AuthorizationRequestInterceptor", q =
|
|
66
|
+
const z = "AuthorizationRequestInterceptor", q = N + 1e3;
|
|
67
67
|
class v {
|
|
68
68
|
/**
|
|
69
69
|
* Creates an AuthorizationRequestInterceptor instance.
|
|
@@ -87,7 +87,7 @@ class v {
|
|
|
87
87
|
async intercept(e) {
|
|
88
88
|
let t = this.options.tokenManager.currentToken;
|
|
89
89
|
const r = e.ensureRequestHeaders();
|
|
90
|
-
!t || r[
|
|
90
|
+
!t || r[o.AUTHORIZATION] || (!e.attributes.has(k) && t.isRefreshNeeded && t.isRefreshable && await this.options.tokenManager.refresh(), t = this.options.tokenManager.currentToken, t && (r[o.AUTHORIZATION] = `Bearer ${t.access.token}`));
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
const F = "AuthorizationResponseInterceptor", K = Number.MIN_SAFE_INTEGER + 1e3;
|
|
@@ -118,7 +118,7 @@ class H extends f {
|
|
|
118
118
|
constructor({
|
|
119
119
|
key: e = p,
|
|
120
120
|
eventBus: t = new O({
|
|
121
|
-
delegate: new
|
|
121
|
+
delegate: new g(p)
|
|
122
122
|
}),
|
|
123
123
|
...r
|
|
124
124
|
} = {}) {
|
|
@@ -130,7 +130,7 @@ class H extends f {
|
|
|
130
130
|
* @returns A newly generated device ID
|
|
131
131
|
*/
|
|
132
132
|
generateDeviceId() {
|
|
133
|
-
return
|
|
133
|
+
return _.generateId();
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* Get or create a device ID.
|
|
@@ -142,8 +142,8 @@ class H extends f {
|
|
|
142
142
|
return e || (e = this.generateDeviceId(), this.set(e)), e;
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
-
const Z = "ForbiddenErrorInterceptor",
|
|
146
|
-
class
|
|
145
|
+
const Z = "ForbiddenErrorInterceptor", x = 0;
|
|
146
|
+
class J {
|
|
147
147
|
/**
|
|
148
148
|
* Creates a new ForbiddenErrorInterceptor instance.
|
|
149
149
|
*
|
|
@@ -162,7 +162,7 @@ class Q {
|
|
|
162
162
|
* ```
|
|
163
163
|
*/
|
|
164
164
|
constructor(e) {
|
|
165
|
-
this.options = e, this.name = Z, this.order =
|
|
165
|
+
this.options = e, this.name = Z, this.order = x;
|
|
166
166
|
}
|
|
167
167
|
/**
|
|
168
168
|
* Intercepts fetch exchanges to detect and handle forbidden (403) responses.
|
|
@@ -209,7 +209,7 @@ class E extends D {
|
|
|
209
209
|
super("Refresh token failed.", t), this.token = e, this.name = "RefreshTokenError", Object.setPrototypeOf(this, E.prototype);
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
-
class
|
|
212
|
+
class Q {
|
|
213
213
|
/**
|
|
214
214
|
* Creates a new JwtTokenManager instance
|
|
215
215
|
* @param tokenStorage The storage used to persist tokens
|
|
@@ -282,12 +282,12 @@ class V {
|
|
|
282
282
|
const r = t.access.payload;
|
|
283
283
|
if (!r || !r.tenantId && !r.sub)
|
|
284
284
|
return;
|
|
285
|
-
const
|
|
285
|
+
const n = e.fetcher.urlBuilder.urlTemplateResolver.extractPathParams(
|
|
286
286
|
e.request.url
|
|
287
|
-
), c = this.tenantIdPathKey, i = e.ensureRequestUrlParams().path,
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
I &&
|
|
287
|
+
), c = this.tenantIdPathKey, i = e.ensureRequestUrlParams().path, R = r.tenantId;
|
|
288
|
+
R && n.includes(c) && !i[c] && (i[c] = R);
|
|
289
|
+
const d = this.ownerIdPathKey, I = r.sub;
|
|
290
|
+
I && n.includes(d) && !i[d] && (i[d] = I);
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
function S(s) {
|
|
@@ -297,11 +297,11 @@ function S(s) {
|
|
|
297
297
|
const e = s.split(".");
|
|
298
298
|
if (e.length !== 3)
|
|
299
299
|
return null;
|
|
300
|
-
const r = e[1].replace(/-/g, "+").replace(/_/g, "/"),
|
|
300
|
+
const r = e[1].replace(/-/g, "+").replace(/_/g, "/"), n = r.padEnd(
|
|
301
301
|
r.length + (4 - r.length % 4) % 4,
|
|
302
302
|
"="
|
|
303
303
|
), c = decodeURIComponent(
|
|
304
|
-
atob(
|
|
304
|
+
atob(n).split("").map(function(i) {
|
|
305
305
|
return "%" + ("00" + i.charCodeAt(0).toString(16)).slice(-2);
|
|
306
306
|
}).join("")
|
|
307
307
|
);
|
|
@@ -319,14 +319,27 @@ function W(s, e = 0) {
|
|
|
319
319
|
}
|
|
320
320
|
class T {
|
|
321
321
|
/**
|
|
322
|
-
* Creates a new JwtToken instance
|
|
322
|
+
* Creates a new JwtToken instance.
|
|
323
|
+
*
|
|
324
|
+
* Parses the JWT token string to extract the payload and stores the early period
|
|
325
|
+
* for expiration checks.
|
|
326
|
+
*
|
|
327
|
+
* @param token The raw JWT token string to parse
|
|
328
|
+
* @param earlyPeriod The early expiration period in milliseconds (default: 0).
|
|
329
|
+
* Tokens are considered expired this many milliseconds before their actual expiration time.
|
|
330
|
+
*
|
|
331
|
+
* @throws Will not throw but payload will be null if token parsing fails
|
|
323
332
|
*/
|
|
324
333
|
constructor(e, t = 0) {
|
|
325
334
|
this.token = e, this.earlyPeriod = t, this.payload = S(e);
|
|
326
335
|
}
|
|
327
336
|
/**
|
|
328
|
-
* Checks if the token is expired
|
|
329
|
-
*
|
|
337
|
+
* Checks if the token is expired.
|
|
338
|
+
*
|
|
339
|
+
* Considers both the token's expiration time and the early period.
|
|
340
|
+
* Returns true if the payload is null (parsing failed) or if the token is expired.
|
|
341
|
+
*
|
|
342
|
+
* @returns true if the token is expired or invalid, false otherwise
|
|
330
343
|
*/
|
|
331
344
|
get isExpired() {
|
|
332
345
|
return this.payload ? W(this.payload, this.earlyPeriod) : !0;
|
|
@@ -334,41 +347,69 @@ class T {
|
|
|
334
347
|
}
|
|
335
348
|
class A {
|
|
336
349
|
/**
|
|
337
|
-
* Creates a new JwtCompositeToken instance
|
|
350
|
+
* Creates a new JwtCompositeToken instance.
|
|
351
|
+
*
|
|
352
|
+
* Initializes both access and refresh token instances with the provided early period.
|
|
353
|
+
*
|
|
354
|
+
* @param token The composite token containing access and refresh token strings
|
|
355
|
+
* @param earlyPeriod The early expiration period in milliseconds (default: 0)
|
|
338
356
|
*/
|
|
339
357
|
constructor(e, t = 0) {
|
|
340
358
|
this.token = e, this.earlyPeriod = t, this.access = new T(e.accessToken, t), this.refresh = new T(e.refreshToken, t);
|
|
341
359
|
}
|
|
342
360
|
/**
|
|
343
|
-
* Checks if the access token needs to be refreshed
|
|
361
|
+
* Checks if the access token needs to be refreshed.
|
|
362
|
+
*
|
|
344
363
|
* @returns true if the access token is expired, false otherwise
|
|
345
364
|
*/
|
|
346
365
|
get isRefreshNeeded() {
|
|
347
366
|
return this.access.isExpired;
|
|
348
367
|
}
|
|
349
368
|
/**
|
|
350
|
-
* Checks if the refresh token is still valid and can be used to refresh the access token
|
|
369
|
+
* Checks if the refresh token is still valid and can be used to refresh the access token.
|
|
370
|
+
*
|
|
351
371
|
* @returns true if the refresh token is not expired, false otherwise
|
|
352
372
|
*/
|
|
353
373
|
get isRefreshable() {
|
|
354
374
|
return !this.refresh.isExpired;
|
|
355
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Checks if the user is currently authenticated (access token is valid).
|
|
378
|
+
*
|
|
379
|
+
* @returns true if the access token is not expired, false otherwise
|
|
380
|
+
*/
|
|
381
|
+
get authenticated() {
|
|
382
|
+
return !this.access.isExpired;
|
|
383
|
+
}
|
|
356
384
|
}
|
|
357
385
|
class P {
|
|
386
|
+
/**
|
|
387
|
+
* Creates a new JwtCompositeTokenSerializer instance.
|
|
388
|
+
*
|
|
389
|
+
* @param earlyPeriod The early expiration period in milliseconds to use for deserialized tokens (default: 0)
|
|
390
|
+
*/
|
|
358
391
|
constructor(e = 0) {
|
|
359
392
|
this.earlyPeriod = e;
|
|
360
393
|
}
|
|
361
394
|
/**
|
|
362
|
-
* Deserializes a JSON string to a JwtCompositeToken
|
|
395
|
+
* Deserializes a JSON string to a JwtCompositeToken.
|
|
396
|
+
*
|
|
397
|
+
* Parses the JSON string and creates a new JwtCompositeToken instance with the stored tokens.
|
|
398
|
+
*
|
|
363
399
|
* @param value The JSON string representation of a composite token
|
|
364
400
|
* @returns A JwtCompositeToken instance
|
|
401
|
+
* @throws SyntaxError if the JSON string is invalid
|
|
402
|
+
* @throws Error if the parsed object doesn't match the expected CompositeToken structure
|
|
365
403
|
*/
|
|
366
404
|
deserialize(e) {
|
|
367
405
|
const t = JSON.parse(e);
|
|
368
406
|
return new A(t, this.earlyPeriod);
|
|
369
407
|
}
|
|
370
408
|
/**
|
|
371
|
-
* Serializes a JwtCompositeToken to a JSON string
|
|
409
|
+
* Serializes a JwtCompositeToken to a JSON string.
|
|
410
|
+
*
|
|
411
|
+
* Converts the composite token to a JSON string for storage.
|
|
412
|
+
*
|
|
372
413
|
* @param value The JwtCompositeToken to serialize
|
|
373
414
|
* @returns A JSON string representation of the composite token
|
|
374
415
|
*/
|
|
@@ -378,24 +419,66 @@ class P {
|
|
|
378
419
|
}
|
|
379
420
|
const ae = new P(), l = "cosec-token";
|
|
380
421
|
class X extends f {
|
|
422
|
+
/**
|
|
423
|
+
* Creates a new TokenStorage instance.
|
|
424
|
+
* @param options - Configuration options for the token storage.
|
|
425
|
+
* @param options.key - The storage key for tokens. Defaults to DEFAULT_COSEC_TOKEN_KEY.
|
|
426
|
+
* @param options.eventBus - Event bus for token change notifications. Defaults to a BroadcastTypedEventBus with SerialTypedEventBus delegate.
|
|
427
|
+
* @param options.earlyPeriod - Early period for token refresh in milliseconds. Defaults to 0.
|
|
428
|
+
* @param reset - Additional options passed to KeyStorage.
|
|
429
|
+
*/
|
|
381
430
|
constructor({
|
|
382
431
|
key: e = l,
|
|
383
432
|
eventBus: t = new O({
|
|
384
|
-
delegate: new
|
|
433
|
+
delegate: new g(l)
|
|
385
434
|
}),
|
|
386
435
|
earlyPeriod: r = 0,
|
|
387
|
-
...
|
|
436
|
+
...n
|
|
388
437
|
} = {}) {
|
|
389
438
|
super({
|
|
390
439
|
key: e,
|
|
391
440
|
eventBus: t,
|
|
392
|
-
...
|
|
441
|
+
...n,
|
|
393
442
|
serializer: new P(r)
|
|
394
443
|
}), this.earlyPeriod = r;
|
|
395
444
|
}
|
|
445
|
+
/**
|
|
446
|
+
* Sets a composite token in storage.
|
|
447
|
+
* Converts the composite token to a JwtCompositeToken and stores it.
|
|
448
|
+
* @deprecated Use signIn() instead for better semantic clarity.
|
|
449
|
+
* @param compositeToken - The composite token containing access and refresh tokens.
|
|
450
|
+
*/
|
|
396
451
|
setCompositeToken(e) {
|
|
452
|
+
this.signIn(e);
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Signs in by storing the composite token.
|
|
456
|
+
* @param compositeToken - The composite token to store for authentication.
|
|
457
|
+
*/
|
|
458
|
+
signIn(e) {
|
|
397
459
|
this.set(new A(e, this.earlyPeriod));
|
|
398
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* Signs out by removing the stored token.
|
|
463
|
+
* Clears the token from storage.
|
|
464
|
+
*/
|
|
465
|
+
signOut() {
|
|
466
|
+
this.remove();
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Checks if the user is authenticated.
|
|
470
|
+
* @returns true if a valid token is present and authenticated, false otherwise.
|
|
471
|
+
*/
|
|
472
|
+
get authenticated() {
|
|
473
|
+
return this.get()?.authenticated === !0;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Gets the current user's JWT payload.
|
|
477
|
+
* @returns The JWT payload of the current user if authenticated, null otherwise.
|
|
478
|
+
*/
|
|
479
|
+
get currentUser() {
|
|
480
|
+
return this.authenticated ? this.get()?.access.payload ?? null : null;
|
|
481
|
+
}
|
|
399
482
|
}
|
|
400
483
|
const $ = "UnauthorizedErrorInterceptor", ee = 0;
|
|
401
484
|
class te {
|
|
@@ -461,7 +544,7 @@ class ce {
|
|
|
461
544
|
* ```
|
|
462
545
|
*/
|
|
463
546
|
constructor(e) {
|
|
464
|
-
this.config = e, this.tokenStorage = e.tokenStorage ?? new X(), this.deviceIdStorage = e.deviceIdStorage ?? new H(), e.tokenRefresher && (this.tokenManager = new
|
|
547
|
+
this.config = e, this.tokenStorage = e.tokenStorage ?? new X(), this.deviceIdStorage = e.deviceIdStorage ?? new H(), e.tokenRefresher && (this.tokenManager = new Q(
|
|
465
548
|
this.tokenStorage,
|
|
466
549
|
e.tokenRefresher
|
|
467
550
|
));
|
|
@@ -522,7 +605,7 @@ class ce {
|
|
|
522
605
|
onUnauthorized: this.config.onUnauthorized
|
|
523
606
|
})
|
|
524
607
|
), this.config.onForbidden && e.interceptors.error.use(
|
|
525
|
-
new
|
|
608
|
+
new J({
|
|
526
609
|
onForbidden: this.config.onForbidden
|
|
527
610
|
})
|
|
528
611
|
);
|
|
@@ -602,22 +685,22 @@ export {
|
|
|
602
685
|
B as AuthorizationResponseInterceptor,
|
|
603
686
|
ie as AuthorizeResults,
|
|
604
687
|
b as COSEC_REQUEST_INTERCEPTOR_NAME,
|
|
605
|
-
|
|
688
|
+
N as COSEC_REQUEST_INTERCEPTOR_ORDER,
|
|
606
689
|
ce as CoSecConfigurer,
|
|
607
|
-
|
|
690
|
+
o as CoSecHeaders,
|
|
608
691
|
M as CoSecRequestInterceptor,
|
|
609
692
|
he as CoSecTokenRefresher,
|
|
610
693
|
p as DEFAULT_COSEC_DEVICE_ID_KEY,
|
|
611
694
|
l as DEFAULT_COSEC_TOKEN_KEY,
|
|
612
695
|
H as DeviceIdStorage,
|
|
613
696
|
Z as FORBIDDEN_ERROR_INTERCEPTOR_NAME,
|
|
614
|
-
|
|
615
|
-
|
|
697
|
+
x as FORBIDDEN_ERROR_INTERCEPTOR_ORDER,
|
|
698
|
+
J as ForbiddenErrorInterceptor,
|
|
616
699
|
k as IGNORE_REFRESH_TOKEN_ATTRIBUTE_KEY,
|
|
617
700
|
A as JwtCompositeToken,
|
|
618
701
|
P as JwtCompositeTokenSerializer,
|
|
619
702
|
T as JwtToken,
|
|
620
|
-
|
|
703
|
+
Q as JwtTokenManager,
|
|
621
704
|
m as NanoIdGenerator,
|
|
622
705
|
j as RESOURCE_ATTRIBUTION_REQUEST_INTERCEPTOR_NAME,
|
|
623
706
|
G as RESOURCE_ATTRIBUTION_REQUEST_INTERCEPTOR_ORDER,
|
|
@@ -628,7 +711,7 @@ export {
|
|
|
628
711
|
$ as UNAUTHORIZED_ERROR_INTERCEPTOR_NAME,
|
|
629
712
|
ee as UNAUTHORIZED_ERROR_INTERCEPTOR_ORDER,
|
|
630
713
|
te as UnauthorizedErrorInterceptor,
|
|
631
|
-
|
|
714
|
+
_ as idGenerator,
|
|
632
715
|
W as isTokenExpired,
|
|
633
716
|
ae as jwtCompositeTokenSerializer,
|
|
634
717
|
S as parseJwtPayload
|