@zskj-idaas/sdk 1.0.0 → 1.0.3
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.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +171 -7
- package/dist/index.mjs +171 -7
- package/package.json +4 -3
package/dist/index.d.mts
CHANGED
|
@@ -18,6 +18,11 @@ interface TokenSet {
|
|
|
18
18
|
refresh_token?: string;
|
|
19
19
|
scope: string;
|
|
20
20
|
}
|
|
21
|
+
interface ServiceTokenState {
|
|
22
|
+
accessToken: string;
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
scope: string;
|
|
25
|
+
}
|
|
21
26
|
interface UserInfo {
|
|
22
27
|
sub: string;
|
|
23
28
|
preferred_username?: string;
|
|
@@ -35,6 +40,10 @@ interface AuthState {
|
|
|
35
40
|
idToken: string | null;
|
|
36
41
|
expiresAt: number | null;
|
|
37
42
|
}
|
|
43
|
+
interface SessionLogoutOptions {
|
|
44
|
+
/** Redirect after the server-side session and local tokens are cleared. */
|
|
45
|
+
redirectTo?: string;
|
|
46
|
+
}
|
|
38
47
|
interface PKCEPair {
|
|
39
48
|
codeVerifier: string;
|
|
40
49
|
codeChallenge: string;
|
|
@@ -45,6 +54,7 @@ declare class IdaasClient {
|
|
|
45
54
|
private endpoints;
|
|
46
55
|
private storage;
|
|
47
56
|
private userInfo;
|
|
57
|
+
private serviceTokens;
|
|
48
58
|
constructor(config: IdaasConfig);
|
|
49
59
|
init(): Promise<AuthState>;
|
|
50
60
|
private discover;
|
|
@@ -53,13 +63,16 @@ declare class IdaasClient {
|
|
|
53
63
|
refreshToken(): Promise<TokenSet | null>;
|
|
54
64
|
getUserInfo(forceRefresh?: boolean): Promise<UserInfo | null>;
|
|
55
65
|
getAccessToken(): Promise<string | null>;
|
|
66
|
+
getServiceToken(serviceKey: string): Promise<string | null>;
|
|
56
67
|
getIdToken(): string | null;
|
|
57
68
|
getAuthState(): AuthState;
|
|
58
69
|
isAuthenticated(): boolean;
|
|
59
70
|
logout(): Promise<void>;
|
|
71
|
+
logoutSession(options?: SessionLogoutOptions): Promise<void>;
|
|
60
72
|
revokeToken(): Promise<void>;
|
|
61
73
|
/** Create an authenticated fetch wrapper */
|
|
62
74
|
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
75
|
+
fetchService(serviceKey: string, url: string, init?: RequestInit): Promise<Response>;
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
declare function createPKCE(): Promise<PKCEPair>;
|
|
@@ -86,4 +99,4 @@ declare class TokenStorage {
|
|
|
86
99
|
clearAuthState(): void;
|
|
87
100
|
}
|
|
88
101
|
|
|
89
|
-
export { type AuthState, IdaasClient, type IdaasConfig, type TokenSet, TokenStorage, type UserInfo, createPKCE, generateNonce, generateState };
|
|
102
|
+
export { type AuthState, IdaasClient, type IdaasConfig, type ServiceTokenState, type SessionLogoutOptions, type TokenSet, TokenStorage, type UserInfo, createPKCE, generateNonce, generateState };
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ interface TokenSet {
|
|
|
18
18
|
refresh_token?: string;
|
|
19
19
|
scope: string;
|
|
20
20
|
}
|
|
21
|
+
interface ServiceTokenState {
|
|
22
|
+
accessToken: string;
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
scope: string;
|
|
25
|
+
}
|
|
21
26
|
interface UserInfo {
|
|
22
27
|
sub: string;
|
|
23
28
|
preferred_username?: string;
|
|
@@ -35,6 +40,10 @@ interface AuthState {
|
|
|
35
40
|
idToken: string | null;
|
|
36
41
|
expiresAt: number | null;
|
|
37
42
|
}
|
|
43
|
+
interface SessionLogoutOptions {
|
|
44
|
+
/** Redirect after the server-side session and local tokens are cleared. */
|
|
45
|
+
redirectTo?: string;
|
|
46
|
+
}
|
|
38
47
|
interface PKCEPair {
|
|
39
48
|
codeVerifier: string;
|
|
40
49
|
codeChallenge: string;
|
|
@@ -45,6 +54,7 @@ declare class IdaasClient {
|
|
|
45
54
|
private endpoints;
|
|
46
55
|
private storage;
|
|
47
56
|
private userInfo;
|
|
57
|
+
private serviceTokens;
|
|
48
58
|
constructor(config: IdaasConfig);
|
|
49
59
|
init(): Promise<AuthState>;
|
|
50
60
|
private discover;
|
|
@@ -53,13 +63,16 @@ declare class IdaasClient {
|
|
|
53
63
|
refreshToken(): Promise<TokenSet | null>;
|
|
54
64
|
getUserInfo(forceRefresh?: boolean): Promise<UserInfo | null>;
|
|
55
65
|
getAccessToken(): Promise<string | null>;
|
|
66
|
+
getServiceToken(serviceKey: string): Promise<string | null>;
|
|
56
67
|
getIdToken(): string | null;
|
|
57
68
|
getAuthState(): AuthState;
|
|
58
69
|
isAuthenticated(): boolean;
|
|
59
70
|
logout(): Promise<void>;
|
|
71
|
+
logoutSession(options?: SessionLogoutOptions): Promise<void>;
|
|
60
72
|
revokeToken(): Promise<void>;
|
|
61
73
|
/** Create an authenticated fetch wrapper */
|
|
62
74
|
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
75
|
+
fetchService(serviceKey: string, url: string, init?: RequestInit): Promise<Response>;
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
declare function createPKCE(): Promise<PKCEPair>;
|
|
@@ -86,4 +99,4 @@ declare class TokenStorage {
|
|
|
86
99
|
clearAuthState(): void;
|
|
87
100
|
}
|
|
88
101
|
|
|
89
|
-
export { type AuthState, IdaasClient, type IdaasConfig, type TokenSet, TokenStorage, type UserInfo, createPKCE, generateNonce, generateState };
|
|
102
|
+
export { type AuthState, IdaasClient, type IdaasConfig, type ServiceTokenState, type SessionLogoutOptions, type TokenSet, TokenStorage, type UserInfo, createPKCE, generateNonce, generateState };
|
package/dist/index.js
CHANGED
|
@@ -42,11 +42,129 @@ function base64UrlEncode(buffer) {
|
|
|
42
42
|
});
|
|
43
43
|
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
44
44
|
}
|
|
45
|
+
async function sha256(data) {
|
|
46
|
+
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
47
|
+
return crypto.subtle.digest("SHA-256", data);
|
|
48
|
+
}
|
|
49
|
+
const K = [
|
|
50
|
+
1116352408,
|
|
51
|
+
1899447441,
|
|
52
|
+
3049323471,
|
|
53
|
+
3921009573,
|
|
54
|
+
961987163,
|
|
55
|
+
1508970993,
|
|
56
|
+
2453635748,
|
|
57
|
+
2870763221,
|
|
58
|
+
3624381080,
|
|
59
|
+
310598401,
|
|
60
|
+
607225278,
|
|
61
|
+
1426881987,
|
|
62
|
+
1925078388,
|
|
63
|
+
2162078206,
|
|
64
|
+
2614888103,
|
|
65
|
+
3248222580,
|
|
66
|
+
3835390401,
|
|
67
|
+
4022224774,
|
|
68
|
+
264347078,
|
|
69
|
+
604807628,
|
|
70
|
+
770255983,
|
|
71
|
+
1249150122,
|
|
72
|
+
1555081692,
|
|
73
|
+
1996064986,
|
|
74
|
+
2554220882,
|
|
75
|
+
2821834349,
|
|
76
|
+
2952996808,
|
|
77
|
+
3210313671,
|
|
78
|
+
3336571891,
|
|
79
|
+
3584528711,
|
|
80
|
+
113926993,
|
|
81
|
+
338241895,
|
|
82
|
+
666307205,
|
|
83
|
+
773529912,
|
|
84
|
+
1294757372,
|
|
85
|
+
1396182291,
|
|
86
|
+
1695183700,
|
|
87
|
+
1986661051,
|
|
88
|
+
2177026350,
|
|
89
|
+
2456956037,
|
|
90
|
+
2730485921,
|
|
91
|
+
2820302411,
|
|
92
|
+
3259730800,
|
|
93
|
+
3345764771,
|
|
94
|
+
3516065817,
|
|
95
|
+
3600352804,
|
|
96
|
+
4094571909,
|
|
97
|
+
275423344,
|
|
98
|
+
430227734,
|
|
99
|
+
506948616,
|
|
100
|
+
659060556,
|
|
101
|
+
883997877,
|
|
102
|
+
958139571,
|
|
103
|
+
1322822218,
|
|
104
|
+
1537002063,
|
|
105
|
+
1747873779,
|
|
106
|
+
1955562222,
|
|
107
|
+
2024104815,
|
|
108
|
+
2227730452,
|
|
109
|
+
2361852424,
|
|
110
|
+
2428436474,
|
|
111
|
+
2756734187,
|
|
112
|
+
3204031479,
|
|
113
|
+
3329325298
|
|
114
|
+
];
|
|
115
|
+
const rotr = (n, x) => x >>> n | x << 32 - n;
|
|
116
|
+
const ch = (x, y, z) => x & y ^ ~x & z;
|
|
117
|
+
const maj = (x, y, z) => x & y ^ x & z ^ y & z;
|
|
118
|
+
const sigma0 = (x) => rotr(2, x) ^ rotr(13, x) ^ rotr(22, x);
|
|
119
|
+
const sigma1 = (x) => rotr(6, x) ^ rotr(11, x) ^ rotr(25, x);
|
|
120
|
+
const gamma0 = (x) => rotr(7, x) ^ rotr(18, x) ^ x >>> 3;
|
|
121
|
+
const gamma1 = (x) => rotr(17, x) ^ rotr(19, x) ^ x >>> 10;
|
|
122
|
+
const len = data.length;
|
|
123
|
+
const bitLen = len * 8;
|
|
124
|
+
const padLen = (len + 8 >> 6 << 6) + 64;
|
|
125
|
+
const padded = new Uint8Array(padLen);
|
|
126
|
+
padded.set(data);
|
|
127
|
+
padded[len] = 128;
|
|
128
|
+
const view = new DataView(padded.buffer);
|
|
129
|
+
view.setUint32(padLen - 4, bitLen, false);
|
|
130
|
+
let h0 = 1779033703, h1 = 3144134277, h2 = 1013904242, h3 = 2773480762;
|
|
131
|
+
let h4 = 1359893119, h5 = 2600822924, h6 = 528734635, h7 = 1541459225;
|
|
132
|
+
for (let offset = 0; offset < padLen; offset += 64) {
|
|
133
|
+
const w = new Array(64);
|
|
134
|
+
for (let i = 0; i < 16; i++) w[i] = view.getUint32(offset + i * 4, false);
|
|
135
|
+
for (let i = 16; i < 64; i++) w[i] = gamma1(w[i - 2]) + w[i - 7] + gamma0(w[i - 15]) + w[i - 16] | 0;
|
|
136
|
+
let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
|
|
137
|
+
for (let i = 0; i < 64; i++) {
|
|
138
|
+
const t1 = h + sigma1(e) + ch(e, f, g) + K[i] + w[i] | 0;
|
|
139
|
+
const t2 = sigma0(a) + maj(a, b, c) | 0;
|
|
140
|
+
h = g;
|
|
141
|
+
g = f;
|
|
142
|
+
f = e;
|
|
143
|
+
e = d + t1 | 0;
|
|
144
|
+
d = c;
|
|
145
|
+
c = b;
|
|
146
|
+
b = a;
|
|
147
|
+
a = t1 + t2 | 0;
|
|
148
|
+
}
|
|
149
|
+
h0 = h0 + a | 0;
|
|
150
|
+
h1 = h1 + b | 0;
|
|
151
|
+
h2 = h2 + c | 0;
|
|
152
|
+
h3 = h3 + d | 0;
|
|
153
|
+
h4 = h4 + e | 0;
|
|
154
|
+
h5 = h5 + f | 0;
|
|
155
|
+
h6 = h6 + g | 0;
|
|
156
|
+
h7 = h7 + h | 0;
|
|
157
|
+
}
|
|
158
|
+
const result = new ArrayBuffer(32);
|
|
159
|
+
const dv = new DataView(result);
|
|
160
|
+
[h0, h1, h2, h3, h4, h5, h6, h7].forEach((v, i) => dv.setUint32(i * 4, v, false));
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
45
163
|
async function createPKCE() {
|
|
46
164
|
const codeVerifier = generateRandomString(64);
|
|
47
165
|
const encoder = new TextEncoder();
|
|
48
166
|
const data = encoder.encode(codeVerifier);
|
|
49
|
-
const digest = await
|
|
167
|
+
const digest = await sha256(data);
|
|
50
168
|
const codeChallenge = base64UrlEncode(digest);
|
|
51
169
|
return { codeVerifier, codeChallenge };
|
|
52
170
|
}
|
|
@@ -136,6 +254,7 @@ var IdaasClient = class {
|
|
|
136
254
|
constructor(config) {
|
|
137
255
|
this.endpoints = null;
|
|
138
256
|
this.userInfo = null;
|
|
257
|
+
this.serviceTokens = /* @__PURE__ */ new Map();
|
|
139
258
|
this.config = {
|
|
140
259
|
scope: "openid profile email",
|
|
141
260
|
autoDiscovery: true,
|
|
@@ -158,6 +277,7 @@ var IdaasClient = class {
|
|
|
158
277
|
introspection_endpoint: `${this.config.issuer}/oauth2/introspect`
|
|
159
278
|
};
|
|
160
279
|
}
|
|
280
|
+
await this.getAccessToken();
|
|
161
281
|
return this.getAuthState();
|
|
162
282
|
}
|
|
163
283
|
async discover() {
|
|
@@ -274,14 +394,40 @@ var IdaasClient = class {
|
|
|
274
394
|
return this.userInfo;
|
|
275
395
|
}
|
|
276
396
|
async getAccessToken() {
|
|
277
|
-
|
|
278
|
-
if (token) return token;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (tokens) return tokens.access_token;
|
|
282
|
-
}
|
|
397
|
+
const token = this.storage.getAccessToken();
|
|
398
|
+
if (token && !this.storage.isTokenExpired()) return token;
|
|
399
|
+
const tokens = await this.refreshToken();
|
|
400
|
+
if (tokens) return tokens.access_token;
|
|
283
401
|
return null;
|
|
284
402
|
}
|
|
403
|
+
async getServiceToken(serviceKey) {
|
|
404
|
+
if (!this.endpoints) await this.init();
|
|
405
|
+
const cached = this.serviceTokens.get(serviceKey);
|
|
406
|
+
if (cached && Date.now() < cached.expiresAt - 6e4) {
|
|
407
|
+
return cached.accessToken;
|
|
408
|
+
}
|
|
409
|
+
const baseToken = await this.getAccessToken();
|
|
410
|
+
if (!baseToken) return null;
|
|
411
|
+
const res = await fetch(`${this.config.issuer}/oauth2/business-token`, {
|
|
412
|
+
method: "POST",
|
|
413
|
+
headers: {
|
|
414
|
+
"Content-Type": "application/json",
|
|
415
|
+
Authorization: `Bearer ${baseToken}`
|
|
416
|
+
},
|
|
417
|
+
body: JSON.stringify({ service_key: serviceKey })
|
|
418
|
+
});
|
|
419
|
+
if (!res.ok) {
|
|
420
|
+
this.serviceTokens.delete(serviceKey);
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
const tokenSet = await res.json();
|
|
424
|
+
this.serviceTokens.set(serviceKey, {
|
|
425
|
+
accessToken: tokenSet.access_token,
|
|
426
|
+
expiresAt: Date.now() + tokenSet.expires_in * 1e3,
|
|
427
|
+
scope: tokenSet.scope
|
|
428
|
+
});
|
|
429
|
+
return tokenSet.access_token;
|
|
430
|
+
}
|
|
285
431
|
getIdToken() {
|
|
286
432
|
return this.storage.getIdToken();
|
|
287
433
|
}
|
|
@@ -310,6 +456,17 @@ var IdaasClient = class {
|
|
|
310
456
|
}
|
|
311
457
|
window.location.href = `${this.endpoints.end_session_endpoint}?${params.toString()}`;
|
|
312
458
|
}
|
|
459
|
+
async logoutSession(options = {}) {
|
|
460
|
+
this.storage.clear();
|
|
461
|
+
this.userInfo = null;
|
|
462
|
+
await fetch(`${this.config.issuer}/auth/logout`, {
|
|
463
|
+
method: "POST",
|
|
464
|
+
credentials: "include"
|
|
465
|
+
}).catch(() => void 0);
|
|
466
|
+
if (options.redirectTo) {
|
|
467
|
+
window.location.href = options.redirectTo;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
313
470
|
async revokeToken() {
|
|
314
471
|
if (!this.endpoints) await this.init();
|
|
315
472
|
const refreshToken = this.storage.getRefreshToken();
|
|
@@ -333,6 +490,13 @@ var IdaasClient = class {
|
|
|
333
490
|
}
|
|
334
491
|
return fetch(url, { ...init, headers });
|
|
335
492
|
}
|
|
493
|
+
async fetchService(serviceKey, url, init) {
|
|
494
|
+
const token = await this.getServiceToken(serviceKey);
|
|
495
|
+
if (!token) throw new Error(`No service token available for ${serviceKey}`);
|
|
496
|
+
const headers = new Headers(init?.headers);
|
|
497
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
498
|
+
return fetch(url, { ...init, headers });
|
|
499
|
+
}
|
|
336
500
|
};
|
|
337
501
|
// Annotate the CommonJS export names for ESM import in node:
|
|
338
502
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -12,11 +12,129 @@ function base64UrlEncode(buffer) {
|
|
|
12
12
|
});
|
|
13
13
|
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
14
14
|
}
|
|
15
|
+
async function sha256(data) {
|
|
16
|
+
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
17
|
+
return crypto.subtle.digest("SHA-256", data);
|
|
18
|
+
}
|
|
19
|
+
const K = [
|
|
20
|
+
1116352408,
|
|
21
|
+
1899447441,
|
|
22
|
+
3049323471,
|
|
23
|
+
3921009573,
|
|
24
|
+
961987163,
|
|
25
|
+
1508970993,
|
|
26
|
+
2453635748,
|
|
27
|
+
2870763221,
|
|
28
|
+
3624381080,
|
|
29
|
+
310598401,
|
|
30
|
+
607225278,
|
|
31
|
+
1426881987,
|
|
32
|
+
1925078388,
|
|
33
|
+
2162078206,
|
|
34
|
+
2614888103,
|
|
35
|
+
3248222580,
|
|
36
|
+
3835390401,
|
|
37
|
+
4022224774,
|
|
38
|
+
264347078,
|
|
39
|
+
604807628,
|
|
40
|
+
770255983,
|
|
41
|
+
1249150122,
|
|
42
|
+
1555081692,
|
|
43
|
+
1996064986,
|
|
44
|
+
2554220882,
|
|
45
|
+
2821834349,
|
|
46
|
+
2952996808,
|
|
47
|
+
3210313671,
|
|
48
|
+
3336571891,
|
|
49
|
+
3584528711,
|
|
50
|
+
113926993,
|
|
51
|
+
338241895,
|
|
52
|
+
666307205,
|
|
53
|
+
773529912,
|
|
54
|
+
1294757372,
|
|
55
|
+
1396182291,
|
|
56
|
+
1695183700,
|
|
57
|
+
1986661051,
|
|
58
|
+
2177026350,
|
|
59
|
+
2456956037,
|
|
60
|
+
2730485921,
|
|
61
|
+
2820302411,
|
|
62
|
+
3259730800,
|
|
63
|
+
3345764771,
|
|
64
|
+
3516065817,
|
|
65
|
+
3600352804,
|
|
66
|
+
4094571909,
|
|
67
|
+
275423344,
|
|
68
|
+
430227734,
|
|
69
|
+
506948616,
|
|
70
|
+
659060556,
|
|
71
|
+
883997877,
|
|
72
|
+
958139571,
|
|
73
|
+
1322822218,
|
|
74
|
+
1537002063,
|
|
75
|
+
1747873779,
|
|
76
|
+
1955562222,
|
|
77
|
+
2024104815,
|
|
78
|
+
2227730452,
|
|
79
|
+
2361852424,
|
|
80
|
+
2428436474,
|
|
81
|
+
2756734187,
|
|
82
|
+
3204031479,
|
|
83
|
+
3329325298
|
|
84
|
+
];
|
|
85
|
+
const rotr = (n, x) => x >>> n | x << 32 - n;
|
|
86
|
+
const ch = (x, y, z) => x & y ^ ~x & z;
|
|
87
|
+
const maj = (x, y, z) => x & y ^ x & z ^ y & z;
|
|
88
|
+
const sigma0 = (x) => rotr(2, x) ^ rotr(13, x) ^ rotr(22, x);
|
|
89
|
+
const sigma1 = (x) => rotr(6, x) ^ rotr(11, x) ^ rotr(25, x);
|
|
90
|
+
const gamma0 = (x) => rotr(7, x) ^ rotr(18, x) ^ x >>> 3;
|
|
91
|
+
const gamma1 = (x) => rotr(17, x) ^ rotr(19, x) ^ x >>> 10;
|
|
92
|
+
const len = data.length;
|
|
93
|
+
const bitLen = len * 8;
|
|
94
|
+
const padLen = (len + 8 >> 6 << 6) + 64;
|
|
95
|
+
const padded = new Uint8Array(padLen);
|
|
96
|
+
padded.set(data);
|
|
97
|
+
padded[len] = 128;
|
|
98
|
+
const view = new DataView(padded.buffer);
|
|
99
|
+
view.setUint32(padLen - 4, bitLen, false);
|
|
100
|
+
let h0 = 1779033703, h1 = 3144134277, h2 = 1013904242, h3 = 2773480762;
|
|
101
|
+
let h4 = 1359893119, h5 = 2600822924, h6 = 528734635, h7 = 1541459225;
|
|
102
|
+
for (let offset = 0; offset < padLen; offset += 64) {
|
|
103
|
+
const w = new Array(64);
|
|
104
|
+
for (let i = 0; i < 16; i++) w[i] = view.getUint32(offset + i * 4, false);
|
|
105
|
+
for (let i = 16; i < 64; i++) w[i] = gamma1(w[i - 2]) + w[i - 7] + gamma0(w[i - 15]) + w[i - 16] | 0;
|
|
106
|
+
let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
|
|
107
|
+
for (let i = 0; i < 64; i++) {
|
|
108
|
+
const t1 = h + sigma1(e) + ch(e, f, g) + K[i] + w[i] | 0;
|
|
109
|
+
const t2 = sigma0(a) + maj(a, b, c) | 0;
|
|
110
|
+
h = g;
|
|
111
|
+
g = f;
|
|
112
|
+
f = e;
|
|
113
|
+
e = d + t1 | 0;
|
|
114
|
+
d = c;
|
|
115
|
+
c = b;
|
|
116
|
+
b = a;
|
|
117
|
+
a = t1 + t2 | 0;
|
|
118
|
+
}
|
|
119
|
+
h0 = h0 + a | 0;
|
|
120
|
+
h1 = h1 + b | 0;
|
|
121
|
+
h2 = h2 + c | 0;
|
|
122
|
+
h3 = h3 + d | 0;
|
|
123
|
+
h4 = h4 + e | 0;
|
|
124
|
+
h5 = h5 + f | 0;
|
|
125
|
+
h6 = h6 + g | 0;
|
|
126
|
+
h7 = h7 + h | 0;
|
|
127
|
+
}
|
|
128
|
+
const result = new ArrayBuffer(32);
|
|
129
|
+
const dv = new DataView(result);
|
|
130
|
+
[h0, h1, h2, h3, h4, h5, h6, h7].forEach((v, i) => dv.setUint32(i * 4, v, false));
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
15
133
|
async function createPKCE() {
|
|
16
134
|
const codeVerifier = generateRandomString(64);
|
|
17
135
|
const encoder = new TextEncoder();
|
|
18
136
|
const data = encoder.encode(codeVerifier);
|
|
19
|
-
const digest = await
|
|
137
|
+
const digest = await sha256(data);
|
|
20
138
|
const codeChallenge = base64UrlEncode(digest);
|
|
21
139
|
return { codeVerifier, codeChallenge };
|
|
22
140
|
}
|
|
@@ -106,6 +224,7 @@ var IdaasClient = class {
|
|
|
106
224
|
constructor(config) {
|
|
107
225
|
this.endpoints = null;
|
|
108
226
|
this.userInfo = null;
|
|
227
|
+
this.serviceTokens = /* @__PURE__ */ new Map();
|
|
109
228
|
this.config = {
|
|
110
229
|
scope: "openid profile email",
|
|
111
230
|
autoDiscovery: true,
|
|
@@ -128,6 +247,7 @@ var IdaasClient = class {
|
|
|
128
247
|
introspection_endpoint: `${this.config.issuer}/oauth2/introspect`
|
|
129
248
|
};
|
|
130
249
|
}
|
|
250
|
+
await this.getAccessToken();
|
|
131
251
|
return this.getAuthState();
|
|
132
252
|
}
|
|
133
253
|
async discover() {
|
|
@@ -244,14 +364,40 @@ var IdaasClient = class {
|
|
|
244
364
|
return this.userInfo;
|
|
245
365
|
}
|
|
246
366
|
async getAccessToken() {
|
|
247
|
-
|
|
248
|
-
if (token) return token;
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (tokens) return tokens.access_token;
|
|
252
|
-
}
|
|
367
|
+
const token = this.storage.getAccessToken();
|
|
368
|
+
if (token && !this.storage.isTokenExpired()) return token;
|
|
369
|
+
const tokens = await this.refreshToken();
|
|
370
|
+
if (tokens) return tokens.access_token;
|
|
253
371
|
return null;
|
|
254
372
|
}
|
|
373
|
+
async getServiceToken(serviceKey) {
|
|
374
|
+
if (!this.endpoints) await this.init();
|
|
375
|
+
const cached = this.serviceTokens.get(serviceKey);
|
|
376
|
+
if (cached && Date.now() < cached.expiresAt - 6e4) {
|
|
377
|
+
return cached.accessToken;
|
|
378
|
+
}
|
|
379
|
+
const baseToken = await this.getAccessToken();
|
|
380
|
+
if (!baseToken) return null;
|
|
381
|
+
const res = await fetch(`${this.config.issuer}/oauth2/business-token`, {
|
|
382
|
+
method: "POST",
|
|
383
|
+
headers: {
|
|
384
|
+
"Content-Type": "application/json",
|
|
385
|
+
Authorization: `Bearer ${baseToken}`
|
|
386
|
+
},
|
|
387
|
+
body: JSON.stringify({ service_key: serviceKey })
|
|
388
|
+
});
|
|
389
|
+
if (!res.ok) {
|
|
390
|
+
this.serviceTokens.delete(serviceKey);
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
const tokenSet = await res.json();
|
|
394
|
+
this.serviceTokens.set(serviceKey, {
|
|
395
|
+
accessToken: tokenSet.access_token,
|
|
396
|
+
expiresAt: Date.now() + tokenSet.expires_in * 1e3,
|
|
397
|
+
scope: tokenSet.scope
|
|
398
|
+
});
|
|
399
|
+
return tokenSet.access_token;
|
|
400
|
+
}
|
|
255
401
|
getIdToken() {
|
|
256
402
|
return this.storage.getIdToken();
|
|
257
403
|
}
|
|
@@ -280,6 +426,17 @@ var IdaasClient = class {
|
|
|
280
426
|
}
|
|
281
427
|
window.location.href = `${this.endpoints.end_session_endpoint}?${params.toString()}`;
|
|
282
428
|
}
|
|
429
|
+
async logoutSession(options = {}) {
|
|
430
|
+
this.storage.clear();
|
|
431
|
+
this.userInfo = null;
|
|
432
|
+
await fetch(`${this.config.issuer}/auth/logout`, {
|
|
433
|
+
method: "POST",
|
|
434
|
+
credentials: "include"
|
|
435
|
+
}).catch(() => void 0);
|
|
436
|
+
if (options.redirectTo) {
|
|
437
|
+
window.location.href = options.redirectTo;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
283
440
|
async revokeToken() {
|
|
284
441
|
if (!this.endpoints) await this.init();
|
|
285
442
|
const refreshToken = this.storage.getRefreshToken();
|
|
@@ -303,6 +460,13 @@ var IdaasClient = class {
|
|
|
303
460
|
}
|
|
304
461
|
return fetch(url, { ...init, headers });
|
|
305
462
|
}
|
|
463
|
+
async fetchService(serviceKey, url, init) {
|
|
464
|
+
const token = await this.getServiceToken(serviceKey);
|
|
465
|
+
if (!token) throw new Error(`No service token available for ${serviceKey}`);
|
|
466
|
+
const headers = new Headers(init?.headers);
|
|
467
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
468
|
+
return fetch(url, { ...init, headers });
|
|
469
|
+
}
|
|
306
470
|
};
|
|
307
471
|
export {
|
|
308
472
|
IdaasClient,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zskj-idaas/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "IDaaS OIDC Client SDK for browser applications — supports Authorization Code Flow with PKCE, token management, and authenticated fetch.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
28
28
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
29
|
+
"test": "vitest run",
|
|
29
30
|
"prepublishOnly": "npm run build"
|
|
30
31
|
},
|
|
31
32
|
"keywords": [
|
|
@@ -57,9 +58,9 @@
|
|
|
57
58
|
"not dead",
|
|
58
59
|
"not ie 11"
|
|
59
60
|
],
|
|
60
|
-
"dependencies": {},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"tsup": "^8.2.0",
|
|
63
|
-
"typescript": "^5.6.0"
|
|
63
|
+
"typescript": "^5.6.0",
|
|
64
|
+
"vitest": "^4.1.7"
|
|
64
65
|
}
|
|
65
66
|
}
|