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