@ahoo-wang/fetcher-cosec 3.0.2 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -0
- package/README.zh-CN.md +104 -0
- package/dist/cosecConfigurer.d.ts +88 -0
- package/dist/cosecConfigurer.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +285 -231
- 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/resourceAttributionRequestInterceptor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.es.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { REQUEST_BODY_INTERCEPTOR_ORDER as
|
|
2
|
-
import { nanoid as
|
|
1
|
+
import { REQUEST_BODY_INTERCEPTOR_ORDER as w, FetcherError as D, ResultExtractors as y } from "@ahoo-wang/fetcher";
|
|
2
|
+
import { nanoid as U } from "nanoid";
|
|
3
3
|
import { KeyStorage as f } from "@ahoo-wang/fetcher-storage";
|
|
4
4
|
import { BroadcastTypedEventBus as O, SerialTypedEventBus as _ } 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
8
|
let n = a;
|
|
9
|
-
const
|
|
9
|
+
const u = class u {
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
let h =
|
|
13
|
-
const
|
|
11
|
+
u.UNAUTHORIZED = 401, u.FORBIDDEN = 403;
|
|
12
|
+
let h = u;
|
|
13
|
+
const ne = {
|
|
14
14
|
ALLOW: { authorized: !0, reason: "Allow" },
|
|
15
15
|
EXPLICIT_DENY: { authorized: !1, reason: "Explicit Deny" },
|
|
16
16
|
IMPLICIT_DENY: { authorized: !1, reason: "Implicit Deny" },
|
|
@@ -24,17 +24,17 @@ class C {
|
|
|
24
24
|
* @returns A unique request ID
|
|
25
25
|
*/
|
|
26
26
|
generateId() {
|
|
27
|
-
return
|
|
27
|
+
return U();
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
const
|
|
31
|
-
class
|
|
30
|
+
const g = new C(), m = "CoSecRequestInterceptor", N = w + 1e3, k = "Ignore-Refresh-Token";
|
|
31
|
+
class b {
|
|
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 = m, this.order =
|
|
37
|
+
this.name = m, this.order = N, this.options = e;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Intercept requests to add CoSec authentication headers.
|
|
@@ -59,19 +59,19 @@ class G {
|
|
|
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[n.APP_ID] = this.options.appId, o[n.DEVICE_ID] =
|
|
62
|
+
const t = g.generateId(), s = this.options.deviceIdStorage.getOrCreate(), o = e.ensureRequestHeaders();
|
|
63
|
+
o[n.APP_ID] = this.options.appId, o[n.DEVICE_ID] = s, o[n.REQUEST_ID] = t;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
const
|
|
67
|
-
class
|
|
66
|
+
const M = "AuthorizationRequestInterceptor", z = N + 1e3;
|
|
67
|
+
class q {
|
|
68
68
|
/**
|
|
69
69
|
* Creates an AuthorizationRequestInterceptor instance.
|
|
70
70
|
*
|
|
71
71
|
* @param options - Configuration options containing the token manager
|
|
72
72
|
*/
|
|
73
73
|
constructor(e) {
|
|
74
|
-
this.options = e, this.name =
|
|
74
|
+
this.options = e, this.name = M, this.order = z;
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
77
77
|
* Intercepts the request exchange to add authorization headers.
|
|
@@ -86,18 +86,18 @@ class V {
|
|
|
86
86
|
*/
|
|
87
87
|
async intercept(e) {
|
|
88
88
|
let t = this.options.tokenManager.currentToken;
|
|
89
|
-
const
|
|
90
|
-
!t ||
|
|
89
|
+
const s = e.ensureRequestHeaders();
|
|
90
|
+
!t || s[n.AUTHORIZATION] || (!e.attributes.has(k) && t.isRefreshNeeded && t.isRefreshable && await this.options.tokenManager.refresh(), t = this.options.tokenManager.currentToken, t && (s[n.AUTHORIZATION] = `Bearer ${t.access.token}`));
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
const
|
|
94
|
-
class
|
|
93
|
+
const v = "AuthorizationResponseInterceptor", F = Number.MIN_SAFE_INTEGER + 1e3;
|
|
94
|
+
class B {
|
|
95
95
|
/**
|
|
96
96
|
* Creates a new AuthorizationResponseInterceptor instance.
|
|
97
97
|
* @param options - The CoSec configuration options including token storage and refresher
|
|
98
98
|
*/
|
|
99
99
|
constructor(e) {
|
|
100
|
-
this.options = e, this.name =
|
|
100
|
+
this.options = e, this.name = v, this.order = F;
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Intercepts the response and handles unauthorized responses by refreshing tokens.
|
|
@@ -108,16 +108,16 @@ class X {
|
|
|
108
108
|
if (t && t.status === h.UNAUTHORIZED && this.options.tokenManager.isRefreshable)
|
|
109
109
|
try {
|
|
110
110
|
await this.options.tokenManager.refresh(), await e.fetcher.interceptors.exchange(e);
|
|
111
|
-
} catch (
|
|
112
|
-
throw this.options.tokenManager.tokenStorage.remove(),
|
|
111
|
+
} catch (s) {
|
|
112
|
+
throw this.options.tokenManager.tokenStorage.remove(), s;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
const
|
|
117
|
-
class
|
|
116
|
+
const T = "cosec-device-id";
|
|
117
|
+
class K extends f {
|
|
118
118
|
constructor(e = {
|
|
119
|
-
key:
|
|
120
|
-
eventBus: new O({ delegate: new _(
|
|
119
|
+
key: T,
|
|
120
|
+
eventBus: new O({ delegate: new _(T) })
|
|
121
121
|
}) {
|
|
122
122
|
super(e);
|
|
123
123
|
}
|
|
@@ -127,7 +127,7 @@ class W extends f {
|
|
|
127
127
|
* @returns A newly generated device ID
|
|
128
128
|
*/
|
|
129
129
|
generateDeviceId() {
|
|
130
|
-
return
|
|
130
|
+
return g.generateId();
|
|
131
131
|
}
|
|
132
132
|
/**
|
|
133
133
|
* Get or create a device ID.
|
|
@@ -139,99 +139,74 @@ class W extends f {
|
|
|
139
139
|
return e || (e = this.generateDeviceId(), this.set(e)), e;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (typeof s != "string")
|
|
145
|
-
return null;
|
|
146
|
-
const e = s.split(".");
|
|
147
|
-
if (e.length !== 3)
|
|
148
|
-
return null;
|
|
149
|
-
const r = e[1].replace(/-/g, "+").replace(/_/g, "/"), o = r.padEnd(
|
|
150
|
-
r.length + (4 - r.length % 4) % 4,
|
|
151
|
-
"="
|
|
152
|
-
), c = decodeURIComponent(
|
|
153
|
-
atob(o).split("").map(function(i) {
|
|
154
|
-
return "%" + ("00" + i.charCodeAt(0).toString(16)).slice(-2);
|
|
155
|
-
}).join("")
|
|
156
|
-
);
|
|
157
|
-
return JSON.parse(c);
|
|
158
|
-
} catch (e) {
|
|
159
|
-
return console.error("Failed to parse JWT token", e), null;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function v(s, e = 0) {
|
|
163
|
-
const t = typeof s == "string" ? k(s) : s;
|
|
164
|
-
if (!t)
|
|
165
|
-
return !0;
|
|
166
|
-
const r = t.exp;
|
|
167
|
-
return r ? Date.now() / 1e3 > r - e : !1;
|
|
168
|
-
}
|
|
169
|
-
class p {
|
|
170
|
-
/**
|
|
171
|
-
* Creates a new JwtToken instance
|
|
172
|
-
*/
|
|
173
|
-
constructor(e, t = 0) {
|
|
174
|
-
this.token = e, this.earlyPeriod = t, this.payload = k(e);
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Checks if the token is expired
|
|
178
|
-
* @returns true if the token is expired, false otherwise
|
|
179
|
-
*/
|
|
180
|
-
get isExpired() {
|
|
181
|
-
return this.payload ? v(this.payload, this.earlyPeriod) : !0;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
class g {
|
|
185
|
-
/**
|
|
186
|
-
* Creates a new JwtCompositeToken instance
|
|
187
|
-
*/
|
|
188
|
-
constructor(e, t = 0) {
|
|
189
|
-
this.token = e, this.earlyPeriod = t, this.access = new p(e.accessToken, t), this.refresh = new p(e.refreshToken, t);
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Checks if the access token needs to be refreshed
|
|
193
|
-
* @returns true if the access token is expired, false otherwise
|
|
194
|
-
*/
|
|
195
|
-
get isRefreshNeeded() {
|
|
196
|
-
return this.access.isExpired;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Checks if the refresh token is still valid and can be used to refresh the access token
|
|
200
|
-
* @returns true if the refresh token is not expired, false otherwise
|
|
201
|
-
*/
|
|
202
|
-
get isRefreshable() {
|
|
203
|
-
return !this.refresh.isExpired;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
class y {
|
|
207
|
-
constructor(e = 0) {
|
|
208
|
-
this.earlyPeriod = e;
|
|
209
|
-
}
|
|
142
|
+
const H = "ForbiddenErrorInterceptor", Z = 0;
|
|
143
|
+
class J {
|
|
210
144
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* @
|
|
145
|
+
* Creates a new ForbiddenErrorInterceptor instance.
|
|
146
|
+
*
|
|
147
|
+
* @param options - Configuration options containing the callback to handle forbidden responses.
|
|
148
|
+
* Must include the `onForbidden` callback function.
|
|
149
|
+
*
|
|
150
|
+
* @throws Will throw an error if options are not provided or if `onForbidden` callback is missing.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const interceptor = new ForbiddenErrorInterceptor({
|
|
155
|
+
* onForbidden: async (exchange) => {
|
|
156
|
+
* // Handle forbidden access
|
|
157
|
+
* }
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
214
160
|
*/
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return new g(t, this.earlyPeriod);
|
|
161
|
+
constructor(e) {
|
|
162
|
+
this.options = e, this.name = H, this.order = Z;
|
|
218
163
|
}
|
|
219
164
|
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
165
|
+
* Intercepts fetch exchanges to detect and handle forbidden (403) responses.
|
|
166
|
+
*
|
|
167
|
+
* This method examines the response status code and invokes the configured `onForbidden`
|
|
168
|
+
* callback when a 403 Forbidden response is detected. The method is asynchronous to
|
|
169
|
+
* allow the callback to perform async operations like API calls, redirects, or UI updates.
|
|
170
|
+
*
|
|
171
|
+
* The interceptor only acts on responses with status code 403. Other error codes are
|
|
172
|
+
* ignored and passed through to other error interceptors in the chain.
|
|
173
|
+
*
|
|
174
|
+
* @param exchange - The fetch exchange containing request, response, and error information
|
|
175
|
+
* to be inspected for forbidden status codes. The exchange object provides
|
|
176
|
+
* access to the original request, response details, and any error information.
|
|
177
|
+
* @returns Promise that resolves when the forbidden error handling is complete.
|
|
178
|
+
* Returns void - the method does not modify the exchange or return values.
|
|
179
|
+
*
|
|
180
|
+
* @remarks
|
|
181
|
+
* - Only responds to HTTP 403 status codes
|
|
182
|
+
* - Does not retry requests or modify responses
|
|
183
|
+
* - Allows async operations in the callback
|
|
184
|
+
* - Does not throw exceptions - delegates all error handling to the callback
|
|
185
|
+
* - Safe to use with other error interceptors
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* // The intercept method is called automatically by the fetcher
|
|
190
|
+
* // No manual invocation needed - this is for documentation purposes
|
|
191
|
+
* const interceptor = new ForbiddenErrorInterceptor({
|
|
192
|
+
* onForbidden: async (exchange) => {
|
|
193
|
+
* // exchange.response.status === 403
|
|
194
|
+
* // exchange.request contains original request details
|
|
195
|
+
* await handleForbiddenAccess(exchange);
|
|
196
|
+
* }
|
|
197
|
+
* });
|
|
198
|
+
* ```
|
|
223
199
|
*/
|
|
224
|
-
|
|
225
|
-
|
|
200
|
+
async intercept(e) {
|
|
201
|
+
e.response?.status === h.FORBIDDEN && await this.options.onForbidden(e);
|
|
226
202
|
}
|
|
227
203
|
}
|
|
228
|
-
|
|
229
|
-
class u extends S {
|
|
204
|
+
class E extends D {
|
|
230
205
|
constructor(e, t) {
|
|
231
|
-
super("Refresh token failed.", t), this.token = e, this.name = "RefreshTokenError", Object.setPrototypeOf(this,
|
|
206
|
+
super("Refresh token failed.", t), this.token = e, this.name = "RefreshTokenError", Object.setPrototypeOf(this, E.prototype);
|
|
232
207
|
}
|
|
233
208
|
}
|
|
234
|
-
class
|
|
209
|
+
class Q {
|
|
235
210
|
/**
|
|
236
211
|
* Creates a new JwtTokenManager instance
|
|
237
212
|
* @param tokenStorage The storage used to persist tokens
|
|
@@ -259,7 +234,7 @@ class ee {
|
|
|
259
234
|
return this.refreshInProgress ? this.refreshInProgress : (this.refreshInProgress = this.tokenRefresher.refresh(e.token).then((t) => {
|
|
260
235
|
this.tokenStorage.setCompositeToken(t);
|
|
261
236
|
}).catch((t) => {
|
|
262
|
-
throw this.tokenStorage.remove(), new
|
|
237
|
+
throw this.tokenStorage.remove(), new E(e, t);
|
|
263
238
|
}).finally(() => {
|
|
264
239
|
this.refreshInProgress = void 0;
|
|
265
240
|
}), this.refreshInProgress);
|
|
@@ -279,18 +254,18 @@ class ee {
|
|
|
279
254
|
return this.currentToken ? this.currentToken.isRefreshable : !1;
|
|
280
255
|
}
|
|
281
256
|
}
|
|
282
|
-
const
|
|
283
|
-
class
|
|
257
|
+
const x = "tenantId", Y = "ownerId", L = "ResourceAttributionRequestInterceptor", j = Number.MAX_SAFE_INTEGER;
|
|
258
|
+
class G {
|
|
284
259
|
/**
|
|
285
260
|
* Creates a new ResourceAttributionRequestInterceptor
|
|
286
261
|
* @param options - Configuration options for resource attribution including tenantId, ownerId and tokenStorage
|
|
287
262
|
*/
|
|
288
263
|
constructor({
|
|
289
|
-
tenantId: e =
|
|
290
|
-
ownerId: t =
|
|
291
|
-
tokenStorage:
|
|
264
|
+
tenantId: e = x,
|
|
265
|
+
ownerId: t = Y,
|
|
266
|
+
tokenStorage: s
|
|
292
267
|
}) {
|
|
293
|
-
this.name =
|
|
268
|
+
this.name = L, this.order = j, this.tenantIdPathKey = e, this.ownerIdPathKey = t, this.tokenStorage = s;
|
|
294
269
|
}
|
|
295
270
|
/**
|
|
296
271
|
* Intercepts outgoing requests and automatically adds tenant and owner ID path parameters
|
|
@@ -301,69 +276,127 @@ class te {
|
|
|
301
276
|
const t = this.tokenStorage.get();
|
|
302
277
|
if (!t)
|
|
303
278
|
return;
|
|
304
|
-
const
|
|
305
|
-
if (!
|
|
279
|
+
const s = t.access.payload;
|
|
280
|
+
if (!s || !s.tenantId && !s.sub)
|
|
306
281
|
return;
|
|
307
282
|
const o = e.fetcher.urlBuilder.urlTemplateResolver.extractPathParams(
|
|
308
283
|
e.request.url
|
|
309
|
-
), c = this.tenantIdPathKey, i = e.ensureRequestUrlParams().path,
|
|
310
|
-
|
|
311
|
-
const R = this.ownerIdPathKey,
|
|
312
|
-
|
|
284
|
+
), c = this.tenantIdPathKey, i = e.ensureRequestUrlParams().path, d = s.tenantId;
|
|
285
|
+
d && o.includes(c) && !i[c] && (i[c] = d);
|
|
286
|
+
const R = this.ownerIdPathKey, I = s.sub;
|
|
287
|
+
I && o.includes(R) && !i[R] && (i[R] = I);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function A(r) {
|
|
291
|
+
try {
|
|
292
|
+
if (typeof r != "string")
|
|
293
|
+
return null;
|
|
294
|
+
const e = r.split(".");
|
|
295
|
+
if (e.length !== 3)
|
|
296
|
+
return null;
|
|
297
|
+
const s = e[1].replace(/-/g, "+").replace(/_/g, "/"), o = s.padEnd(
|
|
298
|
+
s.length + (4 - s.length % 4) % 4,
|
|
299
|
+
"="
|
|
300
|
+
), c = decodeURIComponent(
|
|
301
|
+
atob(o).split("").map(function(i) {
|
|
302
|
+
return "%" + ("00" + i.charCodeAt(0).toString(16)).slice(-2);
|
|
303
|
+
}).join("")
|
|
304
|
+
);
|
|
305
|
+
return JSON.parse(c);
|
|
306
|
+
} catch (e) {
|
|
307
|
+
return console.error("Failed to parse JWT token", e), null;
|
|
313
308
|
}
|
|
314
309
|
}
|
|
315
|
-
|
|
310
|
+
function V(r, e = 0) {
|
|
311
|
+
const t = typeof r == "string" ? A(r) : r;
|
|
312
|
+
if (!t)
|
|
313
|
+
return !0;
|
|
314
|
+
const s = t.exp;
|
|
315
|
+
return s ? Date.now() / 1e3 > s - e : !1;
|
|
316
|
+
}
|
|
317
|
+
class p {
|
|
316
318
|
/**
|
|
317
|
-
* Creates a new instance
|
|
318
|
-
*
|
|
319
|
-
* @param options The configuration options for the token refresher including fetcher and endpoint
|
|
319
|
+
* Creates a new JwtToken instance
|
|
320
320
|
*/
|
|
321
|
-
constructor(e) {
|
|
322
|
-
this.
|
|
321
|
+
constructor(e, t = 0) {
|
|
322
|
+
this.token = e, this.earlyPeriod = t, this.payload = A(e);
|
|
323
323
|
}
|
|
324
324
|
/**
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* @param token The token to refresh
|
|
328
|
-
* @returns A Promise that resolves to a new CompositeToken
|
|
325
|
+
* Checks if the token is expired
|
|
326
|
+
* @returns true if the token is expired, false otherwise
|
|
329
327
|
*/
|
|
330
|
-
|
|
331
|
-
return this.
|
|
332
|
-
this.options.endpoint,
|
|
333
|
-
{
|
|
334
|
-
body: e
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
resultExtractor: U.Json,
|
|
338
|
-
attributes: /* @__PURE__ */ new Map([[A, !0]])
|
|
339
|
-
}
|
|
340
|
-
);
|
|
328
|
+
get isExpired() {
|
|
329
|
+
return this.payload ? V(this.payload, this.earlyPeriod) : !0;
|
|
341
330
|
}
|
|
342
331
|
}
|
|
343
|
-
|
|
344
|
-
|
|
332
|
+
class P {
|
|
333
|
+
/**
|
|
334
|
+
* Creates a new JwtCompositeToken instance
|
|
335
|
+
*/
|
|
336
|
+
constructor(e, t = 0) {
|
|
337
|
+
this.token = e, this.earlyPeriod = t, this.access = new p(e.accessToken, t), this.refresh = new p(e.refreshToken, t);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Checks if the access token needs to be refreshed
|
|
341
|
+
* @returns true if the access token is expired, false otherwise
|
|
342
|
+
*/
|
|
343
|
+
get isRefreshNeeded() {
|
|
344
|
+
return this.access.isExpired;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Checks if the refresh token is still valid and can be used to refresh the access token
|
|
348
|
+
* @returns true if the refresh token is not expired, false otherwise
|
|
349
|
+
*/
|
|
350
|
+
get isRefreshable() {
|
|
351
|
+
return !this.refresh.isExpired;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
class S {
|
|
355
|
+
constructor(e = 0) {
|
|
356
|
+
this.earlyPeriod = e;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Deserializes a JSON string to a JwtCompositeToken
|
|
360
|
+
* @param value The JSON string representation of a composite token
|
|
361
|
+
* @returns A JwtCompositeToken instance
|
|
362
|
+
*/
|
|
363
|
+
deserialize(e) {
|
|
364
|
+
const t = JSON.parse(e);
|
|
365
|
+
return new P(t, this.earlyPeriod);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Serializes a JwtCompositeToken to a JSON string
|
|
369
|
+
* @param value The JwtCompositeToken to serialize
|
|
370
|
+
* @returns A JSON string representation of the composite token
|
|
371
|
+
*/
|
|
372
|
+
serialize(e) {
|
|
373
|
+
return JSON.stringify(e.token);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const ie = new S(), l = "cosec-token";
|
|
377
|
+
class W extends f {
|
|
345
378
|
constructor(e = {
|
|
346
379
|
key: l,
|
|
347
380
|
eventBus: new O({ delegate: new _(l) })
|
|
348
381
|
}) {
|
|
349
382
|
super({
|
|
350
|
-
serializer: new
|
|
383
|
+
serializer: new S(e.earlyPeriod),
|
|
351
384
|
...e
|
|
352
385
|
}), this.earlyPeriod = e.earlyPeriod ?? 0;
|
|
353
386
|
}
|
|
354
387
|
setCompositeToken(e) {
|
|
355
|
-
this.set(new
|
|
388
|
+
this.set(new P(e, this.earlyPeriod));
|
|
356
389
|
}
|
|
357
390
|
}
|
|
358
|
-
const
|
|
359
|
-
class
|
|
391
|
+
const X = "UnauthorizedErrorInterceptor", $ = 0;
|
|
392
|
+
class ee {
|
|
360
393
|
/**
|
|
361
394
|
* Creates a new UnauthorizedErrorInterceptor instance.
|
|
362
395
|
*
|
|
363
396
|
* @param options - Configuration options containing the callback to handle unauthorized responses
|
|
364
397
|
*/
|
|
365
398
|
constructor(e) {
|
|
366
|
-
this.options = e, this.name =
|
|
399
|
+
this.options = e, this.name = X, this.order = $;
|
|
367
400
|
}
|
|
368
401
|
/**
|
|
369
402
|
* Intercepts fetch exchanges to detect and handle unauthorized (401) responses
|
|
@@ -389,108 +422,129 @@ class oe {
|
|
|
389
422
|
* ```
|
|
390
423
|
*/
|
|
391
424
|
async intercept(e) {
|
|
392
|
-
(e.response?.status === h.UNAUTHORIZED || e.error instanceof
|
|
425
|
+
(e.response?.status === h.UNAUTHORIZED || e.error instanceof E) && await this.options.onUnauthorized(e);
|
|
393
426
|
}
|
|
394
427
|
}
|
|
395
|
-
|
|
396
|
-
class ne {
|
|
428
|
+
class ae {
|
|
397
429
|
/**
|
|
398
|
-
* Creates a new
|
|
399
|
-
*
|
|
400
|
-
* @param options - Configuration options containing the callback to handle forbidden responses.
|
|
401
|
-
* Must include the `onForbidden` callback function.
|
|
430
|
+
* Creates a new CoSecConfigurer instance with the provided configuration.
|
|
402
431
|
*
|
|
403
|
-
* @
|
|
404
|
-
*
|
|
405
|
-
* @example
|
|
406
|
-
* ```typescript
|
|
407
|
-
* const interceptor = new ForbiddenErrorInterceptor({
|
|
408
|
-
* onForbidden: async (exchange) => {
|
|
409
|
-
* // Handle forbidden access
|
|
410
|
-
* }
|
|
411
|
-
* });
|
|
412
|
-
* ```
|
|
432
|
+
* @param config - Simplified CoSec configuration
|
|
413
433
|
*/
|
|
414
434
|
constructor(e) {
|
|
415
|
-
this.
|
|
435
|
+
this.config = e, this.tokenStorage = new W(), this.deviceIdStorage = new K(), this.tokenManager = new Q(
|
|
436
|
+
this.tokenStorage,
|
|
437
|
+
this.config.tokenRefresher
|
|
438
|
+
);
|
|
416
439
|
}
|
|
417
440
|
/**
|
|
418
|
-
*
|
|
441
|
+
* Applies all CoSec interceptors to the provided Fetcher instance.
|
|
419
442
|
*
|
|
420
|
-
* This method
|
|
421
|
-
*
|
|
422
|
-
*
|
|
443
|
+
* This method configures the following interceptors in the correct order:
|
|
444
|
+
* 1. CoSecRequestInterceptor - Adds CoSec headers (appId, deviceId, requestId)
|
|
445
|
+
* 2. AuthorizationRequestInterceptor - Adds Authorization header with Bearer token
|
|
446
|
+
* 3. ResourceAttributionRequestInterceptor - Adds tenant/owner path parameters
|
|
447
|
+
* 4. AuthorizationResponseInterceptor - Handles 401 responses with token refresh
|
|
448
|
+
* 5. UnauthorizedErrorInterceptor - Handles unauthorized errors
|
|
449
|
+
* 6. ForbiddenErrorInterceptor - Handles forbidden errors
|
|
423
450
|
*
|
|
424
|
-
*
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
451
|
+
* @param fetcher - The Fetcher instance to configure
|
|
452
|
+
*/
|
|
453
|
+
applyTo(e) {
|
|
454
|
+
e.interceptors.request.use(
|
|
455
|
+
new b({
|
|
456
|
+
appId: this.config.appId,
|
|
457
|
+
deviceIdStorage: this.deviceIdStorage
|
|
458
|
+
})
|
|
459
|
+
), e.interceptors.request.use(
|
|
460
|
+
new q({
|
|
461
|
+
tokenManager: this.tokenManager
|
|
462
|
+
})
|
|
463
|
+
), e.interceptors.request.use(
|
|
464
|
+
new G({
|
|
465
|
+
tokenStorage: this.tokenStorage
|
|
466
|
+
})
|
|
467
|
+
), e.interceptors.response.use(
|
|
468
|
+
new B({
|
|
469
|
+
tokenManager: this.tokenManager
|
|
470
|
+
})
|
|
471
|
+
), this.config.onUnauthorized && e.interceptors.error.use(
|
|
472
|
+
new ee({
|
|
473
|
+
onUnauthorized: this.config.onUnauthorized
|
|
474
|
+
})
|
|
475
|
+
), this.config.onForbidden && e.interceptors.error.use(
|
|
476
|
+
new J({
|
|
477
|
+
onForbidden: this.config.onForbidden
|
|
478
|
+
})
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
class ce {
|
|
483
|
+
/**
|
|
484
|
+
* Creates a new instance of CoSecTokenRefresher.
|
|
432
485
|
*
|
|
433
|
-
* @
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
486
|
+
* @param options The configuration options for the token refresher including fetcher and endpoint
|
|
487
|
+
*/
|
|
488
|
+
constructor(e) {
|
|
489
|
+
this.options = e;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Refresh the given token and return a new CompositeToken.
|
|
439
493
|
*
|
|
440
|
-
* @
|
|
441
|
-
*
|
|
442
|
-
* // The intercept method is called automatically by the fetcher
|
|
443
|
-
* // No manual invocation needed - this is for documentation purposes
|
|
444
|
-
* const interceptor = new ForbiddenErrorInterceptor({
|
|
445
|
-
* onForbidden: async (exchange) => {
|
|
446
|
-
* // exchange.response.status === 403
|
|
447
|
-
* // exchange.request contains original request details
|
|
448
|
-
* await handleForbiddenAccess(exchange);
|
|
449
|
-
* }
|
|
450
|
-
* });
|
|
451
|
-
* ```
|
|
494
|
+
* @param token The token to refresh
|
|
495
|
+
* @returns A Promise that resolves to a new CompositeToken
|
|
452
496
|
*/
|
|
453
|
-
|
|
454
|
-
|
|
497
|
+
refresh(e) {
|
|
498
|
+
return this.options.fetcher.post(
|
|
499
|
+
this.options.endpoint,
|
|
500
|
+
{
|
|
501
|
+
body: e
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
resultExtractor: y.Json,
|
|
505
|
+
attributes: /* @__PURE__ */ new Map([[k, !0]])
|
|
506
|
+
}
|
|
507
|
+
);
|
|
455
508
|
}
|
|
456
509
|
}
|
|
457
510
|
export {
|
|
458
|
-
|
|
511
|
+
M as AUTHORIZATION_REQUEST_INTERCEPTOR_NAME,
|
|
459
512
|
z as AUTHORIZATION_REQUEST_INTERCEPTOR_ORDER,
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
513
|
+
v as AUTHORIZATION_RESPONSE_INTERCEPTOR_NAME,
|
|
514
|
+
F as AUTHORIZATION_RESPONSE_INTERCEPTOR_ORDER,
|
|
515
|
+
q as AuthorizationRequestInterceptor,
|
|
516
|
+
B as AuthorizationResponseInterceptor,
|
|
517
|
+
ne as AuthorizeResults,
|
|
465
518
|
m as COSEC_REQUEST_INTERCEPTOR_NAME,
|
|
466
|
-
|
|
519
|
+
N as COSEC_REQUEST_INTERCEPTOR_ORDER,
|
|
520
|
+
ae as CoSecConfigurer,
|
|
467
521
|
n as CoSecHeaders,
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
522
|
+
b as CoSecRequestInterceptor,
|
|
523
|
+
ce as CoSecTokenRefresher,
|
|
524
|
+
T as DEFAULT_COSEC_DEVICE_ID_KEY,
|
|
471
525
|
l as DEFAULT_COSEC_TOKEN_KEY,
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
526
|
+
K as DeviceIdStorage,
|
|
527
|
+
H as FORBIDDEN_ERROR_INTERCEPTOR_NAME,
|
|
528
|
+
Z as FORBIDDEN_ERROR_INTERCEPTOR_ORDER,
|
|
529
|
+
J as ForbiddenErrorInterceptor,
|
|
530
|
+
k as IGNORE_REFRESH_TOKEN_ATTRIBUTE_KEY,
|
|
531
|
+
P as JwtCompositeToken,
|
|
532
|
+
S as JwtCompositeTokenSerializer,
|
|
479
533
|
p as JwtToken,
|
|
480
|
-
|
|
534
|
+
Q as JwtTokenManager,
|
|
481
535
|
C as NanoIdGenerator,
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
536
|
+
L as RESOURCE_ATTRIBUTION_REQUEST_INTERCEPTOR_NAME,
|
|
537
|
+
j as RESOURCE_ATTRIBUTION_REQUEST_INTERCEPTOR_ORDER,
|
|
538
|
+
E as RefreshTokenError,
|
|
539
|
+
G as ResourceAttributionRequestInterceptor,
|
|
486
540
|
h as ResponseCodes,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
541
|
+
W as TokenStorage,
|
|
542
|
+
X as UNAUTHORIZED_ERROR_INTERCEPTOR_NAME,
|
|
543
|
+
$ as UNAUTHORIZED_ERROR_INTERCEPTOR_ORDER,
|
|
544
|
+
ee as UnauthorizedErrorInterceptor,
|
|
545
|
+
g as idGenerator,
|
|
546
|
+
V as isTokenExpired,
|
|
547
|
+
ie as jwtCompositeTokenSerializer,
|
|
548
|
+
A as parseJwtPayload
|
|
495
549
|
};
|
|
496
550
|
//# sourceMappingURL=index.es.js.map
|