@enterprisestandard/react 0.0.3-beta.20251106.1 → 0.0.3-beta.20251110.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.js +127 -9
- package/dist/sso.d.ts +4 -1
- package/dist/ui/sso-provider.d.ts +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ function getES(es) {
|
|
|
31
31
|
|
|
32
32
|
// src/sso.ts
|
|
33
33
|
var jwksCache = new Map;
|
|
34
|
+
var _logoutTokenJtis = new Set;
|
|
34
35
|
function sso(config) {
|
|
35
36
|
const configWithDefaults = {
|
|
36
37
|
...config,
|
|
@@ -93,6 +94,52 @@ function sso(config) {
|
|
|
93
94
|
}
|
|
94
95
|
});
|
|
95
96
|
}
|
|
97
|
+
async function logout(request, _config) {
|
|
98
|
+
try {
|
|
99
|
+
const refreshToken2 = getCookie("refresh", request);
|
|
100
|
+
if (refreshToken2) {
|
|
101
|
+
await revokeToken(refreshToken2);
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.warn("Failed to revoke token:", error);
|
|
105
|
+
}
|
|
106
|
+
const clearHeaders = [
|
|
107
|
+
["Set-Cookie", clearCookie("access")],
|
|
108
|
+
["Set-Cookie", clearCookie("id")],
|
|
109
|
+
["Set-Cookie", clearCookie("refresh")],
|
|
110
|
+
["Set-Cookie", clearCookie("control")],
|
|
111
|
+
["Set-Cookie", clearCookie("state")]
|
|
112
|
+
];
|
|
113
|
+
const url = new URL(request.url);
|
|
114
|
+
const redirectTo = url.searchParams.get("redirect");
|
|
115
|
+
if (redirectTo) {
|
|
116
|
+
return new Response("Logged out", {
|
|
117
|
+
status: 302,
|
|
118
|
+
headers: [["Location", redirectTo], ...clearHeaders]
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const accept = request.headers.get("accept");
|
|
122
|
+
const isAjax = accept?.includes("application/json") || accept?.includes("text/javascript");
|
|
123
|
+
if (isAjax) {
|
|
124
|
+
return new Response(JSON.stringify({ success: true, message: "Logged out" }), {
|
|
125
|
+
status: 200,
|
|
126
|
+
headers: [["Content-Type", "application/json"], ...clearHeaders]
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
return new Response(`
|
|
130
|
+
<!DOCTYPE html><html lang="en"><body>
|
|
131
|
+
<h1>Logout Complete</h1>
|
|
132
|
+
<div style="display: none">
|
|
133
|
+
It is not recommended to show the default logout page. Include '?redirect=/someHomePage' or logout asynchronously.
|
|
134
|
+
Check the <a href="https://EnterpriseStandard.com/sso#logout">Enterprise Standard Packages</a> for more information.
|
|
135
|
+
</div>
|
|
136
|
+
</body></html>
|
|
137
|
+
`, {
|
|
138
|
+
status: 200,
|
|
139
|
+
headers: [["Content-Type", "text/html"], ...clearHeaders]
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
96
143
|
async function callbackHandler(request) {
|
|
97
144
|
if (!configWithDefaults) {
|
|
98
145
|
console.error("SSO Manager not initialized");
|
|
@@ -231,6 +278,31 @@ function sso(config) {
|
|
|
231
278
|
return data;
|
|
232
279
|
});
|
|
233
280
|
}
|
|
281
|
+
async function revokeToken(token) {
|
|
282
|
+
try {
|
|
283
|
+
if (!configWithDefaults)
|
|
284
|
+
throw new Error("SSO Manager not initialized");
|
|
285
|
+
const revokeUrl = `${configWithDefaults.authority}/protocol/openid-connect/revoke`;
|
|
286
|
+
const body = new URLSearchParams;
|
|
287
|
+
body.append("token", token);
|
|
288
|
+
body.append("token_type_hint", "refresh_token");
|
|
289
|
+
body.append("client_id", configWithDefaults.client_id);
|
|
290
|
+
const response = await fetch(revokeUrl, {
|
|
291
|
+
method: "POST",
|
|
292
|
+
headers: {
|
|
293
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
294
|
+
},
|
|
295
|
+
body: body.toString()
|
|
296
|
+
});
|
|
297
|
+
if (!response.ok) {
|
|
298
|
+
console.warn("Token revocation failed:", response.status, response.statusText);
|
|
299
|
+
} else {
|
|
300
|
+
console.log("Token revoked successfully");
|
|
301
|
+
}
|
|
302
|
+
} catch (error) {
|
|
303
|
+
console.warn("Error revoking token:", error);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
234
306
|
async function fetchJwks() {
|
|
235
307
|
const url = configWithDefaults.jwks_uri || `${configWithDefaults.authority}/protocol/openid-connect/certs`;
|
|
236
308
|
const cached = jwksCache.get(url);
|
|
@@ -392,13 +464,20 @@ function sso(config) {
|
|
|
392
464
|
return JSON.parse(str);
|
|
393
465
|
}
|
|
394
466
|
async function handler(request, handlerConfig) {
|
|
395
|
-
|
|
396
|
-
if (!loginUrl)
|
|
397
|
-
loginUrl
|
|
467
|
+
const { loginUrl, userUrl, errorUrl, landingUrl, tokenUrl, refreshUrl, logoutUrl, jwksUrl } = handlerConfig ?? {};
|
|
468
|
+
if (!loginUrl) {
|
|
469
|
+
console.error("loginUrl is required");
|
|
470
|
+
}
|
|
398
471
|
const path = new URL(request.url).pathname;
|
|
399
472
|
if (new URL(config.redirect_uri).pathname === path) {
|
|
400
473
|
return callbackHandler(request);
|
|
401
474
|
}
|
|
475
|
+
if (loginUrl === path) {
|
|
476
|
+
return initiateLogin({
|
|
477
|
+
landingUrl: landingUrl || "/",
|
|
478
|
+
errorUrl
|
|
479
|
+
});
|
|
480
|
+
}
|
|
402
481
|
if (userUrl === path) {
|
|
403
482
|
const { tokens, refreshHeaders } = await getTokenFromCookies(request);
|
|
404
483
|
if (!tokens) {
|
|
@@ -434,18 +513,15 @@ function sso(config) {
|
|
|
434
513
|
headers: refreshHeaders
|
|
435
514
|
});
|
|
436
515
|
}
|
|
516
|
+
if (logoutUrl === path) {
|
|
517
|
+
return logout(request, { landingUrl: landingUrl || "/" });
|
|
518
|
+
}
|
|
437
519
|
if (jwksUrl === path) {
|
|
438
520
|
const jwks = await fetchJwks();
|
|
439
521
|
return new Response(JSON.stringify(jwks), {
|
|
440
522
|
headers: [["Content-Type", "application/json"]]
|
|
441
523
|
});
|
|
442
524
|
}
|
|
443
|
-
if (loginUrl === "*" || loginUrl === path) {
|
|
444
|
-
return initiateLogin({
|
|
445
|
-
landingUrl: landingUrl || "/",
|
|
446
|
-
errorUrl
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
525
|
return new Response("Not Found", { status: 404 });
|
|
450
526
|
}
|
|
451
527
|
return {
|
|
@@ -453,6 +529,7 @@ function sso(config) {
|
|
|
453
529
|
getRequiredUser,
|
|
454
530
|
getJwt,
|
|
455
531
|
initiateLogin,
|
|
532
|
+
logout,
|
|
456
533
|
callbackHandler,
|
|
457
534
|
handler
|
|
458
535
|
};
|
|
@@ -781,9 +858,14 @@ function SSOProvider({
|
|
|
781
858
|
}
|
|
782
859
|
}
|
|
783
860
|
};
|
|
861
|
+
const handleLogout = () => {
|
|
862
|
+
setUserState(null);
|
|
863
|
+
};
|
|
784
864
|
window.addEventListener("storage", handleStorageChange);
|
|
865
|
+
window.addEventListener("es-sso-logout", handleLogout);
|
|
785
866
|
return () => {
|
|
786
867
|
window.removeEventListener("storage", handleStorageChange);
|
|
868
|
+
window.removeEventListener("es-sso-logout", handleLogout);
|
|
787
869
|
};
|
|
788
870
|
}, [disableListener, storage, actualStorageKey, isValidUser]);
|
|
789
871
|
const contextValue = {
|
|
@@ -882,6 +964,41 @@ function useToken() {
|
|
|
882
964
|
refresh
|
|
883
965
|
};
|
|
884
966
|
}
|
|
967
|
+
async function logout(logoutUrl) {
|
|
968
|
+
try {
|
|
969
|
+
const response = await fetch(logoutUrl, {
|
|
970
|
+
headers: { Accept: "application/json" }
|
|
971
|
+
});
|
|
972
|
+
if (!response.ok) {
|
|
973
|
+
return { success: false, error: `HTTP ${response.status}` };
|
|
974
|
+
}
|
|
975
|
+
const data = await response.json();
|
|
976
|
+
if (!data.success) {
|
|
977
|
+
return { success: false, error: data.message || "Logout failed" };
|
|
978
|
+
}
|
|
979
|
+
if (typeof window !== "undefined") {
|
|
980
|
+
for (let i = localStorage.length - 1;i >= 0; i--) {
|
|
981
|
+
const key = localStorage.key(i);
|
|
982
|
+
if (key?.startsWith("es-sso-user")) {
|
|
983
|
+
localStorage.removeItem(key);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
for (let i = sessionStorage.length - 1;i >= 0; i--) {
|
|
987
|
+
const key = sessionStorage.key(i);
|
|
988
|
+
if (key?.startsWith("es-sso-user")) {
|
|
989
|
+
sessionStorage.removeItem(key);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
window.dispatchEvent(new CustomEvent("es-sso-logout"));
|
|
993
|
+
}
|
|
994
|
+
return { success: true };
|
|
995
|
+
} catch (error) {
|
|
996
|
+
return {
|
|
997
|
+
success: false,
|
|
998
|
+
error: error instanceof Error ? error.message : "Network error"
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
885
1002
|
|
|
886
1003
|
// src/index.ts
|
|
887
1004
|
async function enterpriseStandard(appId, appKey, initConfig) {
|
|
@@ -927,6 +1044,7 @@ export {
|
|
|
927
1044
|
useUser,
|
|
928
1045
|
useToken,
|
|
929
1046
|
oidcCallbackSchema,
|
|
1047
|
+
logout,
|
|
930
1048
|
initiateLogin,
|
|
931
1049
|
handler,
|
|
932
1050
|
getUser,
|
package/dist/sso.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ export type SSOConfig = {
|
|
|
7
7
|
redirect_uri: string;
|
|
8
8
|
response_type: string;
|
|
9
9
|
scope: string;
|
|
10
|
-
post_logout_redirect_uri?: string;
|
|
11
10
|
silent_redirect_uri?: string;
|
|
12
11
|
jwks_uri?: string;
|
|
13
12
|
cookies_prefix?: string;
|
|
14
13
|
cookies_path?: string;
|
|
15
14
|
cookies_secure?: boolean;
|
|
16
15
|
cookies_same_site?: 'Strict' | 'Lax';
|
|
16
|
+
end_session_endpoint?: string;
|
|
17
17
|
};
|
|
18
18
|
export type ESConfig = {
|
|
19
19
|
es?: EnterpriseStandard;
|
|
@@ -30,12 +30,15 @@ export type SSOHandlerConfig = {
|
|
|
30
30
|
tokenUrl?: string;
|
|
31
31
|
refreshUrl?: string;
|
|
32
32
|
jwksUrl?: string;
|
|
33
|
+
logoutUrl?: string;
|
|
34
|
+
logoutCallbackUrl?: string;
|
|
33
35
|
} & ESConfig;
|
|
34
36
|
export type SSO = {
|
|
35
37
|
getUser: (request: Request) => Promise<EnterpriseUser | undefined>;
|
|
36
38
|
getRequiredUser: (request: Request) => Promise<EnterpriseUser>;
|
|
37
39
|
getJwt: (request: Request) => Promise<string | undefined>;
|
|
38
40
|
initiateLogin: (config: LoginConfig) => Promise<Response>;
|
|
41
|
+
logout: (request: Request, config?: LoginConfig) => Promise<Response>;
|
|
39
42
|
callbackHandler: (request: Request) => Promise<Response>;
|
|
40
43
|
handler: (request: Request, handlerConfig?: SSOHandlerConfig) => Promise<Response>;
|
|
41
44
|
};
|