@ollaid/native-sso 2.7.8 → 2.8.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.
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * } />
10
10
  * ```
11
11
  *
12
- * @version 2.7.8
12
+ * @version 2.7.9
13
13
  */
14
14
  export { NativeSSOPage } from './components/NativeSSOPage';
15
15
  export type { NativeSSOPageProps } from './components/NativeSSOPage';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
- import { createContext, forwardRef, useEffect, useContext, useRef, useState, useCallback, useMemo } from "react";
5
+ import { createContext, forwardRef, useEffect, useContext, useRef, useState, useCallback, useMemo, createElement } from "react";
6
6
  const iconProps = { width: "100%", height: "100%", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
7
7
  function IconShieldCheck(props) {
8
8
  return /* @__PURE__ */ jsxs("svg", { ...iconProps, ...props, children: [
@@ -8888,6 +8888,25 @@ function useTokenHealthCheck(options) {
8888
8888
  };
8889
8889
  }, [enabled, saasApiUrl, performCheck, debug]);
8890
8890
  }
8891
+ function normalizeNativeUser(user) {
8892
+ if (!user) return null;
8893
+ const input = user;
8894
+ return {
8895
+ reference: input.reference ?? input.iam_reference ?? input.alias_reference ?? "",
8896
+ name: input.name ?? "",
8897
+ email: input.email ?? void 0,
8898
+ phone: input.phone,
8899
+ ccphone: input.ccphone,
8900
+ image_url: input.image_url ?? input.image,
8901
+ account_type: input.account_type,
8902
+ town: input.town,
8903
+ country: input.country,
8904
+ address: input.address,
8905
+ auth_2fa: input.auth_2fa,
8906
+ alias_reference: input.alias_reference,
8907
+ iam_reference: input.iam_reference
8908
+ };
8909
+ }
8891
8910
  function saveSession(exchangeResult, accountType) {
8892
8911
  var _a, _b;
8893
8912
  const storage = getNativeStorage();
@@ -9004,7 +9023,8 @@ function useNativeAuth(options) {
9004
9023
  if (storedRaw) {
9005
9024
  try {
9006
9025
  const stored = JSON.parse(storedRaw);
9007
- const merged = { ...stored, ...userInfos };
9026
+ const merged = normalizeNativeUser({ ...stored, ...userInfos });
9027
+ if (!merged) return;
9008
9028
  getNativeStorage().setItem(STORAGE.USER, JSON.stringify(merged));
9009
9029
  setState((prev) => ({ ...prev, user: merged }));
9010
9030
  } catch {
@@ -9027,13 +9047,10 @@ function useNativeAuth(options) {
9027
9047
  }
9028
9048
  const res = await nativeAuthService.refresh();
9029
9049
  if (res.success) {
9030
- const storedUser = getNativeStorage().getItem(STORAGE.USER);
9031
- if (storedUser) {
9032
- try {
9033
- const user = JSON.parse(storedUser);
9034
- setState((prev) => ({ ...prev, user, status: "completed" }));
9035
- } catch {
9036
- }
9050
+ const snapshot = getSsoSessionSnapshot();
9051
+ const user = normalizeNativeUser(snapshot.user);
9052
+ if (user) {
9053
+ setState((prev) => ({ ...prev, user, status: "completed" }));
9037
9054
  }
9038
9055
  return "recovered";
9039
9056
  }
@@ -9072,16 +9089,10 @@ function useNativeAuth(options) {
9072
9089
  return () => clearTimeout(t);
9073
9090
  }, [state.status, state.user, tryRefreshSession]);
9074
9091
  useEffect(() => {
9075
- const storage2 = getNativeStorage();
9076
- const storedToken = storage2.getItem(STORAGE.AUTH_TOKEN) || storage2.getItem(STORAGE.TOKEN);
9077
- const storedUser = storage2.getItem(STORAGE.USER);
9078
- if (storedToken && storedUser) {
9079
- try {
9080
- const user = JSON.parse(storedUser);
9081
- setState((prev) => ({ ...prev, user, status: "completed" }));
9082
- } catch {
9083
- clearSession();
9084
- }
9092
+ const snapshot = getSsoSessionSnapshot();
9093
+ const user = normalizeNativeUser(snapshot.user);
9094
+ if (snapshot.authToken && user) {
9095
+ setState((prev) => ({ ...prev, user, status: "completed" }));
9085
9096
  }
9086
9097
  }, []);
9087
9098
  useEffect(() => {
@@ -11241,7 +11252,7 @@ function SuccessOrbit() {
11241
11252
  justifyContent: "center",
11242
11253
  zIndex: 2
11243
11254
  }, children: /* @__PURE__ */ jsx(IconLink, { style: { width: "1.7rem", height: "1.7rem", color: C$1.green } }) }),
11244
- orbitIcons.map((Icon, i) => {
11255
+ orbitIcons.map((Icon2, i) => {
11245
11256
  const angle = i * 360 / orbitIcons.length;
11246
11257
  return /* @__PURE__ */ jsx("div", { style: {
11247
11258
  position: "absolute",
@@ -11260,7 +11271,7 @@ function SuccessOrbit() {
11260
11271
  display: "flex",
11261
11272
  alignItems: "center",
11262
11273
  justifyContent: "center"
11263
- }, children: /* @__PURE__ */ jsx(Icon, { style: { width: "1rem", height: "1rem", color: C$1.gray500 } }) }) }, i);
11274
+ }, children: /* @__PURE__ */ jsx(Icon2, { style: { width: "1rem", height: "1rem", color: C$1.gray500 } }) }) }, i);
11264
11275
  })
11265
11276
  ] });
11266
11277
  }
@@ -13298,7 +13309,248 @@ function OnboardingModal({
13298
13309
  renderConfirmDialog()
13299
13310
  ] });
13300
13311
  }
13301
- function DebugPanel({ saasApiUrl, iamApiUrl, onOpenLogin, onOpenSignup, onOpenOnboarding, onResetProfilePrompt }) {
13312
+ /**
13313
+ * @license lucide-react v0.462.0 - ISC
13314
+ *
13315
+ * This source code is licensed under the ISC license.
13316
+ * See the LICENSE file in the root directory of this source tree.
13317
+ */
13318
+ const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
13319
+ const mergeClasses = (...classes) => classes.filter((className, index, array) => {
13320
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
13321
+ }).join(" ").trim();
13322
+ /**
13323
+ * @license lucide-react v0.462.0 - ISC
13324
+ *
13325
+ * This source code is licensed under the ISC license.
13326
+ * See the LICENSE file in the root directory of this source tree.
13327
+ */
13328
+ var defaultAttributes = {
13329
+ xmlns: "http://www.w3.org/2000/svg",
13330
+ width: 24,
13331
+ height: 24,
13332
+ viewBox: "0 0 24 24",
13333
+ fill: "none",
13334
+ stroke: "currentColor",
13335
+ strokeWidth: 2,
13336
+ strokeLinecap: "round",
13337
+ strokeLinejoin: "round"
13338
+ };
13339
+ /**
13340
+ * @license lucide-react v0.462.0 - ISC
13341
+ *
13342
+ * This source code is licensed under the ISC license.
13343
+ * See the LICENSE file in the root directory of this source tree.
13344
+ */
13345
+ const Icon = forwardRef(
13346
+ ({
13347
+ color = "currentColor",
13348
+ size = 24,
13349
+ strokeWidth = 2,
13350
+ absoluteStrokeWidth,
13351
+ className = "",
13352
+ children,
13353
+ iconNode,
13354
+ ...rest
13355
+ }, ref) => {
13356
+ return createElement(
13357
+ "svg",
13358
+ {
13359
+ ref,
13360
+ ...defaultAttributes,
13361
+ width: size,
13362
+ height: size,
13363
+ stroke: color,
13364
+ strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
13365
+ className: mergeClasses("lucide", className),
13366
+ ...rest
13367
+ },
13368
+ [
13369
+ ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
13370
+ ...Array.isArray(children) ? children : [children]
13371
+ ]
13372
+ );
13373
+ }
13374
+ );
13375
+ /**
13376
+ * @license lucide-react v0.462.0 - ISC
13377
+ *
13378
+ * This source code is licensed under the ISC license.
13379
+ * See the LICENSE file in the root directory of this source tree.
13380
+ */
13381
+ const createLucideIcon = (iconName, iconNode) => {
13382
+ const Component = forwardRef(
13383
+ ({ className, ...props }, ref) => createElement(Icon, {
13384
+ ref,
13385
+ iconNode,
13386
+ className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),
13387
+ ...props
13388
+ })
13389
+ );
13390
+ Component.displayName = `${iconName}`;
13391
+ return Component;
13392
+ };
13393
+ /**
13394
+ * @license lucide-react v0.462.0 - ISC
13395
+ *
13396
+ * This source code is licensed under the ISC license.
13397
+ * See the LICENSE file in the root directory of this source tree.
13398
+ */
13399
+ const ExternalLink = createLucideIcon("ExternalLink", [
13400
+ ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
13401
+ ["path", { d: "M10 14 21 3", key: "gplh6r" }],
13402
+ ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
13403
+ ]);
13404
+ /**
13405
+ * @license lucide-react v0.462.0 - ISC
13406
+ *
13407
+ * This source code is licensed under the ISC license.
13408
+ * See the LICENSE file in the root directory of this source tree.
13409
+ */
13410
+ const LoaderCircle = createLucideIcon("LoaderCircle", [
13411
+ ["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]
13412
+ ]);
13413
+ /**
13414
+ * @license lucide-react v0.462.0 - ISC
13415
+ *
13416
+ * This source code is licensed under the ISC license.
13417
+ * See the LICENSE file in the root directory of this source tree.
13418
+ */
13419
+ const LockKeyhole = createLucideIcon("LockKeyhole", [
13420
+ ["circle", { cx: "12", cy: "16", r: "1", key: "1au0dj" }],
13421
+ ["rect", { x: "3", y: "10", width: "18", height: "12", rx: "2", key: "6s8ecr" }],
13422
+ ["path", { d: "M7 10V7a5 5 0 0 1 10 0v3", key: "1pqi11" }]
13423
+ ]);
13424
+ /**
13425
+ * @license lucide-react v0.462.0 - ISC
13426
+ *
13427
+ * This source code is licensed under the ISC license.
13428
+ * See the LICENSE file in the root directory of this source tree.
13429
+ */
13430
+ const ShieldCheck = createLucideIcon("ShieldCheck", [
13431
+ [
13432
+ "path",
13433
+ {
13434
+ d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
13435
+ key: "oel41y"
13436
+ }
13437
+ ],
13438
+ ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
13439
+ ]);
13440
+ const PasswordRedirectModal = ({ open, onOpenChange, saasApiUrl, iamApiUrl }) => {
13441
+ const [confirmOpen, setConfirmOpen] = useState(false);
13442
+ const [loading, setLoading] = useState(false);
13443
+ const [errorMessage, setErrorMessage] = useState(null);
13444
+ const apiBaseUrl = useMemo(() => {
13445
+ const source = saasApiUrl || iamApiUrl;
13446
+ if (!source) {
13447
+ return "";
13448
+ }
13449
+ const normalized = source.replace(/\/$/, "");
13450
+ return normalized.endsWith("/api") ? normalized : `${normalized}/api`;
13451
+ }, [saasApiUrl, iamApiUrl]);
13452
+ const buildUrl = (redirectUrl, magicToken) => {
13453
+ if (redirectUrl) {
13454
+ return redirectUrl;
13455
+ }
13456
+ if (magicToken) {
13457
+ const fallbackUrl = new URL("/auth/auto-connect", "https://iam.ollaid.com");
13458
+ fallbackUrl.searchParams.set("magic_token", magicToken);
13459
+ return fallbackUrl.toString();
13460
+ }
13461
+ return "";
13462
+ };
13463
+ const handleRedirect = async () => {
13464
+ if (loading) return;
13465
+ setLoading(true);
13466
+ setErrorMessage(null);
13467
+ try {
13468
+ const authToken = getAuthToken();
13469
+ const appAccessTokenRef = getNativeStorage().getItem(STORAGE.APP_ACCESS_TOKEN_REF);
13470
+ if (!authToken && !appAccessTokenRef) {
13471
+ throw new Error("Session Native SSO introuvable");
13472
+ }
13473
+ if (!apiBaseUrl) {
13474
+ throw new Error("saasApiUrl non configurée");
13475
+ }
13476
+ const result = await fetchWithTimeout(
13477
+ `${apiBaseUrl}/native/password-link`,
13478
+ {
13479
+ method: "POST",
13480
+ headers: getHeaders(authToken || void 0, true)
13481
+ },
13482
+ 2e4
13483
+ );
13484
+ if (!result.success) {
13485
+ throw new Error(result.message || "Impossible de générer le lien");
13486
+ }
13487
+ const redirectUrl = buildUrl(
13488
+ typeof result.redirect_url === "string" && result.redirect_url.length > 0 ? result.redirect_url : typeof result.sso_url === "string" && result.sso_url.length > 0 ? result.sso_url : "",
13489
+ result.magic_token
13490
+ );
13491
+ if (!redirectUrl) {
13492
+ throw new Error("URL de redirection manquante");
13493
+ }
13494
+ window.open(redirectUrl, "_blank", "noopener,noreferrer");
13495
+ onOpenChange(false);
13496
+ setConfirmOpen(false);
13497
+ } catch (error) {
13498
+ const message = error instanceof ApiError ? error.message : (error == null ? void 0 : error.message) || "Impossible de lancer le flux de mot de passe";
13499
+ setErrorMessage(message);
13500
+ } finally {
13501
+ setLoading(false);
13502
+ }
13503
+ };
13504
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
13505
+ /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { style: { maxWidth: "28rem", borderRadius: "16px", background: "#fff" }, children: [
13506
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
13507
+ /* @__PURE__ */ jsx("div", { style: { margin: "0 auto 12px", width: 56, height: 56, borderRadius: "50%", background: "rgba(232, 67, 10, 0.1)", display: "flex", alignItems: "center", justifyContent: "center", color: "#e8430a" }, children: /* @__PURE__ */ jsx(LockKeyhole, { size: 28 }) }),
13508
+ /* @__PURE__ */ jsx(DialogTitle, { className: "text-center", children: "Mot de passe géré par OLLAID SSO" }),
13509
+ /* @__PURE__ */ jsx(DialogDescription, { className: "text-center", children: "Ce bouton sert à tester la redirection vers IAM et l'ouverture du modal de changement de mot de passe." })
13510
+ ] }),
13511
+ /* @__PURE__ */ jsxs("div", { style: { border: "1px solid #e5e7eb", borderRadius: 12, padding: 16, background: "#f8fafc", color: "#475569", fontSize: 13, display: "grid", gap: 8 }, children: [
13512
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "flex-start" }, children: [
13513
+ /* @__PURE__ */ jsx(ShieldCheck, { size: 16, color: "#e8430a" }),
13514
+ /* @__PURE__ */ jsx("span", { children: "Le SaaS agit comme relais. Le backend SaaS appelle IAM côté serveur, puis renvoie l'URL de redirection." })
13515
+ ] }),
13516
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "flex-start" }, children: [
13517
+ /* @__PURE__ */ jsx(ExternalLink, { size: 16, color: "#e8430a" }),
13518
+ /* @__PURE__ */ jsx("span", { children: "Une fenêtre IAM va s'ouvrir avec auto-connexion temporaire, sans appel direct du navigateur vers IAM." })
13519
+ ] })
13520
+ ] }),
13521
+ /* @__PURE__ */ jsxs(DialogFooter, { style: { gap: 12 }, children: [
13522
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), style: { flex: 1 }, disabled: loading, children: "Fermer" }),
13523
+ /* @__PURE__ */ jsx(Button, { onClick: () => setConfirmOpen(true), disabled: loading, style: { flex: 1 }, children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
13524
+ /* @__PURE__ */ jsx(LoaderCircle, { size: 16, style: { marginRight: 8, animation: "spin 1s linear infinite" } }),
13525
+ "Préparation..."
13526
+ ] }) : "Changer mon mot de passe" })
13527
+ ] })
13528
+ ] }) }),
13529
+ /* @__PURE__ */ jsx(Dialog, { open: confirmOpen, onOpenChange: (nextOpen) => {
13530
+ if (!loading) {
13531
+ setConfirmOpen(nextOpen);
13532
+ }
13533
+ }, children: /* @__PURE__ */ jsxs(DialogContent, { style: { maxWidth: "26rem", borderRadius: "16px", background: "#fff" }, children: [
13534
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
13535
+ /* @__PURE__ */ jsx(DialogTitle, { className: "text-center", children: "Êtes-vous sûr de rediriger vers le SSO ?" }),
13536
+ /* @__PURE__ */ jsx(DialogDescription, { className: "text-center", children: "Cette action ouvre IAM dans un nouvel onglet et prépare l'auto-connexion pour tester le changement de mot de passe." })
13537
+ ] }),
13538
+ errorMessage && /* @__PURE__ */ jsx("div", { style: { border: "1px solid #fecaca", background: "#fef2f2", color: "#b91c1c", borderRadius: 12, padding: 12, fontSize: 13 }, children: errorMessage }),
13539
+ loading && /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 10, padding: "8px 0 4px" }, children: [
13540
+ /* @__PURE__ */ jsx(LoaderCircle, { size: 26, style: { animation: "spin 1s linear infinite", color: "#e8430a" } }),
13541
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13, color: "#475569", textAlign: "center" }, children: "Création de la session en cours..." })
13542
+ ] }),
13543
+ /* @__PURE__ */ jsxs(DialogFooter, { style: { gap: 12 }, children: [
13544
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => setConfirmOpen(false), style: { flex: 1 }, disabled: loading, children: "Annuler" }),
13545
+ /* @__PURE__ */ jsx(Button, { onClick: handleRedirect, style: { flex: 1 }, disabled: loading, children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
13546
+ /* @__PURE__ */ jsx(LoaderCircle, { size: 16, style: { marginRight: 8, animation: "spin 1s linear infinite" } }),
13547
+ "Confirmer..."
13548
+ ] }) : "Confirmer" })
13549
+ ] })
13550
+ ] }) })
13551
+ ] });
13552
+ };
13553
+ function DebugPanel({ saasApiUrl, iamApiUrl, onOpenLogin, onOpenSignup, onOpenOnboarding, onOpenPassword, onResetProfilePrompt }) {
13302
13554
  const [logs, setLogs] = useState([]);
13303
13555
  const [expanded, setExpanded] = useState(true);
13304
13556
  const [selectedLog, setSelectedLog] = useState(null);
@@ -13438,6 +13690,18 @@ function DebugPanel({ saasApiUrl, iamApiUrl, onOpenLogin, onOpenSignup, onOpenOn
13438
13690
  children: "Infos profile"
13439
13691
  }
13440
13692
  ),
13693
+ /* @__PURE__ */ jsx(
13694
+ "button",
13695
+ {
13696
+ onClick: (e) => {
13697
+ e.stopPropagation();
13698
+ onOpenPassword == null ? void 0 : onOpenPassword();
13699
+ },
13700
+ disabled: !onOpenPassword,
13701
+ style: { background: "#334155", color: "#e2e8f0", border: "none", borderRadius: "4px", padding: "2px 8px", cursor: onOpenPassword ? "pointer" : "not-allowed", fontSize: "11px", opacity: onOpenPassword ? 1 : 0.5 },
13702
+ children: "Mot de passe"
13703
+ }
13704
+ ),
13441
13705
  /* @__PURE__ */ jsx(
13442
13706
  "button",
13443
13707
  {
@@ -13631,6 +13895,7 @@ function NativeSSOPage({
13631
13895
  const [showOnboarding, setShowOnboarding] = useState(false);
13632
13896
  const [pendingSession, setPendingSession] = useState(null);
13633
13897
  const [debugOnboardingState, setDebugOnboardingState] = useState(null);
13898
+ const [passwordRedirectOpen, setPasswordRedirectOpen] = useState(false);
13634
13899
  const [redirectingTarget, setRedirectingTarget] = useState(null);
13635
13900
  const [redirectingReason, setRedirectingReason] = useState(null);
13636
13901
  const [session, setSession] = useState(() => {
@@ -14003,6 +14268,9 @@ function NativeSSOPage({
14003
14268
  setShowOnboarding(true);
14004
14269
  }
14005
14270
  }, [session, clearOnboardingTimers]);
14271
+ const openDebugPassword = useCallback(() => {
14272
+ setPasswordRedirectOpen(true);
14273
+ }, []);
14006
14274
  useEffect(() => {
14007
14275
  syncProfilePrompt(session);
14008
14276
  return () => {
@@ -14150,8 +14418,18 @@ function NativeSSOPage({
14150
14418
  onOpenLogin: openDebugLogin,
14151
14419
  onOpenSignup: openDebugSignup,
14152
14420
  onOpenOnboarding: openDebugOnboarding,
14421
+ onOpenPassword: openDebugPassword,
14153
14422
  onResetProfilePrompt: resetDebugProfilePrompt
14154
14423
  }
14424
+ ),
14425
+ /* @__PURE__ */ jsx(
14426
+ PasswordRedirectModal,
14427
+ {
14428
+ open: passwordRedirectOpen,
14429
+ onOpenChange: setPasswordRedirectOpen,
14430
+ saasApiUrl,
14431
+ iamApiUrl
14432
+ }
14155
14433
  )
14156
14434
  ] });
14157
14435
  }
@@ -14231,8 +14509,18 @@ function NativeSSOPage({
14231
14509
  onOpenLogin: openDebugLogin,
14232
14510
  onOpenSignup: openDebugSignup,
14233
14511
  onOpenOnboarding: openDebugOnboarding,
14512
+ onOpenPassword: openDebugPassword,
14234
14513
  onResetProfilePrompt: resetDebugProfilePrompt
14235
14514
  }
14515
+ ),
14516
+ /* @__PURE__ */ jsx(
14517
+ PasswordRedirectModal,
14518
+ {
14519
+ open: passwordRedirectOpen,
14520
+ onOpenChange: setPasswordRedirectOpen,
14521
+ saasApiUrl,
14522
+ iamApiUrl
14523
+ }
14236
14524
  )
14237
14525
  ] });
14238
14526
  }