@burdenoff/microfe-auth 2026.510.127

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.
Files changed (301) hide show
  1. package/README.md +12 -0
  2. package/dist/_virtual/_rolldown/runtime.js +13 -0
  3. package/dist/auth/AuthRoot.d.ts +30 -0
  4. package/dist/auth/AuthRoot.d.ts.map +1 -0
  5. package/dist/auth/AuthRoot.js +82 -0
  6. package/dist/auth/AuthRoot.js.map +1 -0
  7. package/dist/auth/AuthRoutes.d.ts +29 -0
  8. package/dist/auth/AuthRoutes.d.ts.map +1 -0
  9. package/dist/auth/AuthRoutes.js +271 -0
  10. package/dist/auth/AuthRoutes.js.map +1 -0
  11. package/dist/auth/components/AuthIcons.d.ts +17 -0
  12. package/dist/auth/components/AuthIcons.d.ts.map +1 -0
  13. package/dist/auth/components/AuthIcons.js +197 -0
  14. package/dist/auth/components/AuthIcons.js.map +1 -0
  15. package/dist/auth/components/AuthLayout.d.ts +17 -0
  16. package/dist/auth/components/AuthLayout.d.ts.map +1 -0
  17. package/dist/auth/components/AuthLayout.js +237 -0
  18. package/dist/auth/components/AuthLayout.js.map +1 -0
  19. package/dist/auth/components/CaptchaV2.d.ts +16 -0
  20. package/dist/auth/components/CaptchaV2.d.ts.map +1 -0
  21. package/dist/auth/components/CaptchaV2.js +47 -0
  22. package/dist/auth/components/CaptchaV2.js.map +1 -0
  23. package/dist/auth/components/ConfirmActionDialog.d.ts +16 -0
  24. package/dist/auth/components/ConfirmActionDialog.d.ts.map +1 -0
  25. package/dist/auth/components/ConfirmActionDialog.js +68 -0
  26. package/dist/auth/components/ConfirmActionDialog.js.map +1 -0
  27. package/dist/auth/components/index.d.ts +4 -0
  28. package/dist/auth/components/index.d.ts.map +1 -0
  29. package/dist/auth/components/profile/UserProfileMenu.d.ts +42 -0
  30. package/dist/auth/components/profile/UserProfileMenu.d.ts.map +1 -0
  31. package/dist/auth/components/profile/UserProfileMenu.js +91 -0
  32. package/dist/auth/components/profile/UserProfileMenu.js.map +1 -0
  33. package/dist/auth/components/workspace/WorkspaceSelector.d.ts +76 -0
  34. package/dist/auth/components/workspace/WorkspaceSelector.d.ts.map +1 -0
  35. package/dist/auth/components/workspace/WorkspaceSelector.js +240 -0
  36. package/dist/auth/components/workspace/WorkspaceSelector.js.map +1 -0
  37. package/dist/auth/constants/permissions.d.ts +30 -0
  38. package/dist/auth/constants/permissions.d.ts.map +1 -0
  39. package/dist/auth/constants/permissions.js +18 -0
  40. package/dist/auth/constants/permissions.js.map +1 -0
  41. package/dist/auth/constants/sessionKeys.d.ts +18 -0
  42. package/dist/auth/constants/sessionKeys.d.ts.map +1 -0
  43. package/dist/auth/constants/sessionKeys.js +6 -0
  44. package/dist/auth/constants/sessionKeys.js.map +1 -0
  45. package/dist/auth/hooks/index.d.ts +18 -0
  46. package/dist/auth/hooks/index.d.ts.map +1 -0
  47. package/dist/auth/hooks/index.js +16 -0
  48. package/dist/auth/hooks/useAccountOperations.d.ts +19 -0
  49. package/dist/auth/hooks/useAccountOperations.d.ts.map +1 -0
  50. package/dist/auth/hooks/useAccountOperations.js +52 -0
  51. package/dist/auth/hooks/useAccountOperations.js.map +1 -0
  52. package/dist/auth/hooks/useApiKeyOperations.d.ts +22 -0
  53. package/dist/auth/hooks/useApiKeyOperations.d.ts.map +1 -0
  54. package/dist/auth/hooks/useApiKeyOperations.js +4 -0
  55. package/dist/auth/hooks/useAppOperations.d.ts +26 -0
  56. package/dist/auth/hooks/useAppOperations.d.ts.map +1 -0
  57. package/dist/auth/hooks/useAppOperations.js +4 -0
  58. package/dist/auth/hooks/useAuthOperations.d.ts +57 -0
  59. package/dist/auth/hooks/useAuthOperations.d.ts.map +1 -0
  60. package/dist/auth/hooks/useAuthOperations.js +236 -0
  61. package/dist/auth/hooks/useAuthOperations.js.map +1 -0
  62. package/dist/auth/hooks/useAuthPermissions.d.ts +20 -0
  63. package/dist/auth/hooks/useAuthPermissions.d.ts.map +1 -0
  64. package/dist/auth/hooks/useAuthPermissions.js +22 -0
  65. package/dist/auth/hooks/useAuthPermissions.js.map +1 -0
  66. package/dist/auth/hooks/useCaptchaV3.d.ts +13 -0
  67. package/dist/auth/hooks/useCaptchaV3.d.ts.map +1 -0
  68. package/dist/auth/hooks/useCaptchaV3.js +19 -0
  69. package/dist/auth/hooks/useCaptchaV3.js.map +1 -0
  70. package/dist/auth/hooks/useContextSwitcherData.d.ts +106 -0
  71. package/dist/auth/hooks/useContextSwitcherData.d.ts.map +1 -0
  72. package/dist/auth/hooks/useContextSwitcherData.js +466 -0
  73. package/dist/auth/hooks/useContextSwitcherData.js.map +1 -0
  74. package/dist/auth/hooks/useDelegationOperations.d.ts +25 -0
  75. package/dist/auth/hooks/useDelegationOperations.d.ts.map +1 -0
  76. package/dist/auth/hooks/useDelegationOperations.js +4 -0
  77. package/dist/auth/hooks/useMfaOperations.d.ts +18 -0
  78. package/dist/auth/hooks/useMfaOperations.d.ts.map +1 -0
  79. package/dist/auth/hooks/useMfaOperations.js +103 -0
  80. package/dist/auth/hooks/useMfaOperations.js.map +1 -0
  81. package/dist/auth/hooks/useMyWorkspaces.d.ts +45 -0
  82. package/dist/auth/hooks/useMyWorkspaces.d.ts.map +1 -0
  83. package/dist/auth/hooks/useMyWorkspaces.js +140 -0
  84. package/dist/auth/hooks/useMyWorkspaces.js.map +1 -0
  85. package/dist/auth/hooks/useOAuthOperations.d.ts +19 -0
  86. package/dist/auth/hooks/useOAuthOperations.d.ts.map +1 -0
  87. package/dist/auth/hooks/useOAuthOperations.js +103 -0
  88. package/dist/auth/hooks/useOAuthOperations.js.map +1 -0
  89. package/dist/auth/hooks/usePasswordOperations.d.ts +13 -0
  90. package/dist/auth/hooks/usePasswordOperations.d.ts.map +1 -0
  91. package/dist/auth/hooks/usePasswordOperations.js +56 -0
  92. package/dist/auth/hooks/usePasswordOperations.js.map +1 -0
  93. package/dist/auth/hooks/useSessionOperations.d.ts +41 -0
  94. package/dist/auth/hooks/useSessionOperations.d.ts.map +1 -0
  95. package/dist/auth/hooks/useSessionOperations.js +59 -0
  96. package/dist/auth/hooks/useSessionOperations.js.map +1 -0
  97. package/dist/auth/hooks/useSsoOperations.d.ts +65 -0
  98. package/dist/auth/hooks/useSsoOperations.d.ts.map +1 -0
  99. package/dist/auth/hooks/useSsoOperations.js +236 -0
  100. package/dist/auth/hooks/useSsoOperations.js.map +1 -0
  101. package/dist/auth/hooks/useTokenRefresh.d.ts +56 -0
  102. package/dist/auth/hooks/useTokenRefresh.d.ts.map +1 -0
  103. package/dist/auth/hooks/useTokenRefresh.js +53 -0
  104. package/dist/auth/hooks/useTokenRefresh.js.map +1 -0
  105. package/dist/auth/hooks/useUserOperations.d.ts +32 -0
  106. package/dist/auth/hooks/useUserOperations.d.ts.map +1 -0
  107. package/dist/auth/hooks/useUserOperations.js +100 -0
  108. package/dist/auth/hooks/useUserOperations.js.map +1 -0
  109. package/dist/auth/hooks/useWorkspaceOperations.d.ts +35 -0
  110. package/dist/auth/hooks/useWorkspaceOperations.d.ts.map +1 -0
  111. package/dist/auth/hooks/useWorkspaceOperations.js +35 -0
  112. package/dist/auth/hooks/useWorkspaceOperations.js.map +1 -0
  113. package/dist/auth/hooks/useWorkspaceToken.d.ts +56 -0
  114. package/dist/auth/hooks/useWorkspaceToken.d.ts.map +1 -0
  115. package/dist/auth/hooks/useWorkspaceToken.js +94 -0
  116. package/dist/auth/hooks/useWorkspaceToken.js.map +1 -0
  117. package/dist/auth/index.d.ts +63 -0
  118. package/dist/auth/index.d.ts.map +1 -0
  119. package/dist/auth/index.js +18 -0
  120. package/dist/auth/pages/ApiKeysPage.d.ts +5 -0
  121. package/dist/auth/pages/ApiKeysPage.d.ts.map +1 -0
  122. package/dist/auth/pages/AppsPage.d.ts +5 -0
  123. package/dist/auth/pages/AppsPage.d.ts.map +1 -0
  124. package/dist/auth/pages/AuditLogPage.d.ts +5 -0
  125. package/dist/auth/pages/AuditLogPage.d.ts.map +1 -0
  126. package/dist/auth/pages/AuditLogPage.js +129 -0
  127. package/dist/auth/pages/AuditLogPage.js.map +1 -0
  128. package/dist/auth/pages/DelegationsPage.d.ts +5 -0
  129. package/dist/auth/pages/DelegationsPage.d.ts.map +1 -0
  130. package/dist/auth/pages/EmailVerifyPage.d.ts +5 -0
  131. package/dist/auth/pages/EmailVerifyPage.d.ts.map +1 -0
  132. package/dist/auth/pages/EmailVerifyPage.js +166 -0
  133. package/dist/auth/pages/EmailVerifyPage.js.map +1 -0
  134. package/dist/auth/pages/LoginPage.d.ts +6 -0
  135. package/dist/auth/pages/LoginPage.d.ts.map +1 -0
  136. package/dist/auth/pages/LoginPage.js +575 -0
  137. package/dist/auth/pages/LoginPage.js.map +1 -0
  138. package/dist/auth/pages/MagicLinkPage.d.ts +6 -0
  139. package/dist/auth/pages/MagicLinkPage.d.ts.map +1 -0
  140. package/dist/auth/pages/MagicLinkPage.js +219 -0
  141. package/dist/auth/pages/MagicLinkPage.js.map +1 -0
  142. package/dist/auth/pages/MfaSetupPage.d.ts +5 -0
  143. package/dist/auth/pages/MfaSetupPage.d.ts.map +1 -0
  144. package/dist/auth/pages/MfaSetupPage.js +341 -0
  145. package/dist/auth/pages/MfaSetupPage.js.map +1 -0
  146. package/dist/auth/pages/MfaVerifyPage.d.ts +7 -0
  147. package/dist/auth/pages/MfaVerifyPage.d.ts.map +1 -0
  148. package/dist/auth/pages/MfaVerifyPage.js +189 -0
  149. package/dist/auth/pages/MfaVerifyPage.js.map +1 -0
  150. package/dist/auth/pages/OAuthCallbackPage.d.ts +7 -0
  151. package/dist/auth/pages/OAuthCallbackPage.d.ts.map +1 -0
  152. package/dist/auth/pages/OAuthCallbackPage.js +100 -0
  153. package/dist/auth/pages/OAuthCallbackPage.js.map +1 -0
  154. package/dist/auth/pages/PasswordResetPage.d.ts +6 -0
  155. package/dist/auth/pages/PasswordResetPage.d.ts.map +1 -0
  156. package/dist/auth/pages/PasswordResetPage.js +352 -0
  157. package/dist/auth/pages/PasswordResetPage.js.map +1 -0
  158. package/dist/auth/pages/ReactivatePage.d.ts +6 -0
  159. package/dist/auth/pages/ReactivatePage.d.ts.map +1 -0
  160. package/dist/auth/pages/ReactivatePage.js +217 -0
  161. package/dist/auth/pages/ReactivatePage.js.map +1 -0
  162. package/dist/auth/pages/RegisterPage.d.ts +5 -0
  163. package/dist/auth/pages/RegisterPage.d.ts.map +1 -0
  164. package/dist/auth/pages/RegisterPage.js +439 -0
  165. package/dist/auth/pages/RegisterPage.js.map +1 -0
  166. package/dist/auth/pages/SSORelayCallbackPage.d.ts +8 -0
  167. package/dist/auth/pages/SSORelayCallbackPage.d.ts.map +1 -0
  168. package/dist/auth/pages/SSORelayCallbackPage.js +48 -0
  169. package/dist/auth/pages/SSORelayCallbackPage.js.map +1 -0
  170. package/dist/auth/pages/SSORelayPage.d.ts +18 -0
  171. package/dist/auth/pages/SSORelayPage.d.ts.map +1 -0
  172. package/dist/auth/pages/SSORelayPage.js +134 -0
  173. package/dist/auth/pages/SSORelayPage.js.map +1 -0
  174. package/dist/auth/pages/SecurityPage.d.ts +5 -0
  175. package/dist/auth/pages/SecurityPage.d.ts.map +1 -0
  176. package/dist/auth/pages/SecurityPage.js +587 -0
  177. package/dist/auth/pages/SecurityPage.js.map +1 -0
  178. package/dist/auth/pages/SessionBridgePage.d.ts +14 -0
  179. package/dist/auth/pages/SessionBridgePage.d.ts.map +1 -0
  180. package/dist/auth/pages/SessionBridgePage.js +231 -0
  181. package/dist/auth/pages/SessionBridgePage.js.map +1 -0
  182. package/dist/auth/pages/SessionsPage.d.ts +5 -0
  183. package/dist/auth/pages/SessionsPage.d.ts.map +1 -0
  184. package/dist/auth/pages/SessionsPage.js +258 -0
  185. package/dist/auth/pages/SessionsPage.js.map +1 -0
  186. package/dist/auth/pages/SsoCallbackPage.d.ts +8 -0
  187. package/dist/auth/pages/SsoCallbackPage.d.ts.map +1 -0
  188. package/dist/auth/pages/SsoCallbackPage.js +188 -0
  189. package/dist/auth/pages/SsoCallbackPage.js.map +1 -0
  190. package/dist/auth/pages/SsoConfigPage.d.ts +6 -0
  191. package/dist/auth/pages/SsoConfigPage.d.ts.map +1 -0
  192. package/dist/auth/pages/SsoConfigPage.js +1144 -0
  193. package/dist/auth/pages/SsoConfigPage.js.map +1 -0
  194. package/dist/auth/pages/SsoLoginPage.d.ts +7 -0
  195. package/dist/auth/pages/SsoLoginPage.d.ts.map +1 -0
  196. package/dist/auth/pages/SsoLoginPage.js +236 -0
  197. package/dist/auth/pages/SsoLoginPage.js.map +1 -0
  198. package/dist/auth/pages/UserDetailsPage.d.ts +11 -0
  199. package/dist/auth/pages/UserDetailsPage.d.ts.map +1 -0
  200. package/dist/auth/pages/UserDetailsPage.js +338 -0
  201. package/dist/auth/pages/UserDetailsPage.js.map +1 -0
  202. package/dist/auth/pages/UserProfilePage.d.ts +5 -0
  203. package/dist/auth/pages/UserProfilePage.d.ts.map +1 -0
  204. package/dist/auth/pages/UserProfilePage.js +445 -0
  205. package/dist/auth/pages/UserProfilePage.js.map +1 -0
  206. package/dist/auth/pages/UsersPage.d.ts +5 -0
  207. package/dist/auth/pages/UsersPage.d.ts.map +1 -0
  208. package/dist/auth/pages/UsersPage.js +899 -0
  209. package/dist/auth/pages/UsersPage.js.map +1 -0
  210. package/dist/auth/providers/AuthProvider.d.ts +18 -0
  211. package/dist/auth/providers/AuthProvider.d.ts.map +1 -0
  212. package/dist/auth/providers/AuthProvider.js +36 -0
  213. package/dist/auth/providers/AuthProvider.js.map +1 -0
  214. package/dist/auth/providers/CaptchaProvider.d.ts +13 -0
  215. package/dist/auth/providers/CaptchaProvider.d.ts.map +1 -0
  216. package/dist/auth/providers/CaptchaProvider.js +21 -0
  217. package/dist/auth/providers/CaptchaProvider.js.map +1 -0
  218. package/dist/auth/store/authStore.d.ts +91 -0
  219. package/dist/auth/store/authStore.d.ts.map +1 -0
  220. package/dist/auth/store/authStore.js +314 -0
  221. package/dist/auth/store/authStore.js.map +1 -0
  222. package/dist/auth/types/index.d.ts +636 -0
  223. package/dist/auth/types/index.d.ts.map +1 -0
  224. package/dist/auth/utils/captchaConfig.d.ts +4 -0
  225. package/dist/auth/utils/captchaConfig.d.ts.map +1 -0
  226. package/dist/auth/utils/captchaConfig.js +13 -0
  227. package/dist/auth/utils/captchaConfig.js.map +1 -0
  228. package/dist/auth/utils/formatters.d.ts +37 -0
  229. package/dist/auth/utils/formatters.d.ts.map +1 -0
  230. package/dist/auth/utils/formatters.js +48 -0
  231. package/dist/auth/utils/formatters.js.map +1 -0
  232. package/dist/auth/utils/gatewayBaseUrls.d.ts +6 -0
  233. package/dist/auth/utils/gatewayBaseUrls.d.ts.map +1 -0
  234. package/dist/auth/utils/gatewayBaseUrls.js +18 -0
  235. package/dist/auth/utils/gatewayBaseUrls.js.map +1 -0
  236. package/dist/auth/utils/index.d.ts +3 -0
  237. package/dist/auth/utils/index.d.ts.map +1 -0
  238. package/dist/auth/utils/validation.d.ts +30 -0
  239. package/dist/auth/utils/validation.d.ts.map +1 -0
  240. package/dist/auth/utils/validation.js +15 -0
  241. package/dist/auth/utils/validation.js.map +1 -0
  242. package/dist/dev/main.d.ts +2 -0
  243. package/dist/dev/main.d.ts.map +1 -0
  244. package/dist/generated/global-operations.d.ts +2978 -0
  245. package/dist/generated/global-operations.d.ts.map +1 -0
  246. package/dist/generated/global-operations.js +944 -0
  247. package/dist/generated/global-operations.js.map +1 -0
  248. package/dist/generated/global-types.d.ts +21253 -0
  249. package/dist/generated/global-types.d.ts.map +1 -0
  250. package/dist/generated/wspace-operations.d.ts +2 -0
  251. package/dist/generated/wspace-operations.d.ts.map +1 -0
  252. package/dist/generated/wspace-types.d.ts +55214 -0
  253. package/dist/generated/wspace-types.d.ts.map +1 -0
  254. package/dist/index.d.ts +4 -0
  255. package/dist/index.d.ts.map +1 -0
  256. package/dist/index.js +20 -0
  257. package/dist/microfe-auth.css +3 -0
  258. package/dist/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js +70 -0
  259. package/dist/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js.map +1 -0
  260. package/dist/node_modules/object-assign/index.js +41 -0
  261. package/dist/node_modules/object-assign/index.js.map +1 -0
  262. package/dist/node_modules/prop-types/checkPropTypes.js +46 -0
  263. package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -0
  264. package/dist/node_modules/prop-types/factoryWithThrowingShims.js +49 -0
  265. package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -0
  266. package/dist/node_modules/prop-types/factoryWithTypeCheckers.js +272 -0
  267. package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -0
  268. package/dist/node_modules/prop-types/index.js +16 -0
  269. package/dist/node_modules/prop-types/index.js.map +1 -0
  270. package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js +10 -0
  271. package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -0
  272. package/dist/node_modules/prop-types/lib/has.js +10 -0
  273. package/dist/node_modules/prop-types/lib/has.js.map +1 -0
  274. package/dist/node_modules/qrcode.react/lib/esm/index.js +959 -0
  275. package/dist/node_modules/qrcode.react/lib/esm/index.js.map +1 -0
  276. package/dist/node_modules/react-async-script/lib/esm/async-script-loader.js +114 -0
  277. package/dist/node_modules/react-async-script/lib/esm/async-script-loader.js.map +1 -0
  278. package/dist/node_modules/react-google-recaptcha/lib/esm/index.js +8 -0
  279. package/dist/node_modules/react-google-recaptcha/lib/esm/index.js.map +1 -0
  280. package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha-wrapper.js +20 -0
  281. package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha-wrapper.js.map +1 -0
  282. package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha.js +148 -0
  283. package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha.js.map +1 -0
  284. package/dist/node_modules/react-google-recaptcha-v3/dist/react-google-recaptcha-v3.esm.js +445 -0
  285. package/dist/node_modules/react-google-recaptcha-v3/dist/react-google-recaptcha-v3.esm.js.map +1 -0
  286. package/dist/node_modules/react-is/cjs/react-is.development.js +84 -0
  287. package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -0
  288. package/dist/node_modules/react-is/cjs/react-is.production.min.js +64 -0
  289. package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
  290. package/dist/node_modules/react-is/index.js +12 -0
  291. package/dist/node_modules/react-is/index.js.map +1 -0
  292. package/dist/shared/hooks/index.d.ts +7 -0
  293. package/dist/shared/hooks/index.d.ts.map +1 -0
  294. package/dist/shared/index.d.ts +6 -0
  295. package/dist/shared/index.d.ts.map +1 -0
  296. package/dist/shared/types/index.d.ts +109 -0
  297. package/dist/shared/types/index.d.ts.map +1 -0
  298. package/dist/utils/nativeBridge.d.ts +3 -0
  299. package/dist/utils/nativeBridge.d.ts.map +1 -0
  300. package/dist/utils/nativeBridge.js +2 -0
  301. package/package.json +114 -0
@@ -0,0 +1,258 @@
1
+ import { useAuthStore as e } from "../store/authStore.js";
2
+ import { useSessionOperations as t } from "../hooks/useSessionOperations.js";
3
+ import "../hooks/index.js";
4
+ import { AlertIcon as n, SpinnerIcon as r } from "../components/AuthIcons.js";
5
+ import { formatRelativeTime as i, parseBrowserName as a, parseDeviceName as o } from "../utils/formatters.js";
6
+ import { ConfirmActionDialog as s } from "../components/ConfirmActionDialog.js";
7
+ import { useState as c } from "react";
8
+ import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell";
9
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
10
+ //#region src/auth/pages/SessionsPage.tsx
11
+ function f() {
12
+ let { t: f } = l(), p = (e, t) => {
13
+ let n = f(e);
14
+ return n === e ? t : n;
15
+ }, m = e((e) => e.isAuthenticated), { activeSessions: h, revokeSession: g, revokeAllSessions: _, isLoading: v } = t({ disableTokenInfoQuery: !0 }), [y, b] = c(null), [x, S] = c(null), [C, w] = c(null), [T, E] = c(!1), D = async (e) => {
16
+ try {
17
+ await g(e), S("Session revoked successfully"), w(null);
18
+ } catch (e) {
19
+ b(e instanceof Error ? e.message : "Failed to revoke session");
20
+ }
21
+ };
22
+ return m ? /* @__PURE__ */ d("div", {
23
+ className: "max-w-4xl mx-auto p-6",
24
+ children: [
25
+ /* @__PURE__ */ u(s, {
26
+ open: C !== null,
27
+ onOpenChange: (e) => {
28
+ e || w(null);
29
+ },
30
+ title: "Revoke this session?",
31
+ description: "The selected device will be signed out immediately and will need to authenticate again.",
32
+ confirmText: "Revoke session",
33
+ variant: "danger",
34
+ isPending: v,
35
+ onConfirm: async () => {
36
+ C && await D(C);
37
+ }
38
+ }),
39
+ /* @__PURE__ */ u(s, {
40
+ open: T,
41
+ onOpenChange: E,
42
+ title: "Revoke every other session?",
43
+ description: "All devices except your current one will be signed out immediately.",
44
+ confirmText: "Revoke all other sessions",
45
+ variant: "warning",
46
+ isPending: v,
47
+ onConfirm: async () => {
48
+ try {
49
+ await _(), S("All other sessions have been revoked"), E(!1);
50
+ } catch (e) {
51
+ b(e instanceof Error ? e.message : "Failed to revoke all sessions");
52
+ }
53
+ }
54
+ }),
55
+ /* @__PURE__ */ d("div", {
56
+ className: "flex items-center justify-between mb-8",
57
+ children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h1", {
58
+ className: "text-3xl font-semibold text-[var(--color-text-primary)]",
59
+ children: p("auth.sessions.title", "Active Sessions")
60
+ }), /* @__PURE__ */ d("p", {
61
+ className: "text-[var(--color-text-secondary)] mt-2",
62
+ children: [
63
+ "You have ",
64
+ h.length,
65
+ " active session",
66
+ h.length === 1 ? "" : "s"
67
+ ]
68
+ })] }), h.length > 1 && /* @__PURE__ */ u("button", {
69
+ onClick: () => E(!0),
70
+ className: "px-4 py-2.5 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium hover:bg-[var(--color-status-error-bg-subtle)] transition-colors duration-200",
71
+ children: p("auth.sessions.revokeAll", "Revoke All Sessions")
72
+ })]
73
+ }),
74
+ x && /* @__PURE__ */ d("div", {
75
+ className: "mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]",
76
+ children: [/* @__PURE__ */ u("p", {
77
+ className: "text-[var(--color-status-success-text)]",
78
+ children: x
79
+ }), /* @__PURE__ */ u("button", {
80
+ onClick: () => S(null),
81
+ className: "mt-2 text-sm text-[var(--color-status-success-text)] hover:underline transition-colors duration-200",
82
+ children: "Dismiss"
83
+ })]
84
+ }),
85
+ y && /* @__PURE__ */ d("div", {
86
+ className: "mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]",
87
+ children: [/* @__PURE__ */ u(n, { className: "w-5 h-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5" }), /* @__PURE__ */ d("div", {
88
+ className: "flex-1",
89
+ children: [/* @__PURE__ */ u("p", {
90
+ className: "text-sm text-[var(--color-status-error-text)]",
91
+ children: y
92
+ }), /* @__PURE__ */ u("button", {
93
+ onClick: () => b(null),
94
+ className: "mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200",
95
+ children: "Dismiss"
96
+ })]
97
+ })]
98
+ }),
99
+ v ? /* @__PURE__ */ d("div", {
100
+ className: "flex items-center justify-center py-12",
101
+ children: [/* @__PURE__ */ u(r, { className: "w-8 h-8 text-text-link animate-spin" }), /* @__PURE__ */ u("span", {
102
+ className: "ml-3 text-[var(--color-text-secondary)]",
103
+ children: p("auth.sessions.loading", "Loading sessions...")
104
+ })]
105
+ }) : h.length === 0 ? /* @__PURE__ */ d("div", {
106
+ className: "text-center py-16 border-2 border-dashed border-[var(--color-border-default)] rounded-xl",
107
+ children: [/* @__PURE__ */ u("div", {
108
+ className: "w-16 h-16 mx-auto mb-4 rounded-full bg-[var(--color-bg-muted)] flex items-center justify-center",
109
+ children: /* @__PURE__ */ u("svg", {
110
+ className: "w-8 h-8 text-[var(--color-text-tertiary)]",
111
+ fill: "none",
112
+ viewBox: "0 0 24 24",
113
+ stroke: "currentColor",
114
+ children: /* @__PURE__ */ u("path", {
115
+ strokeLinecap: "round",
116
+ strokeLinejoin: "round",
117
+ strokeWidth: 1.5,
118
+ d: "M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
119
+ })
120
+ })
121
+ }), /* @__PURE__ */ u("p", {
122
+ className: "text-[var(--color-text-secondary)]",
123
+ children: p("auth.sessions.noSessions", "No active sessions found")
124
+ })]
125
+ }) : /* @__PURE__ */ u("div", {
126
+ className: "space-y-4",
127
+ children: h.map((e) => /* @__PURE__ */ u("div", {
128
+ className: "p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm hover:shadow-md transition-shadow",
129
+ children: /* @__PURE__ */ d("div", {
130
+ className: "flex items-start justify-between",
131
+ children: [/* @__PURE__ */ d("div", {
132
+ className: "flex items-start gap-4",
133
+ children: [/* @__PURE__ */ u("div", {
134
+ className: "w-12 h-12 rounded-xl bg-[var(--color-bg-accent)] flex items-center justify-center flex-shrink-0",
135
+ children: /* @__PURE__ */ u("svg", {
136
+ className: "w-6 h-6 text-[var(--color-text-link)]",
137
+ fill: "none",
138
+ viewBox: "0 0 24 24",
139
+ stroke: "currentColor",
140
+ children: /* @__PURE__ */ u("path", {
141
+ strokeLinecap: "round",
142
+ strokeLinejoin: "round",
143
+ strokeWidth: 1.5,
144
+ d: "M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
145
+ })
146
+ })
147
+ }), /* @__PURE__ */ d("div", {
148
+ className: "flex-1",
149
+ children: [
150
+ /* @__PURE__ */ d("div", {
151
+ className: "flex items-center gap-3 mb-1",
152
+ children: [/* @__PURE__ */ u("h3", {
153
+ className: "text-lg font-semibold text-[var(--color-text-primary)]",
154
+ children: e.isCurrent && o(e.userAgent) === "Unknown Device" ? p("auth.sessions.thisDevice", "This Device") : o(e.userAgent)
155
+ }), e.isCurrent && /* @__PURE__ */ u("span", {
156
+ className: "px-2.5 py-1 rounded-full bg-[var(--color-status-success-bg-subtle)] text-[var(--color-status-success-text)] text-xs font-medium",
157
+ children: p("auth.sessions.currentSession", "Current Session")
158
+ })]
159
+ }),
160
+ /* @__PURE__ */ u("p", {
161
+ className: "text-sm text-[var(--color-text-secondary)] mb-2",
162
+ children: a(e.userAgent) === "Unknown Browser" && e.isCurrent ? p("auth.sessions.currentBrowser", "Current Browser") : a(e.userAgent)
163
+ }),
164
+ /* @__PURE__ */ d("div", {
165
+ className: "flex flex-wrap gap-4 text-sm text-[var(--color-text-secondary)]",
166
+ children: [
167
+ e.ipAddress && e.ipAddress !== "unknown" && /* @__PURE__ */ d("span", {
168
+ className: "flex items-center gap-1.5",
169
+ children: [/* @__PURE__ */ u("svg", {
170
+ className: "w-4 h-4",
171
+ fill: "none",
172
+ viewBox: "0 0 24 24",
173
+ stroke: "currentColor",
174
+ children: /* @__PURE__ */ u("path", {
175
+ strokeLinecap: "round",
176
+ strokeLinejoin: "round",
177
+ strokeWidth: 2,
178
+ d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"
179
+ })
180
+ }), e.ipAddress]
181
+ }),
182
+ e.location && /* @__PURE__ */ d("span", {
183
+ className: "flex items-center gap-1.5",
184
+ children: [/* @__PURE__ */ d("svg", {
185
+ className: "w-4 h-4",
186
+ fill: "none",
187
+ viewBox: "0 0 24 24",
188
+ stroke: "currentColor",
189
+ children: [/* @__PURE__ */ u("path", {
190
+ strokeLinecap: "round",
191
+ strokeLinejoin: "round",
192
+ strokeWidth: 2,
193
+ d: "M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
194
+ }), /* @__PURE__ */ u("path", {
195
+ strokeLinecap: "round",
196
+ strokeLinejoin: "round",
197
+ strokeWidth: 2,
198
+ d: "M15 11a3 3 0 11-6 0 3 3 0 016 0z"
199
+ })]
200
+ }), e.location]
201
+ }),
202
+ /* @__PURE__ */ d("span", {
203
+ className: "flex items-center gap-1.5",
204
+ children: [
205
+ /* @__PURE__ */ u("svg", {
206
+ className: "w-4 h-4",
207
+ fill: "none",
208
+ viewBox: "0 0 24 24",
209
+ stroke: "currentColor",
210
+ children: /* @__PURE__ */ u("path", {
211
+ strokeLinecap: "round",
212
+ strokeLinejoin: "round",
213
+ strokeWidth: 2,
214
+ d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
215
+ })
216
+ }),
217
+ "Last active ",
218
+ i(e.lastActivityAt)
219
+ ]
220
+ })
221
+ ]
222
+ })
223
+ ]
224
+ })]
225
+ }), !e.isCurrent && /* @__PURE__ */ u("button", {
226
+ onClick: () => w(e.id),
227
+ className: "ml-4 px-4 py-2 rounded-lg text-sm font-medium border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] transition-colors duration-200",
228
+ children: p("auth.sessions.revoke", "Revoke")
229
+ })]
230
+ })
231
+ }, e.id))
232
+ })
233
+ ]
234
+ }) : /* @__PURE__ */ u("div", {
235
+ className: "max-w-4xl mx-auto p-6",
236
+ children: /* @__PURE__ */ d("div", {
237
+ className: "text-center py-16 border-2 border-dashed border-[var(--color-border-default)] rounded-xl",
238
+ children: [
239
+ /* @__PURE__ */ u("div", {
240
+ className: "w-16 h-16 mx-auto mb-4 rounded-full bg-[var(--color-status-warning-bg-subtle)] flex items-center justify-center",
241
+ children: /* @__PURE__ */ u(n, { className: "w-8 h-8 text-[var(--color-status-warning-text)]" })
242
+ }),
243
+ /* @__PURE__ */ u("h2", {
244
+ className: "text-xl font-semibold text-[var(--color-text-primary)] mb-2",
245
+ children: p("auth.sessions.authRequired", "Authentication Required")
246
+ }),
247
+ /* @__PURE__ */ u("p", {
248
+ className: "text-[var(--color-text-secondary)]",
249
+ children: p("auth.sessions.signInToView", "Please sign in to view your active sessions")
250
+ })
251
+ ]
252
+ })
253
+ });
254
+ }
255
+ //#endregion
256
+ export { f as SessionsPage };
257
+
258
+ //# sourceMappingURL=SessionsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionsPage.js","names":[],"sources":["../../../src/auth/pages/SessionsPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { useSessionOperations } from \"../hooks\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { ConfirmActionDialog } from \"../components/ConfirmActionDialog\";\nimport {\n formatRelativeTime,\n parseDeviceName,\n parseBrowserName,\n} from \"../utils\";\nimport { SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\n\n/**\n * Active sessions management page with professional UI\n */\nexport function SessionsPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const isAuthenticated = useAuthStore((state) => state.isAuthenticated);\n const { activeSessions, revokeSession, revokeAllSessions, isLoading } =\n useSessionOperations({ disableTokenInfoQuery: true });\n const [error, setError] = useState<string | null>(null);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [pendingSessionId, setPendingSessionId] = useState<string | null>(null);\n const [showRevokeAllDialog, setShowRevokeAllDialog] = useState(false);\n\n const handleRevokeSession = async (sessionId: string) => {\n try {\n await revokeSession(sessionId);\n setSuccessMessage(\"Session revoked successfully\");\n setPendingSessionId(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to revoke session\");\n }\n };\n\n const handleRevokeAll = async () => {\n try {\n await revokeAllSessions();\n setSuccessMessage(\"All other sessions have been revoked\");\n setShowRevokeAllDialog(false);\n } catch (err) {\n setError(\n err instanceof Error ? err.message : \"Failed to revoke all sessions\",\n );\n }\n };\n\n if (!isAuthenticated) {\n return (\n <div className=\"max-w-4xl mx-auto p-6\">\n <div className=\"text-center py-16 border-2 border-dashed border-[var(--color-border-default)] rounded-xl\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-[var(--color-status-warning-bg-subtle)] flex items-center justify-center\">\n <AlertIcon className=\"w-8 h-8 text-[var(--color-status-warning-text)]\" />\n </div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)] mb-2\">\n {tr(\"auth.sessions.authRequired\", \"Authentication Required\")}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.sessions.signInToView\",\n \"Please sign in to view your active sessions\",\n )}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"max-w-4xl mx-auto p-6\">\n <ConfirmActionDialog\n open={pendingSessionId !== null}\n onOpenChange={(open) => {\n if (!open) {\n setPendingSessionId(null);\n }\n }}\n title=\"Revoke this session?\"\n description=\"The selected device will be signed out immediately and will need to authenticate again.\"\n confirmText=\"Revoke session\"\n variant=\"danger\"\n isPending={isLoading}\n onConfirm={async () => {\n if (pendingSessionId) {\n await handleRevokeSession(pendingSessionId);\n }\n }}\n />\n <ConfirmActionDialog\n open={showRevokeAllDialog}\n onOpenChange={setShowRevokeAllDialog}\n title=\"Revoke every other session?\"\n description=\"All devices except your current one will be signed out immediately.\"\n confirmText=\"Revoke all other sessions\"\n variant=\"warning\"\n isPending={isLoading}\n onConfirm={handleRevokeAll}\n />\n {/* Header */}\n <div className=\"flex items-center justify-between mb-8\">\n <div>\n <h1 className=\"text-3xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.sessions.title\", \"Active Sessions\")}\n </h1>\n <p className=\"text-[var(--color-text-secondary)] mt-2\">\n You have {activeSessions.length} active session\n {activeSessions.length !== 1 ? \"s\" : \"\"}\n </p>\n </div>\n {activeSessions.length > 1 && (\n <button\n onClick={() => setShowRevokeAllDialog(true)}\n className=\"px-4 py-2.5 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium hover:bg-[var(--color-status-error-bg-subtle)] transition-colors duration-200\"\n >\n {tr(\"auth.sessions.revokeAll\", \"Revoke All Sessions\")}\n </button>\n )}\n </div>\n\n {/* Success Message */}\n {successMessage && (\n <div className=\"mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <p className=\"text-[var(--color-status-success-text)]\">\n {successMessage}\n </p>\n <button\n onClick={() => setSuccessMessage(null)}\n className=\"mt-2 text-sm text-[var(--color-status-success-text)] hover:underline transition-colors duration-200\"\n >\n Dismiss\n </button>\n </div>\n )}\n\n {/* Error Message */}\n {error && (\n <div className=\"mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]\">\n <AlertIcon className=\"w-5 h-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5\" />\n <div className=\"flex-1\">\n <p className=\"text-sm text-[var(--color-status-error-text)]\">\n {error}\n </p>\n <button\n onClick={() => setError(null)}\n className=\"mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200\"\n >\n Dismiss\n </button>\n </div>\n </div>\n )}\n\n {isLoading ? (\n <div className=\"flex items-center justify-center py-12\">\n <SpinnerIcon className=\"w-8 h-8 text-text-link animate-spin\" />\n <span className=\"ml-3 text-[var(--color-text-secondary)]\">\n {tr(\"auth.sessions.loading\", \"Loading sessions...\")}\n </span>\n </div>\n ) : activeSessions.length === 0 ? (\n <div className=\"text-center py-16 border-2 border-dashed border-[var(--color-border-default)] rounded-xl\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-[var(--color-bg-muted)] flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-[var(--color-text-tertiary)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n </div>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\"auth.sessions.noSessions\", \"No active sessions found\")}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n {activeSessions.map((session) => (\n <div\n key={session.id}\n className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm hover:shadow-md transition-shadow\"\n >\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-4\">\n {/* Device Icon */}\n <div className=\"w-12 h-12 rounded-xl bg-[var(--color-bg-accent)] flex items-center justify-center flex-shrink-0\">\n <svg\n className=\"w-6 h-6 text-[var(--color-text-link)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n </div>\n\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-3 mb-1\">\n <h3 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {session.isCurrent &&\n parseDeviceName(session.userAgent) === \"Unknown Device\"\n ? tr(\"auth.sessions.thisDevice\", \"This Device\")\n : parseDeviceName(session.userAgent)}\n </h3>\n {session.isCurrent && (\n <span className=\"px-2.5 py-1 rounded-full bg-[var(--color-status-success-bg-subtle)] text-[var(--color-status-success-text)] text-xs font-medium\">\n {tr(\n \"auth.sessions.currentSession\",\n \"Current Session\",\n )}\n </span>\n )}\n </div>\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-2\">\n {parseBrowserName(session.userAgent) ===\n \"Unknown Browser\" && session.isCurrent\n ? tr(\"auth.sessions.currentBrowser\", \"Current Browser\")\n : parseBrowserName(session.userAgent)}\n </p>\n <div className=\"flex flex-wrap gap-4 text-sm text-[var(--color-text-secondary)]\">\n {session.ipAddress && session.ipAddress !== \"unknown\" && (\n <span className=\"flex items-center gap-1.5\">\n <svg\n className=\"w-4 h-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9\"\n />\n </svg>\n {session.ipAddress}\n </span>\n )}\n {session.location && (\n <span className=\"flex items-center gap-1.5\">\n <svg\n className=\"w-4 h-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 11a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n {session.location}\n </span>\n )}\n <span className=\"flex items-center gap-1.5\">\n <svg\n className=\"w-4 h-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Last active {formatRelativeTime(session.lastActivityAt)}\n </span>\n </div>\n </div>\n </div>\n\n {!session.isCurrent && (\n <button\n onClick={() => setPendingSessionId(session.id)}\n className=\"ml-4 px-4 py-2 rounded-lg text-sm font-medium border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] transition-colors duration-200\"\n >\n {tr(\"auth.sessions.revoke\", \"Revoke\")}\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * SSO Callback Page
3
+ * Handles redirects from:
4
+ * - SAML ACS server (with token/refreshToken in query params)
5
+ * - OIDC Authorization Server (with code/state in query params)
6
+ */
7
+ export declare function SsoCallbackPage(): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=SsoCallbackPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SsoCallbackPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/SsoCallbackPage.tsx"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,wBAAgB,eAAe,4CAqW9B"}
@@ -0,0 +1,188 @@
1
+ import { useAuthStore as e } from "../store/authStore.js";
2
+ import { useSsoOperations as t } from "../hooks/useSsoOperations.js";
3
+ import { AlertIcon as n, SpinnerIcon as r } from "../components/AuthIcons.js";
4
+ import { useEffect as i, useRef as a, useState as o } from "react";
5
+ import { useNavigate as s, useSearchParams as c } from "react-router-dom";
6
+ import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell";
7
+ import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
8
+ //#region src/auth/pages/SsoCallbackPage.tsx
9
+ function p() {
10
+ let { t: p } = l(), m = (e, t) => {
11
+ let n = p(e);
12
+ return n === e ? t : n;
13
+ }, h = s(), [g] = c(), _ = e((e) => e.setAuthTokens), v = e((e) => e.setAuthenticated), { exchangeOidcCode: y, validateOidcState: b, isExternalOidcCallback: x, handleExternalOidcCallback: S } = t(), [C, w] = o(null), [T, E] = o("processing"), [D, O] = o("unknown"), k = a(!1);
14
+ return i(() => {
15
+ if (k.current) return;
16
+ k.current = !0;
17
+ let e = async () => {
18
+ try {
19
+ let e = g.get("error"), r = g.get("message") || g.get("error_description");
20
+ if (e) throw Error(r || `SSO authentication failed: ${e}`);
21
+ let i = g.get("token"), a = g.get("code"), o = g.get("state");
22
+ if (i) O("saml"), await t(i);
23
+ else if (a) O("oidc"), await n(a, o);
24
+ else throw Error("Invalid SSO callback. No token or authorization code received.");
25
+ } catch (e) {
26
+ console.error("[SSO Callback] Error:", e), w(e instanceof Error ? e.message : "Failed to process SSO response"), E("error");
27
+ }
28
+ }, t = async (e) => {
29
+ let t = g.get("refreshToken"), n = g.get("redirect"), r = g.get("requiresMFA") === "true", i = g.get("mfaChallengeId");
30
+ if (r && i) {
31
+ sessionStorage.setItem("mfa_challenge_id", i), sessionStorage.setItem("mfa_pending_token", e), sessionStorage.setItem("mfa_pending_refresh", t || ""), sessionStorage.setItem("mfa_redirect", n || "/dashboard"), h("/auth/mfa-verify", { replace: !0 });
32
+ return;
33
+ }
34
+ _(e, t || ""), v(!0), E("success"), setTimeout(() => {
35
+ h(n || "/dashboard", { replace: !0 });
36
+ }, 1500);
37
+ }, n = async (e, t) => {
38
+ if (x()) {
39
+ if (!t) throw Error("State parameter is required for external OIDC flow");
40
+ let n = await S(e, t);
41
+ if (!n.success) throw Error(n.error || "Failed to authenticate with external OIDC provider");
42
+ E("success");
43
+ let r = n.redirectPath || "/dashboard";
44
+ setTimeout(() => {
45
+ h(r, { replace: !0 });
46
+ }, 1500);
47
+ return;
48
+ }
49
+ if (t && !b(t)) throw Error("Invalid state parameter. This may be a CSRF attack. Please try logging in again.");
50
+ let n = await y(e, sessionStorage.getItem("oidc_client_id") || "default-client", window.location.origin + "/auth/sso/callback");
51
+ if (!n.success) throw Error(n.error || "Failed to exchange authorization code");
52
+ if (n.requiresMFA && n.mfaChallengeId) {
53
+ sessionStorage.setItem("mfa_challenge_id", n.mfaChallengeId), sessionStorage.setItem("mfa_redirect", sessionStorage.getItem("oidc_redirect") || "/dashboard"), sessionStorage.removeItem("oidc_redirect"), sessionStorage.removeItem("oidc_client_id"), h("/auth/mfa-verify", { replace: !0 });
54
+ return;
55
+ }
56
+ E("success");
57
+ let r = sessionStorage.getItem("oidc_redirect") || "/dashboard";
58
+ sessionStorage.removeItem("oidc_redirect"), sessionStorage.removeItem("oidc_client_id"), setTimeout(() => {
59
+ h(r, { replace: !0 });
60
+ }, 1500);
61
+ };
62
+ e();
63
+ }, [
64
+ g,
65
+ h,
66
+ _,
67
+ v,
68
+ y,
69
+ b,
70
+ x,
71
+ S
72
+ ]), /* @__PURE__ */ d("div", {
73
+ className: "min-h-screen flex items-center justify-center bg-gradient-to-br from-bg-canvas to-bg-sunkengray-900gray-800 p-4",
74
+ children: /* @__PURE__ */ d("div", {
75
+ className: "w-full max-w-md",
76
+ children: /* @__PURE__ */ f("div", {
77
+ className: "bg-bg-surface rounded-2xl shadow-xl p-8 text-center",
78
+ children: [
79
+ /* @__PURE__ */ d("div", {
80
+ className: "mb-6",
81
+ children: /* @__PURE__ */ d("div", {
82
+ className: "auth-brand-badge mx-auto flex h-16 w-16 items-center justify-center rounded-xl",
83
+ children: /* @__PURE__ */ d("svg", {
84
+ className: "w-8 h-8 text-white",
85
+ fill: "none",
86
+ viewBox: "0 0 24 24",
87
+ stroke: "currentColor",
88
+ children: /* @__PURE__ */ d("path", {
89
+ strokeLinecap: "round",
90
+ strokeLinejoin: "round",
91
+ strokeWidth: 2,
92
+ d: "M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
93
+ })
94
+ })
95
+ })
96
+ }),
97
+ T === "processing" && /* @__PURE__ */ f(u, { children: [
98
+ /* @__PURE__ */ d("h1", {
99
+ className: "text-2xl font-semibold text-text-primary mb-4",
100
+ children: m("auth.ssoCallback.completing", "Completing Sign In")
101
+ }),
102
+ /* @__PURE__ */ d("p", {
103
+ className: "text-text-secondary mb-6",
104
+ children: D === "oidc" ? m("auth.ssoCallback.exchangingCode", "Exchanging authorization code for access tokens...") : D === "saml" ? m("auth.ssoCallback.validatingSaml", "Validating your SAML credentials...") : m("auth.ssoCallback.validatingCreds", "Validating your credentials from your identity provider...")
105
+ }),
106
+ /* @__PURE__ */ d("div", {
107
+ className: "flex justify-center",
108
+ children: /* @__PURE__ */ d(r, { className: "w-10 h-10 text-text-link animate-spin" })
109
+ })
110
+ ] }),
111
+ T === "success" && /* @__PURE__ */ f(u, { children: [
112
+ /* @__PURE__ */ d("div", {
113
+ className: "w-16 h-16 mx-auto mb-4 rounded-full bg-status-success-bg-subtle flex items-center justify-center",
114
+ children: /* @__PURE__ */ d("svg", {
115
+ className: "w-8 h-8 text-status-success-text",
116
+ fill: "none",
117
+ viewBox: "0 0 24 24",
118
+ stroke: "currentColor",
119
+ children: /* @__PURE__ */ d("path", {
120
+ strokeLinecap: "round",
121
+ strokeLinejoin: "round",
122
+ strokeWidth: 2,
123
+ d: "M5 13l4 4L19 7"
124
+ })
125
+ })
126
+ }),
127
+ /* @__PURE__ */ d("h1", {
128
+ className: "text-2xl font-semibold text-text-primary mb-4",
129
+ children: m("auth.ssoCallback.success", "Sign In Successful")
130
+ }),
131
+ /* @__PURE__ */ d("p", {
132
+ className: "text-text-secondary mb-6",
133
+ children: D === "oidc" ? m("auth.ssoCallback.oidcComplete", "OIDC authentication complete. Redirecting...") : D === "saml" ? m("auth.ssoCallback.samlComplete", "SAML authentication complete. Redirecting...") : m("auth.ssoCallback.authSuccess", "You have been authenticated successfully. Redirecting...")
134
+ }),
135
+ /* @__PURE__ */ d("div", {
136
+ className: "flex justify-center",
137
+ children: /* @__PURE__ */ d(r, { className: "w-6 h-6 text-status-success-text animate-spin" })
138
+ })
139
+ ] }),
140
+ T === "error" && /* @__PURE__ */ f(u, { children: [
141
+ /* @__PURE__ */ d("div", {
142
+ className: "w-16 h-16 mx-auto mb-4 rounded-full bg-status-error-bg-subtle flex items-center justify-center",
143
+ children: /* @__PURE__ */ d(n, { className: "w-8 h-8 text-status-error-text" })
144
+ }),
145
+ /* @__PURE__ */ d("h1", {
146
+ className: "text-2xl font-semibold text-text-primary mb-4",
147
+ children: m("auth.ssoCallback.failed", "Sign In Failed")
148
+ }),
149
+ /* @__PURE__ */ d("p", {
150
+ className: "text-status-error-text mb-6 text-sm",
151
+ children: C
152
+ }),
153
+ /* @__PURE__ */ f("div", {
154
+ className: "space-y-3",
155
+ children: [/* @__PURE__ */ d("button", {
156
+ onClick: () => h("/auth/sso/login", { replace: !0 }),
157
+ className: "auth-primary-button w-full px-6 py-3 font-medium",
158
+ children: m("auth.ssoCallback.tryAgain", "Try Again")
159
+ }), /* @__PURE__ */ d("button", {
160
+ onClick: () => h("/auth/login", { replace: !0 }),
161
+ className: "w-full px-6 py-3 rounded-xl border border-border-default text-text-primary font-medium hover:bg-bg-sunken transition-colors",
162
+ children: m("auth.ssoCallback.backToLogin", "Back to Login")
163
+ })]
164
+ })
165
+ ] }),
166
+ D !== "unknown" && /* @__PURE__ */ d("div", {
167
+ className: "mt-6",
168
+ children: /* @__PURE__ */ d("span", {
169
+ className: `inline-flex items-center px-3 py-1 rounded-full text-xs font-medium ${D === "oidc" ? "bg-accent-purple-subtle text-accent-purple" : "bg-status-info-bg-subtle text-text-linkHover"}`,
170
+ children: D === "oidc" ? "OpenID Connect" : "SAML 2.0"
171
+ })
172
+ }),
173
+ /* @__PURE__ */ d("div", {
174
+ className: "mt-8 pt-6 border-t border-border-subtle",
175
+ children: /* @__PURE__ */ d("p", {
176
+ className: "text-xs text-text-secondary",
177
+ children: m("auth.ssoCallback.helpText", "Having trouble? Contact your organization's IT administrator for assistance with SSO login.")
178
+ })
179
+ })
180
+ ]
181
+ })
182
+ })
183
+ });
184
+ }
185
+ //#endregion
186
+ export { p as SsoCallbackPage };
187
+
188
+ //# sourceMappingURL=SsoCallbackPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SsoCallbackPage.js","names":[],"sources":["../../../src/auth/pages/SsoCallbackPage.tsx"],"sourcesContent":["import { useEffect, useState, useRef } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { useNavigate, useSearchParams } from \"react-router-dom\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { useSsoOperations } from \"../hooks/useSsoOperations\";\nimport { SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\n\n/**\n * SSO Callback Page\n * Handles redirects from:\n * - SAML ACS server (with token/refreshToken in query params)\n * - OIDC Authorization Server (with code/state in query params)\n */\nexport function SsoCallbackPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const navigate = useNavigate();\n const [searchParams] = useSearchParams();\n const setAuthTokens = useAuthStore((state) => state.setAuthTokens);\n const setAuthenticated = useAuthStore((state) => state.setAuthenticated);\n const {\n exchangeOidcCode,\n validateOidcState,\n isExternalOidcCallback,\n handleExternalOidcCallback,\n } = useSsoOperations();\n\n const [error, setError] = useState<string | null>(null);\n const [status, setStatus] = useState<\"processing\" | \"success\" | \"error\">(\n \"processing\",\n );\n const [callbackType, setCallbackType] = useState<\"saml\" | \"oidc\" | \"unknown\">(\n \"unknown\",\n );\n const processedRef = useRef(false);\n\n useEffect(() => {\n // Prevent double execution in React StrictMode\n if (processedRef.current) {\n return;\n }\n processedRef.current = true;\n\n const processCallback = async () => {\n try {\n // Check for error from either SSO provider\n const errorParam = searchParams.get(\"error\");\n const errorMessage =\n searchParams.get(\"message\") || searchParams.get(\"error_description\");\n\n if (errorParam) {\n throw new Error(\n errorMessage || `SSO authentication failed: ${errorParam}`,\n );\n }\n\n // Detect callback type based on query parameters\n const token = searchParams.get(\"token\");\n const code = searchParams.get(\"code\");\n const state = searchParams.get(\"state\");\n\n if (token) {\n // SAML callback - token already exchanged by ACS server\n setCallbackType(\"saml\");\n await handleSamlCallback(token);\n } else if (code) {\n // OIDC callback - need to exchange code for tokens\n setCallbackType(\"oidc\");\n await handleOidcCallback(code, state);\n } else {\n throw new Error(\n \"Invalid SSO callback. No token or authorization code received.\",\n );\n }\n } catch (err) {\n console.error(\"[SSO Callback] Error:\", err);\n setError(\n err instanceof Error ? err.message : \"Failed to process SSO response\",\n );\n setStatus(\"error\");\n }\n };\n\n /**\n * Handle SAML callback from ACS server\n * Token is already exchanged, just store and redirect\n * Also handles MFA if required\n */\n const handleSamlCallback = async (token: string) => {\n const refreshToken = searchParams.get(\"refreshToken\");\n const redirect = searchParams.get(\"redirect\");\n const requiresMFA = searchParams.get(\"requiresMFA\") === \"true\";\n const mfaChallengeId = searchParams.get(\"mfaChallengeId\");\n\n // Check if MFA is required\n if (requiresMFA && mfaChallengeId) {\n // Store partial auth state and MFA info\n sessionStorage.setItem(\"mfa_challenge_id\", mfaChallengeId);\n sessionStorage.setItem(\"mfa_pending_token\", token);\n sessionStorage.setItem(\"mfa_pending_refresh\", refreshToken || \"\");\n sessionStorage.setItem(\"mfa_redirect\", redirect || \"/dashboard\");\n\n // Redirect to MFA verification\n navigate(\"/auth/mfa-verify\", { replace: true });\n return;\n }\n\n // Store tokens\n setAuthTokens(token, refreshToken || \"\");\n setAuthenticated(true);\n\n setStatus(\"success\");\n\n // Redirect to the specified URL or default to dashboard\n setTimeout(() => {\n const redirectUrl = redirect || \"/dashboard\";\n navigate(redirectUrl, { replace: true });\n }, 1500);\n };\n\n /**\n * Handle OIDC callback - exchange code for tokens\n */\n const handleOidcCallback = async (code: string, state: string | null) => {\n const isExternal = isExternalOidcCallback();\n\n // Check if this is an external OIDC flow (Azure AD, Google, etc.)\n if (isExternal) {\n if (!state) {\n throw new Error(\"State parameter is required for external OIDC flow\");\n }\n\n // Use the external OIDC handler\n const result = await handleExternalOidcCallback(code, state);\n\n if (!result.success) {\n throw new Error(\n result.error ||\n \"Failed to authenticate with external OIDC provider\",\n );\n }\n\n setStatus(\"success\");\n\n // Redirect after brief success message using the redirect path from result\n const redirectUrl = result.redirectPath || \"/dashboard\";\n setTimeout(() => {\n navigate(redirectUrl, { replace: true });\n }, 1500);\n return;\n }\n\n // Internal OIDC flow (our auth service as provider)\n // Validate state to prevent CSRF\n if (state && !validateOidcState(state)) {\n throw new Error(\n \"Invalid state parameter. This may be a CSRF attack. Please try logging in again.\",\n );\n }\n\n // Get client configuration from session storage\n const clientId =\n sessionStorage.getItem(\"oidc_client_id\") || \"default-client\";\n const redirectUri = window.location.origin + \"/auth/sso/callback\";\n\n // Exchange code for tokens\n const result = await exchangeOidcCode(code, clientId, redirectUri);\n\n if (!result.success) {\n throw new Error(\n result.error || \"Failed to exchange authorization code\",\n );\n }\n\n // Check if MFA is required after OIDC authentication\n if (result.requiresMFA && result.mfaChallengeId) {\n // Store MFA challenge info for the verification page\n sessionStorage.setItem(\"mfa_challenge_id\", result.mfaChallengeId);\n sessionStorage.setItem(\n \"mfa_redirect\",\n sessionStorage.getItem(\"oidc_redirect\") || \"/dashboard\",\n );\n\n // Clean up OIDC session data\n sessionStorage.removeItem(\"oidc_redirect\");\n sessionStorage.removeItem(\"oidc_client_id\");\n\n // Redirect to MFA verification\n navigate(\"/auth/mfa-verify\", { replace: true });\n return;\n }\n\n setStatus(\"success\");\n\n // Get redirect URL from state or session storage\n const redirect = sessionStorage.getItem(\"oidc_redirect\") || \"/dashboard\";\n sessionStorage.removeItem(\"oidc_redirect\");\n sessionStorage.removeItem(\"oidc_client_id\");\n\n // Redirect after brief success message\n setTimeout(() => {\n navigate(redirect, { replace: true });\n }, 1500);\n };\n\n processCallback();\n }, [\n searchParams,\n navigate,\n setAuthTokens,\n setAuthenticated,\n exchangeOidcCode,\n validateOidcState,\n isExternalOidcCallback,\n handleExternalOidcCallback,\n ]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gradient-to-br from-bg-canvas to-bg-sunkengray-900gray-800 p-4\">\n <div className=\"w-full max-w-md\">\n <div className=\"bg-bg-surface rounded-2xl shadow-xl p-8 text-center\">\n {/* Logo */}\n <div className=\"mb-6\">\n <div className=\"auth-brand-badge mx-auto flex h-16 w-16 items-center justify-center rounded-xl\">\n <svg\n className=\"w-8 h-8 text-white\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n </div>\n\n {/* Processing State */}\n {status === \"processing\" && (\n <>\n <h1 className=\"text-2xl font-semibold text-text-primary mb-4\">\n {tr(\"auth.ssoCallback.completing\", \"Completing Sign In\")}\n </h1>\n <p className=\"text-text-secondary mb-6\">\n {callbackType === \"oidc\"\n ? tr(\n \"auth.ssoCallback.exchangingCode\",\n \"Exchanging authorization code for access tokens...\",\n )\n : callbackType === \"saml\"\n ? tr(\n \"auth.ssoCallback.validatingSaml\",\n \"Validating your SAML credentials...\",\n )\n : tr(\n \"auth.ssoCallback.validatingCreds\",\n \"Validating your credentials from your identity provider...\",\n )}\n </p>\n <div className=\"flex justify-center\">\n <SpinnerIcon className=\"w-10 h-10 text-text-link animate-spin\" />\n </div>\n </>\n )}\n\n {/* Success State */}\n {status === \"success\" && (\n <>\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-status-success-bg-subtle flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-status-success-text\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-semibold text-text-primary mb-4\">\n {tr(\"auth.ssoCallback.success\", \"Sign In Successful\")}\n </h1>\n <p className=\"text-text-secondary mb-6\">\n {callbackType === \"oidc\"\n ? tr(\n \"auth.ssoCallback.oidcComplete\",\n \"OIDC authentication complete. Redirecting...\",\n )\n : callbackType === \"saml\"\n ? tr(\n \"auth.ssoCallback.samlComplete\",\n \"SAML authentication complete. Redirecting...\",\n )\n : tr(\n \"auth.ssoCallback.authSuccess\",\n \"You have been authenticated successfully. Redirecting...\",\n )}\n </p>\n <div className=\"flex justify-center\">\n <SpinnerIcon className=\"w-6 h-6 text-status-success-text animate-spin\" />\n </div>\n </>\n )}\n\n {/* Error State */}\n {status === \"error\" && (\n <>\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-status-error-bg-subtle flex items-center justify-center\">\n <AlertIcon className=\"w-8 h-8 text-status-error-text\" />\n </div>\n <h1 className=\"text-2xl font-semibold text-text-primary mb-4\">\n {tr(\"auth.ssoCallback.failed\", \"Sign In Failed\")}\n </h1>\n <p className=\"text-status-error-text mb-6 text-sm\">{error}</p>\n <div className=\"space-y-3\">\n <button\n onClick={() => navigate(\"/auth/sso/login\", { replace: true })}\n className=\"auth-primary-button w-full px-6 py-3 font-medium\"\n >\n {tr(\"auth.ssoCallback.tryAgain\", \"Try Again\")}\n </button>\n <button\n onClick={() => navigate(\"/auth/login\", { replace: true })}\n className=\"w-full px-6 py-3 rounded-xl border border-border-default text-text-primary font-medium hover:bg-bg-sunken transition-colors\"\n >\n {tr(\"auth.ssoCallback.backToLogin\", \"Back to Login\")}\n </button>\n </div>\n </>\n )}\n\n {/* SSO Type Badge */}\n {callbackType !== \"unknown\" && (\n <div className=\"mt-6\">\n <span\n className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-medium ${\n callbackType === \"oidc\"\n ? \"bg-accent-purple-subtle text-accent-purple\"\n : \"bg-status-info-bg-subtle text-text-linkHover\"\n }`}\n >\n {callbackType === \"oidc\" ? \"OpenID Connect\" : \"SAML 2.0\"}\n </span>\n </div>\n )}\n\n {/* Help Text */}\n <div className=\"mt-8 pt-6 border-t border-border-subtle\">\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"auth.ssoCallback.helpText\",\n \"Having trouble? Contact your organization's IT administrator for assistance with SSO login.\",\n )}\n </p>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * SSO Configuration page for managing SAML/OIDC enterprise SSO
3
+ * Admin only - allows configuring Identity Provider settings
4
+ */
5
+ export declare function SsoConfigPage(): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=SsoConfigPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SsoConfigPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/SsoConfigPage.tsx"],"names":[],"mappings":"AAgHA;;;GAGG;AACH,wBAAgB,aAAa,4CA+7C5B"}