@enterprisestandard/react 0.0.2 → 0.0.3-beta.2
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 -2
- package/dist/index.js +285 -134
- package/dist/server.d.ts +6 -5
- package/dist/sso.d.ts +24 -29
- package/dist/ui/sign-in-loading.d.ts +3 -1
- package/dist/ui/signed-in.d.ts +1 -1
- package/dist/ui/signed-out.d.ts +1 -1
- package/dist/ui/sso-provider.d.ts +14 -3
- package/dist/vault.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type IAM } from './iam';
|
|
2
|
-
import {
|
|
2
|
+
import { type SSO } from './sso';
|
|
3
3
|
import { type Vault } from './vault';
|
|
4
4
|
export type EnterpriseStandard = {
|
|
5
5
|
ioniteUrl: string;
|
|
6
6
|
appId: string;
|
|
7
7
|
defaultInstance: boolean;
|
|
8
8
|
vault: Vault;
|
|
9
|
-
sso?:
|
|
9
|
+
sso?: SSO;
|
|
10
10
|
iam?: IAM;
|
|
11
11
|
};
|
|
12
12
|
type ESConfig = {
|
package/dist/index.js
CHANGED
|
@@ -31,35 +31,31 @@ function getES(es) {
|
|
|
31
31
|
|
|
32
32
|
// src/sso.ts
|
|
33
33
|
var jwksCache = new Map;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
async getUser(request) {
|
|
47
|
-
if (!this.config) {
|
|
34
|
+
function sso(config) {
|
|
35
|
+
const configWithDefaults = {
|
|
36
|
+
...config,
|
|
37
|
+
secure: config.secure !== undefined ? config.secure : false,
|
|
38
|
+
sameSite: config.sameSite !== undefined ? config.sameSite : "Lax",
|
|
39
|
+
cookiePrefix: config.cookiePrefix ?? `es.sso.${config.client_id}`,
|
|
40
|
+
cookiePath: config.cookiePath ?? "/"
|
|
41
|
+
};
|
|
42
|
+
async function getUser(request) {
|
|
43
|
+
if (!configWithDefaults) {
|
|
48
44
|
console.error("SSO Manager not initialized");
|
|
49
45
|
return;
|
|
50
46
|
}
|
|
51
47
|
try {
|
|
52
|
-
const token = await
|
|
48
|
+
const token = await getTokenFromCookies(request);
|
|
53
49
|
if (!token)
|
|
54
50
|
return;
|
|
55
|
-
return await
|
|
51
|
+
return await parseUser(token);
|
|
56
52
|
} catch (error) {
|
|
57
53
|
console.error("Error parsing user from cookies:", error);
|
|
58
54
|
return;
|
|
59
55
|
}
|
|
60
56
|
}
|
|
61
|
-
async getRequiredUser(request) {
|
|
62
|
-
const user = await
|
|
57
|
+
async function getRequiredUser(request) {
|
|
58
|
+
const user = await getUser(request);
|
|
63
59
|
if (user)
|
|
64
60
|
return user;
|
|
65
61
|
throw new Response("Unauthorized", {
|
|
@@ -67,38 +63,38 @@ class SSOManager {
|
|
|
67
63
|
statusText: "Unauthorized"
|
|
68
64
|
});
|
|
69
65
|
}
|
|
70
|
-
async initiateLogin(
|
|
71
|
-
if (!
|
|
66
|
+
async function initiateLogin({ landingUrl, errorUrl }) {
|
|
67
|
+
if (!configWithDefaults) {
|
|
72
68
|
console.error("SSO Manager not initialized");
|
|
73
69
|
return Promise.resolve(new Response("SSO Manager not initialized", { status: 503 }));
|
|
74
70
|
}
|
|
75
|
-
const state =
|
|
76
|
-
const codeVerifier =
|
|
77
|
-
const url = new URL(
|
|
78
|
-
url.searchParams.append("client_id",
|
|
79
|
-
url.searchParams.append("redirect_uri",
|
|
71
|
+
const state = generateRandomString();
|
|
72
|
+
const codeVerifier = generateRandomString(64);
|
|
73
|
+
const url = new URL(configWithDefaults.authorization_url);
|
|
74
|
+
url.searchParams.append("client_id", configWithDefaults.client_id);
|
|
75
|
+
url.searchParams.append("redirect_uri", configWithDefaults.redirect_uri);
|
|
80
76
|
url.searchParams.append("response_type", "code");
|
|
81
|
-
url.searchParams.append("scope",
|
|
77
|
+
url.searchParams.append("scope", configWithDefaults.scope);
|
|
82
78
|
url.searchParams.append("state", state);
|
|
83
|
-
const codeChallenge = await
|
|
79
|
+
const codeChallenge = await pkceChallengeFromVerifier(codeVerifier);
|
|
84
80
|
url.searchParams.append("code_challenge", codeChallenge);
|
|
85
81
|
url.searchParams.append("code_challenge_method", "S256");
|
|
86
82
|
const val = {
|
|
87
83
|
state,
|
|
88
84
|
codeVerifier,
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
landingUrl,
|
|
86
|
+
errorUrl
|
|
91
87
|
};
|
|
92
88
|
return new Response("Redirecting to SSO Provider", {
|
|
93
89
|
status: 302,
|
|
94
90
|
headers: {
|
|
95
91
|
Location: url.toString(),
|
|
96
|
-
"Set-Cookie":
|
|
92
|
+
"Set-Cookie": createCookie("state", val, 86400)
|
|
97
93
|
}
|
|
98
94
|
});
|
|
99
95
|
}
|
|
100
|
-
async callbackHandler(request) {
|
|
101
|
-
if (!
|
|
96
|
+
async function callbackHandler(request) {
|
|
97
|
+
if (!configWithDefaults) {
|
|
102
98
|
console.error("SSO Manager not initialized");
|
|
103
99
|
return Promise.resolve(new Response("SSO Manager not initialized", { status: 503 }));
|
|
104
100
|
}
|
|
@@ -107,37 +103,37 @@ class SSOManager {
|
|
|
107
103
|
try {
|
|
108
104
|
const codeFromUrl = must(params.get("code"), 'OIDC "code" was not passed as a search param, ensure that the SSO login completed successfully');
|
|
109
105
|
const stateFromUrl = must(params.get("state"), 'OIDC "state" was not passed as a search param, ensure that the SSO login completed successfully');
|
|
110
|
-
const cookie =
|
|
111
|
-
const { codeVerifier, state,
|
|
106
|
+
const cookie = getCookie("state", request, true);
|
|
107
|
+
const { codeVerifier, state, landingUrl } = cookie ?? {};
|
|
112
108
|
must(codeVerifier, 'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');
|
|
113
109
|
must(state, 'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');
|
|
114
|
-
must(
|
|
110
|
+
must(landingUrl, 'OIDC "landingUrl" was not present in cookies');
|
|
115
111
|
if (stateFromUrl !== state) {
|
|
116
112
|
throw new Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');
|
|
117
113
|
}
|
|
118
|
-
const tokenResponse = await
|
|
119
|
-
const user = await
|
|
114
|
+
const tokenResponse = await exchangeCodeForToken(codeFromUrl, codeVerifier);
|
|
115
|
+
const user = await parseUser(tokenResponse);
|
|
120
116
|
return new Response("Authentication successful, redirecting", {
|
|
121
117
|
status: 302,
|
|
122
118
|
headers: [
|
|
123
|
-
["Location",
|
|
124
|
-
["Set-Cookie",
|
|
125
|
-
...
|
|
119
|
+
["Location", landingUrl],
|
|
120
|
+
["Set-Cookie", clearCookie("state")],
|
|
121
|
+
...createJwtCookies(tokenResponse, user.sso.expires)
|
|
126
122
|
]
|
|
127
123
|
});
|
|
128
124
|
} catch (error) {
|
|
129
125
|
console.error("Error during sign-in callback:", error);
|
|
130
126
|
try {
|
|
131
|
-
const cookie =
|
|
132
|
-
const {
|
|
133
|
-
if (
|
|
134
|
-
return new Response("Redirecting to error
|
|
127
|
+
const cookie = getCookie("state", request, true);
|
|
128
|
+
const { errorUrl } = cookie ?? {};
|
|
129
|
+
if (errorUrl) {
|
|
130
|
+
return new Response("Redirecting to error url", {
|
|
135
131
|
status: 302,
|
|
136
|
-
headers: [["Location",
|
|
132
|
+
headers: [["Location", errorUrl]]
|
|
137
133
|
});
|
|
138
134
|
}
|
|
139
135
|
} catch (_err) {
|
|
140
|
-
console.warn("Error parsing the
|
|
136
|
+
console.warn("Error parsing the errorUrl from the OIDC cookie");
|
|
141
137
|
}
|
|
142
138
|
console.warn("No error page was found in the cookies. The user will be shown a default error page.");
|
|
143
139
|
return new Response("An error occurred during authentication, please return to the application homepage and try again.", {
|
|
@@ -145,10 +141,10 @@ class SSOManager {
|
|
|
145
141
|
});
|
|
146
142
|
}
|
|
147
143
|
}
|
|
148
|
-
async parseUser(token) {
|
|
149
|
-
if (!
|
|
144
|
+
async function parseUser(token) {
|
|
145
|
+
if (!configWithDefaults)
|
|
150
146
|
throw new Error("SSO Manager not initialized");
|
|
151
|
-
const idToken = await
|
|
147
|
+
const idToken = await parseJwt(token.id_token);
|
|
152
148
|
const expiresIn = Number(token.refresh_expires_in ?? token.expires_in ?? 3600);
|
|
153
149
|
const expires = token.expires ? new Date(token.expires) : new Date(Date.now() + expiresIn * 1000);
|
|
154
150
|
return {
|
|
@@ -165,12 +161,12 @@ class SSOManager {
|
|
|
165
161
|
sso: {
|
|
166
162
|
profile: {
|
|
167
163
|
...idToken,
|
|
168
|
-
iss: idToken.iss ||
|
|
169
|
-
aud: idToken.aud ||
|
|
164
|
+
iss: idToken.iss || configWithDefaults.authority,
|
|
165
|
+
aud: idToken.aud || configWithDefaults.client_id
|
|
170
166
|
},
|
|
171
167
|
tenant: {
|
|
172
|
-
id: idToken.idp || idToken.iss ||
|
|
173
|
-
name: idToken.iss ||
|
|
168
|
+
id: idToken.idp || idToken.iss || configWithDefaults.authority,
|
|
169
|
+
name: idToken.iss || configWithDefaults.authority
|
|
174
170
|
},
|
|
175
171
|
scope: token.scope,
|
|
176
172
|
tokenType: token.token_type,
|
|
@@ -179,15 +175,15 @@ class SSOManager {
|
|
|
179
175
|
}
|
|
180
176
|
};
|
|
181
177
|
}
|
|
182
|
-
async exchangeCodeForToken(code, codeVerifier) {
|
|
183
|
-
if (!
|
|
178
|
+
async function exchangeCodeForToken(code, codeVerifier) {
|
|
179
|
+
if (!configWithDefaults)
|
|
184
180
|
throw new Error("SSO Manager not initialized");
|
|
185
|
-
const tokenUrl =
|
|
181
|
+
const tokenUrl = configWithDefaults.token_url;
|
|
186
182
|
const body = new URLSearchParams;
|
|
187
183
|
body.append("grant_type", "authorization_code");
|
|
188
184
|
body.append("code", code);
|
|
189
|
-
body.append("redirect_uri",
|
|
190
|
-
body.append("client_id",
|
|
185
|
+
body.append("redirect_uri", configWithDefaults.redirect_uri);
|
|
186
|
+
body.append("client_id", configWithDefaults.client_id);
|
|
191
187
|
body.append("code_verifier", codeVerifier);
|
|
192
188
|
try {
|
|
193
189
|
const response = await fetch(tokenUrl, {
|
|
@@ -209,15 +205,15 @@ class SSOManager {
|
|
|
209
205
|
throw new Error("Error during token exchange");
|
|
210
206
|
}
|
|
211
207
|
}
|
|
212
|
-
async refreshToken(
|
|
213
|
-
return
|
|
214
|
-
if (!
|
|
208
|
+
async function refreshToken(refreshToken2) {
|
|
209
|
+
return retryWithBackoff(async () => {
|
|
210
|
+
if (!configWithDefaults)
|
|
215
211
|
throw new Error("SSO Manager not initialized");
|
|
216
|
-
const tokenUrl =
|
|
212
|
+
const tokenUrl = configWithDefaults.token_url;
|
|
217
213
|
const body = new URLSearchParams;
|
|
218
214
|
body.append("grant_type", "refresh_token");
|
|
219
|
-
body.append("refresh_token",
|
|
220
|
-
body.append("client_id",
|
|
215
|
+
body.append("refresh_token", refreshToken2);
|
|
216
|
+
body.append("client_id", configWithDefaults.client_id);
|
|
221
217
|
const response = await fetch(tokenUrl, {
|
|
222
218
|
method: "POST",
|
|
223
219
|
headers: {
|
|
@@ -234,12 +230,13 @@ class SSOManager {
|
|
|
234
230
|
return data;
|
|
235
231
|
});
|
|
236
232
|
}
|
|
237
|
-
async fetchJwks() {
|
|
238
|
-
const url =
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
233
|
+
async function fetchJwks() {
|
|
234
|
+
const url = configWithDefaults.jwks_uri || `${configWithDefaults.authority}/protocol/openid-connect/certs`;
|
|
235
|
+
const cached = jwksCache.get(url);
|
|
236
|
+
if (cached)
|
|
237
|
+
return cached;
|
|
238
|
+
return retryWithBackoff(async () => {
|
|
239
|
+
if (!configWithDefaults)
|
|
243
240
|
throw new Error("SSO Manager not initialized");
|
|
244
241
|
const response = await fetch(url);
|
|
245
242
|
if (!response.ok)
|
|
@@ -249,7 +246,7 @@ class SSOManager {
|
|
|
249
246
|
return jwks;
|
|
250
247
|
});
|
|
251
248
|
}
|
|
252
|
-
async retryWithBackoff(operation, maxRetries = 3, baseDelay = 1000, maxDelay = 30000) {
|
|
249
|
+
async function retryWithBackoff(operation, maxRetries = 3, baseDelay = 1000, maxDelay = 30000) {
|
|
253
250
|
let lastError = new Error("Placeholder Error");
|
|
254
251
|
for (let attempt = 0;attempt <= maxRetries; attempt++) {
|
|
255
252
|
try {
|
|
@@ -270,7 +267,7 @@ class SSOManager {
|
|
|
270
267
|
}
|
|
271
268
|
throw lastError;
|
|
272
269
|
}
|
|
273
|
-
async parseJwt(token) {
|
|
270
|
+
async function parseJwt(token) {
|
|
274
271
|
try {
|
|
275
272
|
const parts = token.split(".");
|
|
276
273
|
if (parts.length !== 3)
|
|
@@ -278,7 +275,7 @@ class SSOManager {
|
|
|
278
275
|
const header = JSON.parse(atob(parts[0].replace(/-/g, "+").replace(/_/g, "/")));
|
|
279
276
|
const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
|
|
280
277
|
const signature = parts[2].replace(/-/g, "+").replace(/_/g, "/");
|
|
281
|
-
const publicKey = await
|
|
278
|
+
const publicKey = await getPublicKey(header.kid);
|
|
282
279
|
const encoder = new TextEncoder;
|
|
283
280
|
const data = encoder.encode(`${parts[0]}.${parts[1]}`);
|
|
284
281
|
const isValid = await crypto.subtle.verify("RSASSA-PKCS1-v1_5", publicKey, Uint8Array.from(atob(signature), (c) => c.charCodeAt(0)), data);
|
|
@@ -290,12 +287,12 @@ class SSOManager {
|
|
|
290
287
|
throw e;
|
|
291
288
|
}
|
|
292
289
|
}
|
|
293
|
-
generateRandomString(length = 32) {
|
|
290
|
+
function generateRandomString(length = 32) {
|
|
294
291
|
const array = new Uint8Array(length);
|
|
295
292
|
crypto.getRandomValues(array);
|
|
296
293
|
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("").substring(0, length);
|
|
297
294
|
}
|
|
298
|
-
async pkceChallengeFromVerifier(verifier) {
|
|
295
|
+
async function pkceChallengeFromVerifier(verifier) {
|
|
299
296
|
const encoder = new TextEncoder;
|
|
300
297
|
const data = encoder.encode(verifier);
|
|
301
298
|
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
@@ -303,8 +300,8 @@ class SSOManager {
|
|
|
303
300
|
const hashBase64 = btoa(String.fromCharCode(...hashArray)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
304
301
|
return hashBase64;
|
|
305
302
|
}
|
|
306
|
-
async getPublicKey(kid) {
|
|
307
|
-
const jwks = await
|
|
303
|
+
async function getPublicKey(kid) {
|
|
304
|
+
const jwks = await fetchJwks();
|
|
308
305
|
const key = jwks.keys.find((k) => k.kid === kid);
|
|
309
306
|
if (!key)
|
|
310
307
|
throw new Error("Public key not found");
|
|
@@ -315,7 +312,7 @@ class SSOManager {
|
|
|
315
312
|
}, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["verify"]);
|
|
316
313
|
return publicKey;
|
|
317
314
|
}
|
|
318
|
-
createJwtCookies(token, expires) {
|
|
315
|
+
function createJwtCookies(token, expires) {
|
|
319
316
|
const control = {
|
|
320
317
|
expires_in: token.expires_in,
|
|
321
318
|
refresh_expires_in: token.refresh_expires_in,
|
|
@@ -325,17 +322,17 @@ class SSOManager {
|
|
|
325
322
|
expires: expires.toISOString()
|
|
326
323
|
};
|
|
327
324
|
return [
|
|
328
|
-
["Set-Cookie",
|
|
329
|
-
["Set-Cookie",
|
|
330
|
-
["Set-Cookie",
|
|
331
|
-
["Set-Cookie",
|
|
325
|
+
["Set-Cookie", createCookie("access", token.access_token, expires)],
|
|
326
|
+
["Set-Cookie", createCookie("id", token.id_token, expires)],
|
|
327
|
+
["Set-Cookie", createCookie("refresh", token.refresh_token ?? "", expires)],
|
|
328
|
+
["Set-Cookie", createCookie("control", control, expires)]
|
|
332
329
|
];
|
|
333
330
|
}
|
|
334
|
-
async
|
|
335
|
-
const access_token =
|
|
336
|
-
const id_token =
|
|
337
|
-
const refresh_token =
|
|
338
|
-
const control =
|
|
331
|
+
async function getTokenFromCookies(req) {
|
|
332
|
+
const access_token = getCookie("access", req);
|
|
333
|
+
const id_token = getCookie("id", req);
|
|
334
|
+
const refresh_token = getCookie("refresh", req);
|
|
335
|
+
const control = getCookie("control", req, true);
|
|
339
336
|
if (!access_token || !id_token || !refresh_token || !control) {
|
|
340
337
|
return;
|
|
341
338
|
}
|
|
@@ -346,12 +343,18 @@ class SSOManager {
|
|
|
346
343
|
...control
|
|
347
344
|
};
|
|
348
345
|
if (control.expires && refresh_token && Date.now() > new Date(control.expires).getTime()) {
|
|
349
|
-
tokenResponse = await
|
|
346
|
+
tokenResponse = await refreshToken(refresh_token);
|
|
350
347
|
}
|
|
351
348
|
return tokenResponse;
|
|
352
349
|
}
|
|
353
|
-
|
|
354
|
-
|
|
350
|
+
async function getJwt(request) {
|
|
351
|
+
const tokenResponse = await getTokenFromCookies(request);
|
|
352
|
+
if (!tokenResponse)
|
|
353
|
+
return;
|
|
354
|
+
return tokenResponse.access_token;
|
|
355
|
+
}
|
|
356
|
+
function createCookie(name, value, expires) {
|
|
357
|
+
name = `${configWithDefaults.cookiePrefix}.${name}`;
|
|
355
358
|
if (typeof value !== "string") {
|
|
356
359
|
value = btoa(JSON.stringify(value));
|
|
357
360
|
}
|
|
@@ -366,16 +369,16 @@ class SSOManager {
|
|
|
366
369
|
if (value.length > 4000) {
|
|
367
370
|
throw new Error(`Error setting cookie: ${name}. Cookie length is: ${value.length}`);
|
|
368
371
|
}
|
|
369
|
-
return `${name}=${value}; ${exp}; Path=${
|
|
372
|
+
return `${name}=${value}; ${exp}; Path=${configWithDefaults.cookiePath}; HttpOnly;${configWithDefaults.secure ? " Secure;" : ""} SameSite=${configWithDefaults.sameSite};`;
|
|
370
373
|
}
|
|
371
|
-
clearCookie(name) {
|
|
372
|
-
return `${
|
|
374
|
+
function clearCookie(name) {
|
|
375
|
+
return `${configWithDefaults.cookiePrefix}.${name}=; Max-Age=0; Path=${configWithDefaults.cookiePath}; HttpOnly;${configWithDefaults.secure ? " Secure;" : ""} SameSite=${configWithDefaults.sameSite};`;
|
|
373
376
|
}
|
|
374
|
-
getCookie(name, req, parse = false) {
|
|
377
|
+
function getCookie(name, req, parse = false) {
|
|
375
378
|
const header = req.headers.get("cookie");
|
|
376
379
|
if (!header)
|
|
377
380
|
return null;
|
|
378
|
-
const cookie = header.split(";").find((row) => row.trim().startsWith(`${
|
|
381
|
+
const cookie = header.split(";").find((row) => row.trim().startsWith(`${configWithDefaults.cookiePrefix}.${name}=`));
|
|
379
382
|
if (!cookie)
|
|
380
383
|
return null;
|
|
381
384
|
const val = cookie.split("=")[1].trim();
|
|
@@ -384,17 +387,73 @@ class SSOManager {
|
|
|
384
387
|
const str = atob(val);
|
|
385
388
|
return JSON.parse(str);
|
|
386
389
|
}
|
|
390
|
+
async function handler(request, handlerConfig) {
|
|
391
|
+
let { loginUrl, userUrl, errorUrl, landingUrl, tokenUrl, refreshUrl } = handlerConfig ?? {};
|
|
392
|
+
if (!loginUrl)
|
|
393
|
+
loginUrl = "*";
|
|
394
|
+
const path = new URL(request.url).pathname;
|
|
395
|
+
if (new URL(config.redirect_uri).pathname === path) {
|
|
396
|
+
return callbackHandler(request);
|
|
397
|
+
}
|
|
398
|
+
if (userUrl === path) {
|
|
399
|
+
const user = await getUser(request);
|
|
400
|
+
if (!user) {
|
|
401
|
+
return new Response("User not logged in", { status: 401 });
|
|
402
|
+
}
|
|
403
|
+
return new Response(JSON.stringify(user), {
|
|
404
|
+
headers: [["Content-Type", "application/json"]]
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
if (tokenUrl === path) {
|
|
408
|
+
const tokenResponse = await getTokenFromCookies(request);
|
|
409
|
+
if (!tokenResponse) {
|
|
410
|
+
return new Response("User not logged in", { status: 401 });
|
|
411
|
+
}
|
|
412
|
+
return new Response(JSON.stringify({
|
|
413
|
+
token: tokenResponse.access_token,
|
|
414
|
+
expires: tokenResponse.expires
|
|
415
|
+
}), {
|
|
416
|
+
headers: [["Content-Type", "application/json"]]
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
if (refreshUrl === path) {
|
|
420
|
+
const tokenResponse = await getTokenFromCookies(request);
|
|
421
|
+
if (!tokenResponse) {
|
|
422
|
+
return new Response("User not logged in", { status: 401 });
|
|
423
|
+
}
|
|
424
|
+
return new Response("Refresh Complete", { status: 200 });
|
|
425
|
+
}
|
|
426
|
+
if (loginUrl === "*" || loginUrl === path) {
|
|
427
|
+
return initiateLogin({
|
|
428
|
+
landingUrl: landingUrl || "/",
|
|
429
|
+
errorUrl
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
return new Response("Not Found", { status: 404 });
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
getUser,
|
|
436
|
+
getRequiredUser,
|
|
437
|
+
getJwt,
|
|
438
|
+
initiateLogin,
|
|
439
|
+
callbackHandler,
|
|
440
|
+
handler
|
|
441
|
+
};
|
|
387
442
|
}
|
|
388
443
|
|
|
389
444
|
// src/vault.ts
|
|
390
|
-
|
|
445
|
+
function vault(url, token) {
|
|
391
446
|
async function getFullSecret(path) {
|
|
392
447
|
const resp = await fetch(`${url}/${path}`, { headers: { "X-Vault-Token": token } });
|
|
393
448
|
if (resp.status !== 200) {
|
|
394
449
|
throw new Error(`Vault returned invalid status, ${resp.status}: '${resp.statusText}' from URL: ${url}`);
|
|
395
450
|
}
|
|
396
|
-
|
|
397
|
-
|
|
451
|
+
try {
|
|
452
|
+
const secret = await resp.json();
|
|
453
|
+
return secret.data;
|
|
454
|
+
} catch (cause) {
|
|
455
|
+
throw new Error("Error retrieving secret", { cause });
|
|
456
|
+
}
|
|
398
457
|
}
|
|
399
458
|
return {
|
|
400
459
|
url,
|
|
@@ -508,8 +567,8 @@ function oidcCallbackSchema(vendor) {
|
|
|
508
567
|
};
|
|
509
568
|
}
|
|
510
569
|
// src/server.ts
|
|
511
|
-
function getSSO(
|
|
512
|
-
es = getES(es);
|
|
570
|
+
function getSSO(config) {
|
|
571
|
+
const es = getES(config?.es);
|
|
513
572
|
if (!es.sso) {
|
|
514
573
|
console.error("TODO tell them how to connect SSO");
|
|
515
574
|
return;
|
|
@@ -523,36 +582,42 @@ function unavailable() {
|
|
|
523
582
|
headers: { "Content-Type": "application/json" }
|
|
524
583
|
});
|
|
525
584
|
}
|
|
526
|
-
async function getUser(request,
|
|
527
|
-
return getSSO(
|
|
585
|
+
async function getUser(request, config) {
|
|
586
|
+
return getSSO(config)?.getUser(request);
|
|
587
|
+
}
|
|
588
|
+
async function getRequiredUser(request, config) {
|
|
589
|
+
const sso2 = getSSO(config);
|
|
590
|
+
if (!sso2)
|
|
591
|
+
throw unavailable();
|
|
592
|
+
return sso2.getRequiredUser(request);
|
|
528
593
|
}
|
|
529
|
-
async function
|
|
530
|
-
const
|
|
531
|
-
if (!
|
|
594
|
+
async function initiateLogin(config) {
|
|
595
|
+
const sso2 = getSSO(config);
|
|
596
|
+
if (!sso2)
|
|
532
597
|
throw unavailable();
|
|
533
|
-
return
|
|
598
|
+
return sso2.initiateLogin(config);
|
|
534
599
|
}
|
|
535
|
-
async function
|
|
536
|
-
const
|
|
537
|
-
if (!
|
|
600
|
+
async function callback(request, config) {
|
|
601
|
+
const sso2 = getSSO(config);
|
|
602
|
+
if (!sso2)
|
|
538
603
|
throw unavailable();
|
|
539
|
-
return
|
|
604
|
+
return sso2.callbackHandler(request);
|
|
540
605
|
}
|
|
541
|
-
async function
|
|
542
|
-
const
|
|
543
|
-
if (!
|
|
606
|
+
async function handler(request, config) {
|
|
607
|
+
const sso2 = getSSO(config);
|
|
608
|
+
if (!sso2)
|
|
544
609
|
throw unavailable();
|
|
545
|
-
return
|
|
610
|
+
return sso2.handler(request, config);
|
|
546
611
|
}
|
|
547
612
|
// src/ui/sign-in-loading.tsx
|
|
548
613
|
import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
|
|
549
|
-
function SignInLoading({ children }) {
|
|
614
|
+
function SignInLoading({ complete = false, children }) {
|
|
550
615
|
const { isLoading } = useUser();
|
|
551
|
-
if (isLoading)
|
|
616
|
+
if (isLoading && !complete)
|
|
552
617
|
return /* @__PURE__ */ jsxDEV(Fragment, {
|
|
553
618
|
children
|
|
554
619
|
}, undefined, false, undefined, this);
|
|
555
|
-
return
|
|
620
|
+
return null;
|
|
556
621
|
}
|
|
557
622
|
// src/ui/signed-in.tsx
|
|
558
623
|
import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime";
|
|
@@ -562,14 +627,14 @@ function SignedIn({ children }) {
|
|
|
562
627
|
return /* @__PURE__ */ jsxDEV2(Fragment2, {
|
|
563
628
|
children
|
|
564
629
|
}, undefined, false, undefined, this);
|
|
565
|
-
return
|
|
630
|
+
return null;
|
|
566
631
|
}
|
|
567
632
|
// src/ui/signed-out.tsx
|
|
568
633
|
import { jsxDEV as jsxDEV3, Fragment as Fragment3 } from "react/jsx-dev-runtime";
|
|
569
634
|
function SignedOut({ children }) {
|
|
570
635
|
const { user } = useUser();
|
|
571
636
|
if (user)
|
|
572
|
-
return
|
|
637
|
+
return null;
|
|
573
638
|
return /* @__PURE__ */ jsxDEV3(Fragment3, {
|
|
574
639
|
children
|
|
575
640
|
}, undefined, false, undefined, this);
|
|
@@ -577,7 +642,7 @@ function SignedOut({ children }) {
|
|
|
577
642
|
// src/ui/sso-provider.tsx
|
|
578
643
|
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
|
579
644
|
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
580
|
-
var
|
|
645
|
+
var CTX = createContext(undefined);
|
|
581
646
|
var generateStorageKey = (tenantId) => {
|
|
582
647
|
return `es-sso-user-${tenantId.replace(/[^a-zA-Z0-9]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")}`;
|
|
583
648
|
};
|
|
@@ -586,6 +651,8 @@ function SSOProvider({
|
|
|
586
651
|
storage = "memory",
|
|
587
652
|
storageKey,
|
|
588
653
|
userUrl,
|
|
654
|
+
tokenUrl,
|
|
655
|
+
refreshUrl,
|
|
589
656
|
disableListener = false,
|
|
590
657
|
children
|
|
591
658
|
}) {
|
|
@@ -598,7 +665,7 @@ function SSOProvider({
|
|
|
598
665
|
return user2.sso?.tenant?.id === tenantId;
|
|
599
666
|
}, [tenantId]);
|
|
600
667
|
const loadUserFromStorage = useCallback(() => {
|
|
601
|
-
if (storage === "memory")
|
|
668
|
+
if (storage === "memory" || typeof window === "undefined")
|
|
602
669
|
return null;
|
|
603
670
|
try {
|
|
604
671
|
const storageObject = storage === "local" ? localStorage : sessionStorage;
|
|
@@ -616,7 +683,7 @@ function SSOProvider({
|
|
|
616
683
|
}
|
|
617
684
|
}, [storage, actualStorageKey, isValidUser]);
|
|
618
685
|
const saveUserToStorage = useCallback((user2) => {
|
|
619
|
-
if (storage === "memory")
|
|
686
|
+
if (storage === "memory" || typeof window === "undefined")
|
|
620
687
|
return;
|
|
621
688
|
try {
|
|
622
689
|
const storageObject = storage === "local" ? localStorage : sessionStorage;
|
|
@@ -641,6 +708,12 @@ function SSOProvider({
|
|
|
641
708
|
setIsLoading(true);
|
|
642
709
|
try {
|
|
643
710
|
const response = await fetch(userUrl);
|
|
711
|
+
if (response.status === 401) {
|
|
712
|
+
setUserState(null);
|
|
713
|
+
saveUserToStorage(null);
|
|
714
|
+
setIsLoading(false);
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
644
717
|
if (!response.ok) {
|
|
645
718
|
throw new Error(`Failed to fetch user: ${response.status} ${response.statusText}`);
|
|
646
719
|
}
|
|
@@ -662,20 +735,17 @@ function SSOProvider({
|
|
|
662
735
|
const storedUser = loadUserFromStorage();
|
|
663
736
|
if (storedUser) {
|
|
664
737
|
setUserState(storedUser);
|
|
665
|
-
|
|
666
|
-
|
|
738
|
+
}
|
|
739
|
+
if (userUrl) {
|
|
667
740
|
fetchUserFromUrl();
|
|
668
741
|
} else {
|
|
669
742
|
setIsLoading(false);
|
|
670
743
|
}
|
|
671
744
|
}, [loadUserFromStorage, userUrl, fetchUserFromUrl]);
|
|
672
745
|
useEffect(() => {
|
|
673
|
-
console.log(disableListener, storage, actualStorageKey);
|
|
674
746
|
if (disableListener || storage === "memory")
|
|
675
747
|
return;
|
|
676
|
-
console.log("set up listener");
|
|
677
748
|
const handleStorageChange = (event) => {
|
|
678
|
-
console.log("lsitened", actualStorageKey);
|
|
679
749
|
if (event.key !== actualStorageKey)
|
|
680
750
|
return;
|
|
681
751
|
if (event.newValue === null) {
|
|
@@ -702,20 +772,99 @@ function SSOProvider({
|
|
|
702
772
|
const contextValue = {
|
|
703
773
|
user,
|
|
704
774
|
setUser,
|
|
705
|
-
isLoading
|
|
775
|
+
isLoading,
|
|
776
|
+
tokenUrl,
|
|
777
|
+
refreshUrl
|
|
706
778
|
};
|
|
707
|
-
return /* @__PURE__ */ jsxDEV4(
|
|
779
|
+
return /* @__PURE__ */ jsxDEV4(CTX.Provider, {
|
|
708
780
|
value: contextValue,
|
|
709
781
|
children
|
|
710
782
|
}, undefined, false, undefined, this);
|
|
711
783
|
}
|
|
712
784
|
function useUser() {
|
|
713
|
-
const context = useContext(
|
|
785
|
+
const context = useContext(CTX);
|
|
714
786
|
if (context === undefined) {
|
|
715
787
|
throw new Error("useUser must be used within a SSOProvider");
|
|
716
788
|
}
|
|
717
789
|
return context;
|
|
718
790
|
}
|
|
791
|
+
function useToken() {
|
|
792
|
+
const context = useContext(CTX);
|
|
793
|
+
if (context === undefined) {
|
|
794
|
+
throw new Error("useToken must be used within a SSOProvider");
|
|
795
|
+
}
|
|
796
|
+
const { tokenUrl, refreshUrl } = context;
|
|
797
|
+
if (!tokenUrl || !refreshUrl) {
|
|
798
|
+
throw new Error('useToken requires that a "tokenUrl" and "refreshUrl" be set in the SSOProvider');
|
|
799
|
+
}
|
|
800
|
+
const [token, setToken] = useState(null);
|
|
801
|
+
const [expires, setExpires] = useState(null);
|
|
802
|
+
const [isLoading, setIsLoading] = useState(!!tokenUrl);
|
|
803
|
+
const [error, setError] = useState(null);
|
|
804
|
+
const fetchJwt = useCallback(async (url) => {
|
|
805
|
+
setIsLoading(true);
|
|
806
|
+
setError(null);
|
|
807
|
+
try {
|
|
808
|
+
const response = await fetch(url);
|
|
809
|
+
if (response.status === 401) {
|
|
810
|
+
context.setUser(null);
|
|
811
|
+
setToken(null);
|
|
812
|
+
setExpires(null);
|
|
813
|
+
setIsLoading(false);
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
if (!response.ok) {
|
|
817
|
+
throw new Error(`Failed to fetch JWT: ${response.status} ${response.statusText}`);
|
|
818
|
+
}
|
|
819
|
+
const data = await response.json();
|
|
820
|
+
setToken(data.token);
|
|
821
|
+
setExpires(new Date(data.expires));
|
|
822
|
+
} catch (err) {
|
|
823
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
824
|
+
setError(error2);
|
|
825
|
+
setToken(null);
|
|
826
|
+
setExpires(null);
|
|
827
|
+
console.error("Error fetching JWT:", error2);
|
|
828
|
+
} finally {
|
|
829
|
+
setIsLoading(false);
|
|
830
|
+
}
|
|
831
|
+
}, [context]);
|
|
832
|
+
const refresh = useCallback(async () => {
|
|
833
|
+
const url = refreshUrl || tokenUrl;
|
|
834
|
+
if (!url) {
|
|
835
|
+
console.warn("No tokenUrl or refreshUrl provided");
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
await fetchJwt(url);
|
|
839
|
+
}, [refreshUrl, tokenUrl, fetchJwt]);
|
|
840
|
+
useEffect(() => {
|
|
841
|
+
if (!tokenUrl) {
|
|
842
|
+
setIsLoading(false);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
fetchJwt(tokenUrl);
|
|
846
|
+
}, [tokenUrl, fetchJwt]);
|
|
847
|
+
useEffect(() => {
|
|
848
|
+
if (!expires || !refreshUrl)
|
|
849
|
+
return;
|
|
850
|
+
const checkExpiration = () => {
|
|
851
|
+
const now = new Date;
|
|
852
|
+
const timeUntilExpiry = expires.getTime() - now.getTime();
|
|
853
|
+
if (timeUntilExpiry <= 60000 && timeUntilExpiry > 0) {
|
|
854
|
+
refresh();
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
checkExpiration();
|
|
858
|
+
const interval = setInterval(checkExpiration, 30000);
|
|
859
|
+
return () => clearInterval(interval);
|
|
860
|
+
}, [expires, refreshUrl, refresh]);
|
|
861
|
+
return {
|
|
862
|
+
token,
|
|
863
|
+
isLoading,
|
|
864
|
+
error,
|
|
865
|
+
refresh
|
|
866
|
+
};
|
|
867
|
+
}
|
|
719
868
|
|
|
720
869
|
// src/index.ts
|
|
721
870
|
async function enterpriseStandard(appId, appKey, initConfig) {
|
|
@@ -724,9 +873,9 @@ async function enterpriseStandard(appId, appKey, initConfig) {
|
|
|
724
873
|
let paths;
|
|
725
874
|
const ioniteUrl = initConfig?.ioniteUrl ?? "https://ionite.com";
|
|
726
875
|
if (appId === "IONITE_PUBLIC_DEMO") {
|
|
727
|
-
vaultUrl = "https://vault.ionite.dev/v1/secret/data";
|
|
728
|
-
vaultToken = "hvs.
|
|
729
|
-
paths = { sso: "ionite/
|
|
876
|
+
vaultUrl = "https://vault-ionite.ionite.dev/v1/secret/data";
|
|
877
|
+
vaultToken = "hvs.NuiBSLuFk5Ju4JDOUwTOlSlP";
|
|
878
|
+
paths = { sso: "ionite/IONITE_PUBLIC_DEMO" };
|
|
730
879
|
} else if (appKey) {
|
|
731
880
|
if (!vaultUrl || !vaultToken) {
|
|
732
881
|
throw new Error("TODO something is wrong with the ionite config, handle this error");
|
|
@@ -742,7 +891,7 @@ async function enterpriseStandard(appId, appKey, initConfig) {
|
|
|
742
891
|
ioniteUrl,
|
|
743
892
|
defaultInstance: initConfig?.defaultInstance || initConfig?.defaultInstance !== false && !defaultInstance2,
|
|
744
893
|
vault: vaultClient,
|
|
745
|
-
sso: paths.sso ?
|
|
894
|
+
sso: paths.sso ? sso(await vaultClient.getSecret(paths.sso)) : undefined,
|
|
746
895
|
iam: paths.iam ? await iam(await vaultClient.getSecret(paths.iam)) : undefined
|
|
747
896
|
};
|
|
748
897
|
if (result.defaultInstance) {
|
|
@@ -755,8 +904,10 @@ async function enterpriseStandard(appId, appKey, initConfig) {
|
|
|
755
904
|
}
|
|
756
905
|
export {
|
|
757
906
|
useUser,
|
|
907
|
+
useToken,
|
|
758
908
|
oidcCallbackSchema,
|
|
759
909
|
initiateLogin,
|
|
910
|
+
handler,
|
|
760
911
|
getUser,
|
|
761
912
|
getRequiredUser,
|
|
762
913
|
enterpriseStandard,
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function getUser(request: Request,
|
|
3
|
-
export declare function getRequiredUser(request: Request,
|
|
4
|
-
export declare function initiateLogin(
|
|
5
|
-
export declare function callback(request: Request,
|
|
1
|
+
import type { ESConfig, LoginConfig, SSOHandlerConfig } from './sso';
|
|
2
|
+
export declare function getUser(request: Request, config?: ESConfig): Promise<import("./enterprise-user").EnterpriseUser | undefined>;
|
|
3
|
+
export declare function getRequiredUser(request: Request, config?: ESConfig): Promise<import("./enterprise-user").EnterpriseUser>;
|
|
4
|
+
export declare function initiateLogin(config: LoginConfig): Promise<Response>;
|
|
5
|
+
export declare function callback(request: Request, config?: ESConfig): Promise<Response>;
|
|
6
|
+
export declare function handler(request: Request, config?: SSOHandlerConfig): Promise<Response>;
|
package/dist/sso.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EnterpriseUser } from '.';
|
|
1
|
+
import type { EnterpriseStandard, EnterpriseUser } from '.';
|
|
2
2
|
export type SSOConfig = {
|
|
3
3
|
authority: string;
|
|
4
4
|
token_url: string;
|
|
@@ -15,32 +15,27 @@ export type SSOConfig = {
|
|
|
15
15
|
sameSite?: 'Strict' | 'Lax';
|
|
16
16
|
secure?: boolean;
|
|
17
17
|
};
|
|
18
|
-
type
|
|
19
|
-
|
|
20
|
-
sameSite: string;
|
|
21
|
-
cookiePrefix: string;
|
|
22
|
-
cookiePath: string;
|
|
18
|
+
export type ESConfig = {
|
|
19
|
+
es?: EnterpriseStandard;
|
|
23
20
|
};
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
export {};
|
|
21
|
+
export type LoginConfig = {
|
|
22
|
+
landingUrl: string;
|
|
23
|
+
errorUrl?: string;
|
|
24
|
+
} & ESConfig;
|
|
25
|
+
export type SSOHandlerConfig = {
|
|
26
|
+
loginUrl?: string;
|
|
27
|
+
userUrl?: string;
|
|
28
|
+
errorUrl?: string;
|
|
29
|
+
landingUrl?: string;
|
|
30
|
+
tokenUrl?: string;
|
|
31
|
+
refreshUrl?: string;
|
|
32
|
+
} & ESConfig;
|
|
33
|
+
export type SSO = {
|
|
34
|
+
getUser: (request: Request) => Promise<EnterpriseUser | undefined>;
|
|
35
|
+
getRequiredUser: (request: Request) => Promise<EnterpriseUser>;
|
|
36
|
+
getJwt: (request: Request) => Promise<string | undefined>;
|
|
37
|
+
initiateLogin: (config: LoginConfig) => Promise<Response>;
|
|
38
|
+
callbackHandler: (request: Request) => Promise<Response>;
|
|
39
|
+
handler: (request: Request, handlerConfig?: SSOHandlerConfig) => Promise<Response>;
|
|
40
|
+
};
|
|
41
|
+
export declare function sso(config: SSOConfig): SSO;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { PropsWithChildren } from 'react';
|
|
2
|
-
export declare function SignInLoading({ children }:
|
|
2
|
+
export declare function SignInLoading({ complete, children }: {
|
|
3
|
+
complete?: boolean;
|
|
4
|
+
} & PropsWithChildren): import("react/jsx-runtime").JSX.Element | null;
|
package/dist/ui/signed-in.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { PropsWithChildren } from 'react';
|
|
2
|
-
export declare function SignedIn({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function SignedIn({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element | null;
|
package/dist/ui/signed-out.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { PropsWithChildren } from 'react';
|
|
2
|
-
export declare function SignedOut({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function SignedOut({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -6,14 +6,25 @@ interface SSOProviderProps {
|
|
|
6
6
|
storage?: StorageType;
|
|
7
7
|
storageKey?: string;
|
|
8
8
|
userUrl?: string;
|
|
9
|
+
tokenUrl?: string;
|
|
10
|
+
refreshUrl?: string;
|
|
9
11
|
disableListener?: boolean;
|
|
10
12
|
children: ReactNode;
|
|
11
13
|
}
|
|
12
|
-
interface
|
|
14
|
+
interface SSOContext {
|
|
13
15
|
user: EnterpriseUser | null;
|
|
14
16
|
setUser: (user: EnterpriseUser | null) => void;
|
|
15
17
|
isLoading: boolean;
|
|
18
|
+
tokenUrl?: string;
|
|
19
|
+
refreshUrl?: string;
|
|
16
20
|
}
|
|
17
|
-
export declare function SSOProvider({ tenantId, storage, storageKey, userUrl, disableListener, children, }: SSOProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
-
export declare function useUser():
|
|
21
|
+
export declare function SSOProvider({ tenantId, storage, storageKey, userUrl, tokenUrl, refreshUrl, disableListener, children, }: SSOProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function useUser(): SSOContext;
|
|
23
|
+
interface UseTokenReturn {
|
|
24
|
+
token: string | null;
|
|
25
|
+
isLoading: boolean;
|
|
26
|
+
error: Error | null;
|
|
27
|
+
refresh: () => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare function useToken(): UseTokenReturn;
|
|
19
30
|
export {};
|
package/dist/vault.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export type Vault = {
|
|
|
13
13
|
getFullSecret: <T>(path: string) => Promise<Secret<T>>;
|
|
14
14
|
getSecret: <T>(path: string) => Promise<T>;
|
|
15
15
|
};
|
|
16
|
-
export declare function vault(url: string, token: string):
|
|
16
|
+
export declare function vault(url: string, token: string): Vault;
|
|
17
17
|
export {};
|