@darajs/core 1.22.4 → 1.23.0

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.
@@ -3,4 +3,7 @@ export * from './auth';
3
3
  export { default as BasicAuthLogin } from './basic/basic-auth-login';
4
4
  export { default as BasicAuthLogout } from './basic/basic-auth-logout';
5
5
  export { default as DefaultAuthLogin } from './default/default-auth-login';
6
+ export { default as OIDCAuthLogin } from './oidc/oidc-login';
7
+ export { default as OIDCAuthLogout } from './oidc/oidc-logout';
8
+ export { default as OIDCAuthSSOCallback } from './oidc/sso-callback';
6
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../js/auth/index.tsx"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../js/auth/index.tsx"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -3,4 +3,7 @@ export * from './auth';
3
3
  export { default as BasicAuthLogin } from './basic/basic-auth-login';
4
4
  export { default as BasicAuthLogout } from './basic/basic-auth-logout';
5
5
  export { default as DefaultAuthLogin } from './default/default-auth-login';
6
+ export { default as OIDCAuthLogin } from './oidc/oidc-login';
7
+ export { default as OIDCAuthLogout } from './oidc/oidc-logout';
8
+ export { default as OIDCAuthSSOCallback } from './oidc/sso-callback';
6
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../js/auth/index.tsx"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../js/auth/index.tsx"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The Login component gets the username and password from the user and generates a session token.
3
+ */
4
+ declare function OIDCAuthLogin(): JSX.Element;
5
+ export default OIDCAuthLogin;
6
+ //# sourceMappingURL=oidc-login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-login.d.ts","sourceRoot":"","sources":["../../../js/auth/oidc/oidc-login.tsx"],"names":[],"mappings":"AAaA;;GAEG;AACH,iBAAS,aAAa,IAAI,GAAG,CAAC,OAAO,CAmEpC;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,82 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { useCallback, useEffect, useMemo } from 'react';
12
+ import { useLocation, useNavigate } from 'react-router';
13
+ import { HTTP_METHOD } from '@darajs/ui-utils';
14
+ import { request } from '../../api/http';
15
+ import DefaultFallback from '../../components/fallback/default';
16
+ import { useRouterContext } from '../../router/context';
17
+ import Center from '../../shared/center/center';
18
+ import { handleAuthErrors, verifySessionToken } from '../auth';
19
+ import { useSessionToken } from '../use-session-token';
20
+ /**
21
+ * The Login component gets the username and password from the user and generates a session token.
22
+ */
23
+ function OIDCAuthLogin() {
24
+ const navigate = useNavigate();
25
+ const location = useLocation();
26
+ const token = useSessionToken();
27
+ const { defaultPath } = useRouterContext();
28
+ const previousLocation = useMemo(() => {
29
+ var _a;
30
+ const queryParams = new URLSearchParams(location.search);
31
+ return (_a = queryParams.get('referrer')) !== null && _a !== void 0 ? _a : defaultPath;
32
+ }, [location, defaultPath]);
33
+ /**
34
+ * Verify existing token
35
+ */
36
+ const verifyToken = useCallback(() => __awaiter(this, void 0, void 0, function* () {
37
+ // send a call to backend to check the token (token will be automatically sent in the headers)
38
+ const verified = yield verifySessionToken();
39
+ // token is valid, redirect back
40
+ if (verified) {
41
+ navigate(decodeURIComponent(previousLocation), { replace: true });
42
+ }
43
+ else {
44
+ // not valid, go to logout to clear the token
45
+ navigate('/logout', { replace: true });
46
+ }
47
+ }), [previousLocation, navigate]);
48
+ /**
49
+ * Get new token
50
+ */
51
+ const getNewToken = useCallback(() => __awaiter(this, void 0, void 0, function* () {
52
+ const res = yield request('/api/auth/session', {
53
+ body: JSON.stringify({
54
+ redirect_to: previousLocation,
55
+ }),
56
+ method: HTTP_METHOD.POST,
57
+ });
58
+ // check for auth errors, redirecting to /error as needed
59
+ const loggedOut = yield handleAuthErrors(res, false);
60
+ if (loggedOut) {
61
+ return;
62
+ }
63
+ // Redirect to the SSO login page
64
+ // The redirect_uri already contains the state parameter with the encoded redirect URL
65
+ if (res.ok) {
66
+ const resContent = yield res.json();
67
+ window.location.href = resContent.redirect_uri;
68
+ }
69
+ }), [previousLocation]);
70
+ useEffect(() => {
71
+ // If we landed on this page with a token already, verify it
72
+ if (token) {
73
+ verifyToken();
74
+ }
75
+ else {
76
+ getNewToken();
77
+ }
78
+ }, [getNewToken, verifyToken, token]);
79
+ return (_jsx(Center, { children: _jsx(DefaultFallback, {}) }));
80
+ }
81
+ export default OIDCAuthLogin;
82
+ //# sourceMappingURL=oidc-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-login.js","sourceRoot":"","sources":["../../../js/auth/oidc/oidc-login.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Auth component that handles OIDC logout.
3
+ *
4
+ * If the IDP supports RP-Initiated Logout, redirects to the IDP's end_session_endpoint
5
+ * with post_logout_redirect_uri pointing back to /login.
6
+ *
7
+ * If the IDP doesn't support logout (server returns { success: true }), simply
8
+ * clears the local session and redirects to /login.
9
+ */
10
+ declare function OIDCAuthLogout(): JSX.Element;
11
+ export default OIDCAuthLogout;
12
+ //# sourceMappingURL=oidc-logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-logout.d.ts","sourceRoot":"","sources":["../../../js/auth/oidc/oidc-logout.tsx"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,iBAAS,cAAc,IAAI,GAAG,CAAC,OAAO,CA6BrC;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { useNavigate } from 'react-router';
4
+ import DefaultFallback from '../../components/fallback/default';
5
+ import Center from '../../shared/center/center';
6
+ import { revokeSession } from '../auth';
7
+ import { setSessionToken } from '../use-session-token';
8
+ /**
9
+ * Auth component that handles OIDC logout.
10
+ *
11
+ * If the IDP supports RP-Initiated Logout, redirects to the IDP's end_session_endpoint
12
+ * with post_logout_redirect_uri pointing back to /login.
13
+ *
14
+ * If the IDP doesn't support logout (server returns { success: true }), simply
15
+ * clears the local session and redirects to /login.
16
+ */
17
+ function OIDCAuthLogout() {
18
+ const navigate = useNavigate();
19
+ useEffect(() => {
20
+ revokeSession().then((responseData) => {
21
+ // Always clear the local session token
22
+ setSessionToken(null);
23
+ // Check if we got a redirect URL (IDP supports RP-Initiated Logout)
24
+ if (responseData && 'redirect_uri' in responseData) {
25
+ // Append the post_logout_redirect_uri to redirect back to /login after IDP logout
26
+ const loginUrl = new URL('/login', window.location.origin);
27
+ const finalRedirectUrl = new URL(responseData.redirect_uri);
28
+ finalRedirectUrl.searchParams.append('post_logout_redirect_uri', loginUrl.toString());
29
+ window.location.href = finalRedirectUrl.toString();
30
+ return;
31
+ }
32
+ // No redirect URL - IDP doesn't support logout, just go to login
33
+ navigate('/login');
34
+ });
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ }, []);
37
+ return (_jsx(Center, { children: _jsx(DefaultFallback, {}) }));
38
+ }
39
+ export default OIDCAuthLogout;
40
+ //# sourceMappingURL=oidc-logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-logout.js","sourceRoot":"","sources":["../../../js/auth/oidc/oidc-logout.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,eAAe,MAAM,+BAA+B,CAAC;AAC5D,OAAO,MAAM,MAAM,wBAAwB,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;GAQG;AACH,SAAS,cAAc;IACnB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,SAAS,CAAC,GAAG,EAAE;QACX,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE;YAClC,uCAAuC;YACvC,eAAe,CAAC,IAAI,CAAC,CAAC;YAEtB,oEAAoE;YACpE,IAAI,YAAY,IAAI,cAAc,IAAI,YAAY,EAAE,CAAC;gBACjD,kFAAkF;gBAClF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC3D,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC5D,gBAAgB,CAAC,YAAY,CAAC,MAAM,CAAC,0BAA0B,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACtF,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC;gBACnD,OAAO;YACX,CAAC;YAED,iEAAiE;YACjE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,uDAAuD;IAC3D,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACH,KAAC,MAAM,cACH,KAAC,eAAe,KAAG,GACd,CACZ,CAAC;AACN,CAAC;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Makes a call to /sso-callback and returns a new token
3
+ * Returns null if no token was returned (i.e. 403)
4
+ *
5
+ * @param search current search string
6
+ */
7
+ export declare function getSSOCallbackToken(search: string, defaultPath: string): Promise<{
8
+ token: string;
9
+ redirectTo: string;
10
+ } | null>;
11
+ declare function OIDCAuthSSOCallback(): JSX.Element;
12
+ export default OIDCAuthSSOCallback;
13
+ //# sourceMappingURL=sso-callback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sso-callback.d.ts","sourceRoot":"","sources":["../../../js/auth/oidc/sso-callback.tsx"],"names":[],"mappings":"AA0CA;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACrC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA8BvD;AAED,iBAAS,mBAAmB,IAAI,GAAG,CAAC,OAAO,CA0B1C;AAED,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,105 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { jwtDecode } from 'jwt-decode';
12
+ import { useEffect } from 'react';
13
+ import { useLocation, useNavigate } from 'react-router';
14
+ import { HTTP_METHOD } from '@darajs/ui-utils';
15
+ import { request } from '../../api/http';
16
+ import DefaultFallback from '../../components/fallback/default';
17
+ import { useRouterContext } from '../../router/context';
18
+ import Center from '../../shared/center/center';
19
+ import { handleAuthErrors } from '../auth';
20
+ import { setSessionToken } from '../use-session-token';
21
+ /**
22
+ * Decode the state parameter which is a JWT containing the redirect URL.
23
+ *
24
+ * @param state The state parameter from the callback URL
25
+ * @returns The redirect URL extracted from the state
26
+ */
27
+ function decodeStateRedirect(state) {
28
+ var _a;
29
+ if (!state) {
30
+ return null;
31
+ }
32
+ try {
33
+ const payload = jwtDecode(state);
34
+ return (_a = payload.redirect_to) !== null && _a !== void 0 ? _a : null;
35
+ }
36
+ catch (_b) {
37
+ // If decoding fails, try using the raw state as a URL (fallback for non-JWT states)
38
+ try {
39
+ return decodeURIComponent(state);
40
+ }
41
+ catch (_c) {
42
+ return null;
43
+ }
44
+ }
45
+ }
46
+ /**
47
+ * Makes a call to /sso-callback and returns a new token
48
+ * Returns null if no token was returned (i.e. 403)
49
+ *
50
+ * @param search current search string
51
+ */
52
+ export function getSSOCallbackToken(search, defaultPath) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ var _a;
55
+ try {
56
+ const params = new URLSearchParams(search);
57
+ const state = params.get('state');
58
+ const res = yield request('/api/auth/sso-callback', {
59
+ body: JSON.stringify({
60
+ auth_code: params.get('code'),
61
+ state,
62
+ }),
63
+ method: HTTP_METHOD.POST,
64
+ });
65
+ const shouldLogOut = yield handleAuthErrors(res);
66
+ if (shouldLogOut) {
67
+ return null;
68
+ }
69
+ if (res.ok) {
70
+ const { token } = yield res.json();
71
+ return {
72
+ token,
73
+ redirectTo: (_a = decodeStateRedirect(state)) !== null && _a !== void 0 ? _a : defaultPath,
74
+ };
75
+ }
76
+ throw new Error(`${res.status}: ${res.statusText}`);
77
+ }
78
+ catch (_b) {
79
+ return null;
80
+ }
81
+ });
82
+ }
83
+ function OIDCAuthSSOCallback() {
84
+ const { search } = useLocation();
85
+ const navigate = useNavigate();
86
+ const routerContext = useRouterContext();
87
+ useEffect(() => {
88
+ getSSOCallbackToken(search, routerContext.defaultPath)
89
+ .then((result) => {
90
+ if (result) {
91
+ setSessionToken(result.token);
92
+ navigate(result.redirectTo);
93
+ }
94
+ })
95
+ .catch((err) => {
96
+ // eslint-disable-next-line no-console
97
+ console.error('Failed to run SSO callback', err);
98
+ navigate('/logout');
99
+ });
100
+ // eslint-disable-next-line react-hooks/exhaustive-deps
101
+ }, []);
102
+ return (_jsx(Center, { children: _jsx(DefaultFallback, {}) }));
103
+ }
104
+ export default OIDCAuthSSOCallback;
105
+ //# sourceMappingURL=sso-callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sso-callback.js","sourceRoot":"","sources":["../../../js/auth/oidc/sso-callback.tsx"],"names":[],"mappings":"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"}
@@ -8,8 +8,4 @@ export interface UserData {
8
8
  identity_id?: string;
9
9
  identity_name: string;
10
10
  }
11
- export declare enum AuthType {
12
- BASIC = "BASIC",
13
- SSO = "SSO"
14
- }
15
11
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../js/types/auth.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,oBAAY,QAAQ;IAChB,KAAK,UAAU;IACf,GAAG,QAAQ;CACd"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../js/types/auth.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACzB"}
@@ -1,6 +1 @@
1
- export var AuthType;
2
- (function (AuthType) {
3
- AuthType["BASIC"] = "BASIC";
4
- AuthType["SSO"] = "SSO";
5
- })(AuthType || (AuthType = {}));
6
1
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../js/types/auth.tsx"],"names":[],"mappings":"AAYA,MAAM,CAAN,IAAY,QAGX;AAHD,WAAY,QAAQ;IAChB,2BAAe,CAAA;IACf,uBAAW,CAAA;AACf,CAAC,EAHW,QAAQ,KAAR,QAAQ,QAGnB"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../js/types/auth.tsx"],"names":[],"mappings":""}
@@ -40389,11 +40389,6 @@ You must set sticky: 'left' | 'right' for the '${bugWithUnderColumnsSticky.Heade
40389
40389
  const mergedInits = React$1.useMemo(() => mergeRequestInits(parentOptions, options), [parentOptions, options]);
40390
40390
  return /* @__PURE__ */ React.createElement(requestExtrasCtx.Provider, { value: { options: mergedInits } }, children);
40391
40391
  }
40392
- var AuthType = /* @__PURE__ */ ((AuthType2) => {
40393
- AuthType2["BASIC"] = "BASIC";
40394
- AuthType2["SSO"] = "SSO";
40395
- return AuthType2;
40396
- })(AuthType || {});
40397
40392
  function $constructor(name, initializer2, params) {
40398
40393
  function init(inst, def) {
40399
40394
  var _a;
@@ -74361,6 +74356,178 @@ Inferred class string: "${iconClasses}."`
74361
74356
  }, []);
74362
74357
  return /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(DefaultFallback$1, null));
74363
74358
  }
74359
+ function OIDCAuthLogin() {
74360
+ const navigate = useNavigate();
74361
+ const location2 = useLocation();
74362
+ const token = useSessionToken();
74363
+ const { defaultPath } = useRouterContext();
74364
+ const previousLocation = React$1.useMemo(() => {
74365
+ const queryParams = new URLSearchParams(location2.search);
74366
+ return queryParams.get("referrer") ?? defaultPath;
74367
+ }, [location2, defaultPath]);
74368
+ const verifyToken = React$1.useCallback(async () => {
74369
+ const verified = await verifySessionToken();
74370
+ if (verified) {
74371
+ navigate(decodeURIComponent(previousLocation), { replace: true });
74372
+ } else {
74373
+ navigate("/logout", { replace: true });
74374
+ }
74375
+ }, [previousLocation, navigate]);
74376
+ const getNewToken = React$1.useCallback(async () => {
74377
+ const res = await request("/api/auth/session", {
74378
+ body: JSON.stringify({
74379
+ redirect_to: previousLocation
74380
+ }),
74381
+ method: HTTP_METHOD.POST
74382
+ });
74383
+ const loggedOut = await handleAuthErrors(res, false);
74384
+ if (loggedOut) {
74385
+ return;
74386
+ }
74387
+ if (res.ok) {
74388
+ const resContent = await res.json();
74389
+ window.location.href = resContent.redirect_uri;
74390
+ }
74391
+ }, [previousLocation]);
74392
+ React$1.useEffect(() => {
74393
+ if (token) {
74394
+ verifyToken();
74395
+ } else {
74396
+ getNewToken();
74397
+ }
74398
+ }, [getNewToken, verifyToken, token]);
74399
+ return /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(DefaultFallback$1, null));
74400
+ }
74401
+ function OIDCAuthLogout() {
74402
+ const navigate = useNavigate();
74403
+ React$1.useEffect(() => {
74404
+ revokeSession().then((responseData) => {
74405
+ setSessionToken(null);
74406
+ if (responseData && "redirect_uri" in responseData) {
74407
+ const loginUrl = new URL("/login", window.location.origin);
74408
+ const finalRedirectUrl = new URL(responseData.redirect_uri);
74409
+ finalRedirectUrl.searchParams.append("post_logout_redirect_uri", loginUrl.toString());
74410
+ window.location.href = finalRedirectUrl.toString();
74411
+ return;
74412
+ }
74413
+ navigate("/login");
74414
+ });
74415
+ }, []);
74416
+ return /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(DefaultFallback$1, null));
74417
+ }
74418
+ class InvalidTokenError extends Error {
74419
+ }
74420
+ InvalidTokenError.prototype.name = "InvalidTokenError";
74421
+ function b64DecodeUnicode(str) {
74422
+ return decodeURIComponent(atob(str).replace(/(.)/g, (m, p2) => {
74423
+ let code = p2.charCodeAt(0).toString(16).toUpperCase();
74424
+ if (code.length < 2) {
74425
+ code = "0" + code;
74426
+ }
74427
+ return "%" + code;
74428
+ }));
74429
+ }
74430
+ function base64UrlDecode(str) {
74431
+ let output = str.replace(/-/g, "+").replace(/_/g, "/");
74432
+ switch (output.length % 4) {
74433
+ case 0:
74434
+ break;
74435
+ case 2:
74436
+ output += "==";
74437
+ break;
74438
+ case 3:
74439
+ output += "=";
74440
+ break;
74441
+ default:
74442
+ throw new Error("base64 string is not of the correct length");
74443
+ }
74444
+ try {
74445
+ return b64DecodeUnicode(output);
74446
+ } catch (err2) {
74447
+ return atob(output);
74448
+ }
74449
+ }
74450
+ function jwtDecode(token, options) {
74451
+ if (typeof token !== "string") {
74452
+ throw new InvalidTokenError("Invalid token specified: must be a string");
74453
+ }
74454
+ options || (options = {});
74455
+ const pos = options.header === true ? 0 : 1;
74456
+ const part = token.split(".")[pos];
74457
+ if (typeof part !== "string") {
74458
+ throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);
74459
+ }
74460
+ let decoded;
74461
+ try {
74462
+ decoded = base64UrlDecode(part);
74463
+ } catch (e2) {
74464
+ throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e2.message})`);
74465
+ }
74466
+ try {
74467
+ return JSON.parse(decoded);
74468
+ } catch (e2) {
74469
+ throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e2.message})`);
74470
+ }
74471
+ }
74472
+ function decodeStateRedirect(state) {
74473
+ if (!state) {
74474
+ return null;
74475
+ }
74476
+ try {
74477
+ const payload = jwtDecode(state);
74478
+ return payload.redirect_to ?? null;
74479
+ } catch {
74480
+ try {
74481
+ return decodeURIComponent(state);
74482
+ } catch {
74483
+ return null;
74484
+ }
74485
+ }
74486
+ }
74487
+ async function getSSOCallbackToken(search, defaultPath) {
74488
+ try {
74489
+ const params = new URLSearchParams(search);
74490
+ const state = params.get("state");
74491
+ const res = await request("/api/auth/sso-callback", {
74492
+ body: JSON.stringify({
74493
+ auth_code: params.get("code"),
74494
+ state
74495
+ }),
74496
+ method: HTTP_METHOD.POST
74497
+ });
74498
+ const shouldLogOut = await handleAuthErrors(res);
74499
+ if (shouldLogOut) {
74500
+ return null;
74501
+ }
74502
+ if (res.ok) {
74503
+ const { token } = await res.json();
74504
+ return {
74505
+ token,
74506
+ redirectTo: decodeStateRedirect(state) ?? defaultPath
74507
+ };
74508
+ }
74509
+ throw new Error(`${res.status}: ${res.statusText}`);
74510
+ } catch {
74511
+ return null;
74512
+ }
74513
+ }
74514
+ function OIDCAuthSSOCallback() {
74515
+ const { search } = useLocation();
74516
+ const navigate = useNavigate();
74517
+ const routerContext = useRouterContext();
74518
+ React$1.useEffect(() => {
74519
+ getSSOCallbackToken(search, routerContext.defaultPath).then((result) => {
74520
+ if (result) {
74521
+ setSessionToken(result.token);
74522
+ navigate(result.redirectTo);
74523
+ }
74524
+ }).catch((err2) => {
74525
+ console.error("Failed to run SSO callback", err2);
74526
+ navigate("/logout");
74527
+ });
74528
+ }, []);
74529
+ return /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(DefaultFallback$1, null));
74530
+ }
74364
74531
  const CenteredDivWithGap$1 = styled(Center)`
74365
74532
  gap: 1rem;
74366
74533
  margin: 10px;
@@ -98864,7 +99031,6 @@ body,
98864
99031
  return /* @__PURE__ */ React.createElement(DynamicComponent$1, { component });
98865
99032
  }
98866
99033
  exports.ActionImpl = ActionImpl;
98867
- exports.AuthType = AuthType;
98868
99034
  exports.AuthenticatedRoot = AuthenticatedRoot;
98869
99035
  exports.BasicAuthLogin = BasicAuthLogin;
98870
99036
  exports.BasicAuthLogout = BasicAuthLogout;
@@ -98897,6 +99063,9 @@ body,
98897
99063
  exports.NavigateTo = NavigateTo;
98898
99064
  exports.Notifications = index$1;
98899
99065
  exports.Notify = Notify;
99066
+ exports.OIDCAuthLogin = OIDCAuthLogin;
99067
+ exports.OIDCAuthLogout = OIDCAuthLogout;
99068
+ exports.OIDCAuthSSOCallback = OIDCAuthSSOCallback;
98900
99069
  exports.Outlet = Outlet;
98901
99070
  exports.PartialRequestExtrasProvider = PartialRequestExtrasProvider;
98902
99071
  exports.PoweredByCausalens = PoweredByCausalens;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darajs/core",
3
- "version": "1.22.4",
3
+ "version": "1.23.0",
4
4
  "description": "Dara Framework core",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -39,9 +39,9 @@
39
39
  "@babel/preset-env": "^7.23.0",
40
40
  "@babel/preset-react": "^7.22.15",
41
41
  "@babel/preset-typescript": "^7.23.0",
42
- "@darajs/eslint-config": "1.22.4",
43
- "@darajs/prettier-config": "1.22.4",
44
- "@darajs/stylelint-config": "1.22.4",
42
+ "@darajs/eslint-config": "1.23.0",
43
+ "@darajs/prettier-config": "1.23.0",
44
+ "@darajs/stylelint-config": "1.23.0",
45
45
  "@rollup/plugin-inject": "^4.0.4",
46
46
  "@testing-library/dom": "^9.3.0",
47
47
  "@testing-library/jest-dom": "^6.0.0",
@@ -75,10 +75,10 @@
75
75
  "whatwg-fetch": "^3.6.20"
76
76
  },
77
77
  "dependencies": {
78
- "@darajs/styled-components": "1.22.4",
79
- "@darajs/ui-components": "1.22.4",
80
- "@darajs/ui-notifications": "1.22.4",
81
- "@darajs/ui-utils": "1.22.4",
78
+ "@darajs/styled-components": "1.23.0",
79
+ "@darajs/ui-components": "1.23.0",
80
+ "@darajs/ui-notifications": "1.23.0",
81
+ "@darajs/ui-utils": "1.23.0",
82
82
  "@fortawesome/fontawesome-free": "~6.4.0",
83
83
  "@recoiljs/refine": "^0.1.1",
84
84
  "@tanstack/query-core": "^4.40.0",
@@ -87,6 +87,7 @@
87
87
  "exceljs": "^4.3.0",
88
88
  "fast-json-patch": "^3.1.1",
89
89
  "file-saver": "^2.0.5",
90
+ "jwt-decode": "^4.0.0",
90
91
  "lodash": "^4.17.21",
91
92
  "nanoid": "^3.3.0",
92
93
  "nprogress": "^0.2.0",
@@ -116,5 +117,5 @@
116
117
  "engines": {
117
118
  "node": ">=20.19.0"
118
119
  },
119
- "gitHead": "fa0e89c75ecd2a39bda5ca938239d069286f1e34"
120
+ "gitHead": "1dee57b6df63904db955f9abf4f984040baab0eb"
120
121
  }
@@ -1,7 +0,0 @@
1
- import * as React from 'react';
2
- /**
3
- * SSO Auth callback placeholder
4
- */
5
- declare function SSOCallbackPage(): React.ReactNode;
6
- export default SSOCallbackPage;
7
- //# sourceMappingURL=sso-callback-page.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sso-callback-page.d.ts","sourceRoot":"","sources":["../../js/pages/sso-callback-page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;GAEG;AACH,iBAAS,eAAe,IAAI,KAAK,CAAC,SAAS,CAE1C;AAED,eAAe,eAAe,CAAC"}
@@ -1,9 +0,0 @@
1
- import * as React from 'react';
2
- /**
3
- * SSO Auth callback placeholder
4
- */
5
- function SSOCallbackPage() {
6
- return null;
7
- }
8
- export default SSOCallbackPage;
9
- //# sourceMappingURL=sso-callback-page.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sso-callback-page.js","sourceRoot":"","sources":["../../js/pages/sso-callback-page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;GAEG;AACH,SAAS,eAAe;IACpB,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,eAAe,eAAe,CAAC"}