@authagonal/login 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4434,7 +4434,13 @@ J.use(Tr).use(P).init({
4434
4434
  caches: ["localStorage"]
4435
4435
  }
4436
4436
  });
4437
- var Pr = J, Fr = [
4437
+ var Pr = J;
4438
+ //#endregion
4439
+ //#region src/components/AuthLayout.tsx
4440
+ function Fr(e) {
4441
+ return /^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e) || /^(?:rgb|rgba|hsl|hsla)\([0-9.,%\s/]+\)$/i.test(e);
4442
+ }
4443
+ var Ir = [
4438
4444
  {
4439
4445
  code: "en",
4440
4446
  label: "English"
@@ -4468,7 +4474,7 @@ var Pr = J, Fr = [
4468
4474
  label: "tlhIngan"
4469
4475
  }
4470
4476
  ];
4471
- function Ir() {
4477
+ function Lr() {
4472
4478
  let { theme: e, setTheme: t } = fe(), n = [
4473
4479
  {
4474
4480
  value: "light",
@@ -4496,15 +4502,17 @@ function Ir() {
4496
4502
  }, n))
4497
4503
  });
4498
4504
  }
4499
- function Lr({ children: e }) {
4505
+ function Rr({ children: e }) {
4500
4506
  let t = se(), { i18n: n } = L();
4501
4507
  return fe(), a(() => {
4502
- if (document.documentElement.style.setProperty("--brand-primary", t.primaryColor), t.customCssUrl) {
4503
- let e = document.createElement("link");
4504
- return e.rel = "stylesheet", e.href = t.customCssUrl, e.id = "branding-css", document.head.appendChild(e), () => {
4505
- e.remove();
4506
- };
4507
- }
4508
+ if (t.primaryColor && Fr(t.primaryColor) && document.documentElement.style.setProperty("--brand-primary", t.primaryColor), t.customCssUrl) try {
4509
+ if (new URL(t.customCssUrl, window.location.origin).origin === window.location.origin) {
4510
+ let e = document.createElement("link");
4511
+ return e.rel = "stylesheet", e.href = t.customCssUrl, e.id = "branding-css", document.head.appendChild(e), () => {
4512
+ e.remove();
4513
+ };
4514
+ }
4515
+ } catch {}
4508
4516
  }, [t]), /* @__PURE__ */ l("div", {
4509
4517
  className: "min-h-screen flex items-center justify-center p-4",
4510
4518
  "data-auth": "page",
@@ -4538,32 +4546,32 @@ function Lr({ children: e }) {
4538
4546
  /* @__PURE__ */ l("div", {
4539
4547
  className: "flex flex-wrap justify-center gap-1 mt-6 pt-4 border-t border-gray-200 dark:border-gray-800",
4540
4548
  "data-auth": "languages",
4541
- children: (t.languages ?? Fr).map((e) => /* @__PURE__ */ l("button", {
4549
+ children: (t.languages ?? Ir).map((e) => /* @__PURE__ */ l("button", {
4542
4550
  type: "button",
4543
4551
  className: U("bg-transparent border-none px-2 py-1 text-xs rounded cursor-pointer transition-colors", n.language === e.code || n.language?.startsWith(e.code) ? "text-primary font-semibold" : "text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"),
4544
4552
  onClick: () => n.changeLanguage(e.code),
4545
4553
  children: e.label
4546
4554
  }, e.code))
4547
4555
  }),
4548
- /* @__PURE__ */ l(Ir, {})
4556
+ /* @__PURE__ */ l(Lr, {})
4549
4557
  ]
4550
4558
  })
4551
4559
  });
4552
4560
  }
4553
4561
  //#endregion
4554
4562
  //#region node_modules/class-variance-authority/dist/index.mjs
4555
- var Rr = (e) => typeof e == "boolean" ? `${e}` : e === 0 ? "0" : e, zr = me, Br = (e, t) => (n) => {
4556
- if (t?.variants == null) return zr(e, n?.class, n?.className);
4563
+ var zr = (e) => typeof e == "boolean" ? `${e}` : e === 0 ? "0" : e, Br = me, Vr = (e, t) => (n) => {
4564
+ if (t?.variants == null) return Br(e, n?.class, n?.className);
4557
4565
  let { variants: r, defaultVariants: i } = t, a = Object.keys(r).map((e) => {
4558
4566
  let t = n?.[e], a = i?.[e];
4559
4567
  if (t === null) return null;
4560
- let o = Rr(t) || Rr(a);
4568
+ let o = zr(t) || zr(a);
4561
4569
  return r[e][o];
4562
4570
  }), o = n && Object.entries(n).reduce((e, t) => {
4563
4571
  let [n, r] = t;
4564
4572
  return r === void 0 || (e[n] = r), e;
4565
4573
  }, {});
4566
- return zr(e, a, t?.compoundVariants?.reduce((e, t) => {
4574
+ return Br(e, a, t?.compoundVariants?.reduce((e, t) => {
4567
4575
  let { class: n, className: r, ...a } = t;
4568
4576
  return Object.entries(a).every((e) => {
4569
4577
  let [t, n] = e;
@@ -4580,7 +4588,7 @@ var Rr = (e) => typeof e == "boolean" ? `${e}` : e === 0 ? "0" : e, zr = me, Br
4580
4588
  r
4581
4589
  ] : e;
4582
4590
  }, []), n?.class, n?.className);
4583
- }, Vr = Br("inline-flex w-full items-center justify-center gap-2 rounded-md text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 cursor-pointer", {
4591
+ }, Hr = Vr("inline-flex w-full items-center justify-center gap-2 rounded-md text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 cursor-pointer", {
4584
4592
  variants: {
4585
4593
  variant: {
4586
4594
  default: "bg-primary text-white hover:bg-primary/85",
@@ -4598,7 +4606,7 @@ var Rr = (e) => typeof e == "boolean" ? `${e}` : e === 0 ? "0" : e, zr = me, Br
4598
4606
  size: "default"
4599
4607
  }
4600
4608
  }), Y = n(({ className: e, variant: t, size: n, loading: r, children: i, disabled: a, ...o }, s) => /* @__PURE__ */ u("button", {
4601
- className: U(Vr({
4609
+ className: U(Hr({
4602
4610
  variant: t,
4603
4611
  size: n,
4604
4612
  className: e
@@ -4628,7 +4636,7 @@ var Z = n(({ className: e, ...t }, n) => /* @__PURE__ */ l("label", {
4628
4636
  Z.displayName = "Label";
4629
4637
  //#endregion
4630
4638
  //#region src/components/ui/alert.tsx
4631
- var Hr = Br("rounded-md border px-3 py-2.5 text-sm mb-4", {
4639
+ var Ur = Vr("rounded-md border px-3 py-2.5 text-sm mb-4", {
4632
4640
  variants: { variant: {
4633
4641
  error: "bg-red-50 text-red-800 border-red-200 dark:bg-red-950/40 dark:text-red-300 dark:border-red-900",
4634
4642
  success: "bg-green-50 text-green-800 border-green-200 dark:bg-green-950/40 dark:text-green-300 dark:border-green-900"
@@ -4636,7 +4644,7 @@ var Hr = Br("rounded-md border px-3 py-2.5 text-sm mb-4", {
4636
4644
  defaultVariants: { variant: "error" }
4637
4645
  }), Q = n(({ className: e, variant: t, ...n }, r) => /* @__PURE__ */ l("div", {
4638
4646
  ref: r,
4639
- className: U(Hr({
4647
+ className: U(Ur({
4640
4648
  variant: t,
4641
4649
  className: e
4642
4650
  })),
@@ -4645,7 +4653,7 @@ var Hr = Br("rounded-md border px-3 py-2.5 text-sm mb-4", {
4645
4653
  Q.displayName = "Alert";
4646
4654
  //#endregion
4647
4655
  //#region src/components/ui/separator.tsx
4648
- function Ur({ label: e, className: t }) {
4656
+ function Wr({ label: e, className: t }) {
4649
4657
  return /* @__PURE__ */ u("div", {
4650
4658
  className: U("flex items-center gap-3 my-4 text-gray-400 dark:text-gray-500 text-[13px]", t),
4651
4659
  children: [
@@ -4657,7 +4665,7 @@ function Ur({ label: e, className: t }) {
4657
4665
  }
4658
4666
  //#endregion
4659
4667
  //#region src/api.ts
4660
- var Wr = "", Gr = class extends Error {
4668
+ var Gr = "", Kr = class extends Error {
4661
4669
  error;
4662
4670
  retryAfter;
4663
4671
  redirectUrl;
@@ -4666,7 +4674,7 @@ var Wr = "", Gr = class extends Error {
4666
4674
  }
4667
4675
  };
4668
4676
  async function $(e, t) {
4669
- let n = `${Wr}${e}`, r = await fetch(n, {
4677
+ let n = `${Gr}${e}`, r = await fetch(n, {
4670
4678
  ...t,
4671
4679
  credentials: "include",
4672
4680
  headers: {
@@ -4684,14 +4692,14 @@ async function $(e, t) {
4684
4692
  message: `Request failed with status ${r.status}`
4685
4693
  };
4686
4694
  }
4687
- throw new Gr(e);
4695
+ throw new Kr(e);
4688
4696
  }
4689
4697
  return r.json();
4690
4698
  }
4691
- function Kr(e) {
4699
+ function qr(e) {
4692
4700
  return e ? { "X-MFA-Setup-Token": e } : {};
4693
4701
  }
4694
- function qr(e, t, n) {
4702
+ function Jr(e, t, n) {
4695
4703
  return $(n ? `/api/auth/login?returnUrl=${encodeURIComponent(n)}` : "/api/auth/login", {
4696
4704
  method: "POST",
4697
4705
  body: JSON.stringify({
@@ -4700,7 +4708,7 @@ function qr(e, t, n) {
4700
4708
  })
4701
4709
  });
4702
4710
  }
4703
- function Jr(e, t, n, r) {
4711
+ function Yr(e, t, n, r) {
4704
4712
  return $("/api/auth/register", {
4705
4713
  method: "POST",
4706
4714
  body: JSON.stringify({
@@ -4711,16 +4719,16 @@ function Jr(e, t, n, r) {
4711
4719
  })
4712
4720
  });
4713
4721
  }
4714
- function Yr() {
4722
+ function Xr() {
4715
4723
  return $("/api/auth/logout", { method: "POST" });
4716
4724
  }
4717
- function Xr(e) {
4725
+ function Zr(e) {
4718
4726
  return $("/api/auth/forgot-password", {
4719
4727
  method: "POST",
4720
4728
  body: JSON.stringify({ email: e })
4721
4729
  });
4722
4730
  }
4723
- function Zr(e, t) {
4731
+ function Qr(e, t) {
4724
4732
  return $("/api/auth/reset-password", {
4725
4733
  method: "POST",
4726
4734
  body: JSON.stringify({
@@ -4729,19 +4737,19 @@ function Zr(e, t) {
4729
4737
  })
4730
4738
  });
4731
4739
  }
4732
- function Qr() {
4740
+ function $r() {
4733
4741
  return $("/api/auth/session");
4734
4742
  }
4735
- function $r(e) {
4743
+ function ei(e) {
4736
4744
  return $(`/api/auth/sso-check?email=${encodeURIComponent(e)}`);
4737
4745
  }
4738
- function ei() {
4746
+ function ti() {
4739
4747
  return $("/api/auth/providers");
4740
4748
  }
4741
- function ti() {
4749
+ function ni() {
4742
4750
  return $("/api/auth/password-policy");
4743
4751
  }
4744
- function ni(e, t, n, r) {
4752
+ function ri(e, t, n, r) {
4745
4753
  return $("/api/auth/mfa/verify", {
4746
4754
  method: "POST",
4747
4755
  body: JSON.stringify({
@@ -4752,57 +4760,57 @@ function ni(e, t, n, r) {
4752
4760
  })
4753
4761
  });
4754
4762
  }
4755
- function ri(e) {
4756
- return $("/api/auth/mfa/status", { headers: Kr(e) });
4757
- }
4758
4763
  function ii(e) {
4764
+ return $("/api/auth/mfa/status", { headers: qr(e) });
4765
+ }
4766
+ function ai(e) {
4759
4767
  return $("/api/auth/mfa/totp/setup", {
4760
4768
  method: "POST",
4761
- headers: Kr(e)
4769
+ headers: qr(e)
4762
4770
  });
4763
4771
  }
4764
- function ai(e, t, n) {
4772
+ function oi(e, t, n) {
4765
4773
  return $("/api/auth/mfa/totp/confirm", {
4766
4774
  method: "POST",
4767
4775
  body: JSON.stringify({
4768
4776
  setupToken: e,
4769
4777
  code: t
4770
4778
  }),
4771
- headers: Kr(n)
4779
+ headers: qr(n)
4772
4780
  });
4773
4781
  }
4774
- function oi(e) {
4782
+ function si(e) {
4775
4783
  return $("/api/auth/mfa/recovery/generate", {
4776
4784
  method: "POST",
4777
- headers: Kr(e)
4785
+ headers: qr(e)
4778
4786
  });
4779
4787
  }
4780
- function si(e) {
4788
+ function ci(e) {
4781
4789
  return $("/api/auth/mfa/webauthn/setup", {
4782
4790
  method: "POST",
4783
- headers: Kr(e)
4791
+ headers: qr(e)
4784
4792
  });
4785
4793
  }
4786
- function ci(e, t, n) {
4794
+ function li(e, t, n) {
4787
4795
  return $("/api/auth/mfa/webauthn/confirm", {
4788
4796
  method: "POST",
4789
4797
  body: JSON.stringify({
4790
4798
  setupToken: e,
4791
4799
  attestationResponse: t
4792
4800
  }),
4793
- headers: Kr(n)
4801
+ headers: qr(n)
4794
4802
  });
4795
4803
  }
4796
- function li(e, t) {
4804
+ function ui(e, t) {
4797
4805
  return $(`/api/auth/mfa/credentials/${e}`, {
4798
4806
  method: "DELETE",
4799
- headers: Kr(t)
4807
+ headers: qr(t)
4800
4808
  });
4801
4809
  }
4802
4810
  //#endregion
4803
4811
  //#region src/pages/LoginPage.tsx
4804
- var ui = "";
4805
- function di(e) {
4812
+ var di = "";
4813
+ function fi(e) {
4806
4814
  if (!e) return !1;
4807
4815
  try {
4808
4816
  return new URL(e, window.location.origin).origin === window.location.origin && e.startsWith("/");
@@ -4810,12 +4818,12 @@ function di(e) {
4810
4818
  return !1;
4811
4819
  }
4812
4820
  }
4813
- function fi() {
4821
+ function pi() {
4814
4822
  let { t: e } = L(), t = se(), n = g(), [i] = _(), d = i.get("returnUrl") || "", p = i.get("login_hint") || "", m = i.get("error_description") || i.get("error") || "", h = i.get("message") || "", [v, y] = s(p), [b, x] = s(""), [S, C] = s(m), [w] = s(() => h === "registration_success" ? e("registrationSuccess") : ""), [T, E] = s(!1), [D, O] = s(null), [k, A] = s(!1), [j, M] = s(!1), [N, ee] = s([]), [te, P] = s(null), [F, ne] = s(null), re = o(null), ie = o(""), I = r(async (e) => {
4815
4823
  if (!(!e.includes("@") || e === ie.current)) {
4816
4824
  ie.current = e, M(!0), C("");
4817
4825
  try {
4818
- let t = await $r(e);
4826
+ let t = await ei(e);
4819
4827
  t.ssoRequired && t.redirectUrl ? O({ redirectUrl: t.redirectUrl }) : O(null), A(!0);
4820
4828
  } catch {
4821
4829
  O(null), A(!0);
@@ -4825,14 +4833,14 @@ function fi() {
4825
4833
  }
4826
4834
  }, []);
4827
4835
  a(() => {
4828
- d && di(d) || Qr().then((e) => {
4836
+ d && fi(d) || $r().then((e) => {
4829
4837
  e.authenticated && P({
4830
4838
  name: e.name,
4831
4839
  email: e.email
4832
4840
  });
4833
4841
  }).catch(() => {});
4834
4842
  }, [d]), a(() => {
4835
- ei().then((e) => ee(e.providers ?? [])).catch(() => {});
4843
+ ti().then((e) => ee(e.providers ?? [])).catch(() => {});
4836
4844
  }, []), a(() => {
4837
4845
  p && p.includes("@") && I(p);
4838
4846
  }, [p, I]);
@@ -4845,19 +4853,19 @@ function fi() {
4845
4853
  y(e), e !== ie.current && (A(!1), O(null));
4846
4854
  }
4847
4855
  function R(e) {
4848
- let t = new URL(`${ui}${e.loginUrl}`, window.location.origin);
4849
- d && di(d) && t.searchParams.set("returnUrl", d), window.location.href = t.toString();
4856
+ let t = new URL(`${di}${e.loginUrl}`, window.location.origin);
4857
+ d && fi(d) && t.searchParams.set("returnUrl", d), window.location.href = t.toString();
4850
4858
  }
4851
4859
  function ce() {
4852
4860
  if (D) {
4853
- let e = new URL(`${ui}${D.redirectUrl}`, window.location.origin);
4854
- d && di(d) && e.searchParams.set("returnUrl", d), v && e.searchParams.set("loginHint", v), window.location.href = e.toString();
4861
+ let e = new URL(`${di}${D.redirectUrl}`, window.location.origin);
4862
+ d && fi(d) && e.searchParams.set("returnUrl", d), v && e.searchParams.set("loginHint", v), window.location.href = e.toString();
4855
4863
  }
4856
4864
  }
4857
4865
  async function le(t) {
4858
4866
  t.preventDefault(), C(""), E(!0);
4859
4867
  try {
4860
- let e = await qr(v, b, d || void 0);
4868
+ let e = await Jr(v, b, d || void 0);
4861
4869
  if (e.mfaRequired && e.challengeId) {
4862
4870
  n(`/mfa-challenge?${new URLSearchParams({
4863
4871
  challengeId: e.challengeId,
@@ -4885,9 +4893,9 @@ function fi() {
4885
4893
  return;
4886
4894
  }
4887
4895
  }
4888
- d && di(d) ? window.location.href = d : window.location.href = "/";
4896
+ d && fi(d) ? window.location.href = d : window.location.href = "/";
4889
4897
  } catch (t) {
4890
- if (t instanceof Gr) switch (t.error) {
4898
+ if (t instanceof Kr) switch (t.error) {
4891
4899
  case "invalid_credentials":
4892
4900
  C(e("errorInvalidCredentials"));
4893
4901
  break;
@@ -4899,8 +4907,8 @@ function fi() {
4899
4907
  break;
4900
4908
  case "sso_required":
4901
4909
  if (t.redirectUrl) {
4902
- let e = new URL(`${ui}${t.redirectUrl}`, window.location.origin);
4903
- d && di(d) && e.searchParams.set("returnUrl", d), window.location.href = e.toString();
4910
+ let e = new URL(`${di}${t.redirectUrl}`, window.location.origin);
4911
+ d && fi(d) && e.searchParams.set("returnUrl", d), window.location.href = e.toString();
4904
4912
  return;
4905
4913
  }
4906
4914
  C(e("errorSsoRequired"));
@@ -4918,7 +4926,7 @@ function fi() {
4918
4926
  E(!1);
4919
4927
  }
4920
4928
  }
4921
- let ue = d && di(d) ? `/forgot-password?returnUrl=${encodeURIComponent(d)}` : "/forgot-password", de = k && !D;
4929
+ let ue = d && fi(d) ? `/forgot-password?returnUrl=${encodeURIComponent(d)}` : "/forgot-password", de = k && !D;
4922
4930
  return F ? /* @__PURE__ */ u("div", { children: [
4923
4931
  /* @__PURE__ */ l(W, { children: e("mfaPromptTitle") }),
4924
4932
  /* @__PURE__ */ l("p", {
@@ -4934,7 +4942,7 @@ function fi() {
4934
4942
  variant: "secondary",
4935
4943
  onClick: () => {
4936
4944
  localStorage.setItem(`mfa-prompt-dismissed:${F.userId}:${F.clientId}`, "1");
4937
- let e = F.returnUrl && di(F.returnUrl) ? F.returnUrl : "/";
4945
+ let e = F.returnUrl && fi(F.returnUrl) ? F.returnUrl : "/";
4938
4946
  window.location.href = e;
4939
4947
  },
4940
4948
  children: e("mfaPromptSkip")
@@ -4948,7 +4956,7 @@ function fi() {
4948
4956
  /* @__PURE__ */ l(G, { children: /* @__PURE__ */ l(Y, {
4949
4957
  variant: "secondary",
4950
4958
  onClick: () => {
4951
- Yr().then(() => {
4959
+ Xr().then(() => {
4952
4960
  P(null);
4953
4961
  }).catch(() => {
4954
4962
  P(null);
@@ -4989,7 +4997,7 @@ function fi() {
4989
4997
  })
4990
4998
  ]
4991
4999
  }), e("continueWith", { provider: t.name })]
4992
- }, t.connectionId)), /* @__PURE__ */ l(Ur, { label: e("or") })]
5000
+ }, t.connectionId)), /* @__PURE__ */ l(Wr, { label: e("or") })]
4993
5001
  }),
4994
5002
  N.length > 0 && de && /* @__PURE__ */ u("div", {
4995
5003
  className: "flex items-center gap-3 mb-4 text-gray-400 dark:text-gray-500 text-[13px]",
@@ -5114,19 +5122,19 @@ function fi() {
5114
5122
  }
5115
5123
  //#endregion
5116
5124
  //#region src/pages/RegisterPage.tsx
5117
- function pi() {
5125
+ function mi() {
5118
5126
  let { t: e } = L(), t = g(), [n] = _(), r = n.get("returnUrl") || "", [i, a] = s(""), [o, c] = s(""), [d, p] = s(""), [m, h] = s(""), [v, y] = s(""), [b, x] = s(!1), [S, C] = s([]), [w, T] = s(!1);
5119
5127
  function E() {
5120
- w || ti().then((e) => C(e.rules)).catch(() => {}).finally(() => T(!0));
5128
+ w || ni().then((e) => C(e.rules)).catch(() => {}).finally(() => T(!0));
5121
5129
  }
5122
5130
  async function D(n) {
5123
5131
  n.preventDefault(), y(""), x(!0);
5124
5132
  try {
5125
- await Jr(i, o, d || void 0, m || void 0);
5133
+ await Yr(i, o, d || void 0, m || void 0);
5126
5134
  let e = new URLSearchParams();
5127
5135
  r && e.set("returnUrl", r), e.set("login_hint", i), e.set("message", "registration_success"), t(`/login?${e.toString()}`);
5128
5136
  } catch (t) {
5129
- if (t instanceof Gr) switch (t.error) {
5137
+ if (t instanceof Kr) switch (t.error) {
5130
5138
  case "email_already_registered":
5131
5139
  y(e("errorEmailAlreadyRegistered"));
5132
5140
  break;
@@ -5246,12 +5254,12 @@ function pi() {
5246
5254
  }
5247
5255
  //#endregion
5248
5256
  //#region src/pages/ForgotPasswordPage.tsx
5249
- function mi() {
5257
+ function hi() {
5250
5258
  let { t: e } = L(), [t] = _(), n = t.get("returnUrl") || "", [r, i] = s(""), [a, o] = s(!1), [c, d] = s(!1), [p, m] = s(""), h = n ? `/login?returnUrl=${encodeURIComponent(n)}` : "/login";
5251
5259
  async function g(t) {
5252
5260
  t.preventDefault(), m(""), o(!0);
5253
5261
  try {
5254
- await Xr(r), d(!0);
5262
+ await Zr(r), d(!0);
5255
5263
  } catch {
5256
5264
  m(e("errorUnexpected"));
5257
5265
  } finally {
@@ -5315,7 +5323,7 @@ function mi() {
5315
5323
  }
5316
5324
  //#endregion
5317
5325
  //#region src/pages/ResetPasswordPage.tsx
5318
- var hi = "", gi = [
5326
+ var gi = "", _i = [
5319
5327
  {
5320
5328
  rule: "minLength",
5321
5329
  value: 8,
@@ -5342,7 +5350,7 @@ var hi = "", gi = [
5342
5350
  label: "Special character"
5343
5351
  }
5344
5352
  ];
5345
- function _i(e, t) {
5353
+ function vi(e, t) {
5346
5354
  return t.map((t) => {
5347
5355
  let n = !1;
5348
5356
  switch (t.rule) {
@@ -5369,10 +5377,10 @@ function _i(e, t) {
5369
5377
  };
5370
5378
  });
5371
5379
  }
5372
- function vi() {
5373
- let { t: e } = L(), [t] = _(), n = t.get("p") || "", [r, i] = s(""), [o, c] = s(""), [d, p] = s(!1), [m, h] = s(""), [g, v] = s(!1), [y, b] = s(""), [x, S] = s(gi);
5380
+ function yi() {
5381
+ let { t: e } = L(), [t] = _(), n = t.get("p") || "", [r, i] = s(""), [o, c] = s(""), [d, p] = s(!1), [m, h] = s(""), [g, v] = s(!1), [y, b] = s(""), [x, S] = s(_i);
5374
5382
  a(() => {
5375
- fetch(`${hi}/api/auth/password-policy`).then((e) => e.ok ? e.json() : null).then((e) => {
5383
+ fetch(`${gi}/api/auth/password-policy`).then((e) => e.ok ? e.json() : null).then((e) => {
5376
5384
  e?.rules && S(e.rules);
5377
5385
  }).catch(() => {});
5378
5386
  }, []);
@@ -5386,7 +5394,7 @@ function vi() {
5386
5394
  default: return t.label;
5387
5395
  }
5388
5396
  }
5389
- let w = _i(r, x.map((e) => ({
5397
+ let w = vi(r, x.map((e) => ({
5390
5398
  ...e,
5391
5399
  label: C(e)
5392
5400
  }))), T = w.every((e) => e.met);
@@ -5401,9 +5409,9 @@ function vi() {
5401
5409
  }
5402
5410
  p(!0);
5403
5411
  try {
5404
- await Zr(n, r), v(!0);
5412
+ await Qr(n, r), v(!0);
5405
5413
  } catch (t) {
5406
- if (t instanceof Gr) switch (t.error) {
5414
+ if (t instanceof Kr) switch (t.error) {
5407
5415
  case "weak_password":
5408
5416
  h(t.message || e("passwordWeakError"));
5409
5417
  break;
@@ -5513,7 +5521,7 @@ function vi() {
5513
5521
  }
5514
5522
  //#endregion
5515
5523
  //#region src/pages/MfaChallengePage.tsx
5516
- function yi(e) {
5524
+ function bi(e) {
5517
5525
  if (!e) return !1;
5518
5526
  try {
5519
5527
  return new URL(e, window.location.origin).origin === window.location.origin && e.startsWith("/");
@@ -5521,21 +5529,21 @@ function yi(e) {
5521
5529
  return !1;
5522
5530
  }
5523
5531
  }
5524
- function bi(e) {
5532
+ function xi(e) {
5525
5533
  let t = e.replace(/-/g, "+").replace(/_/g, "/"), n = t.length % 4 == 0 ? "" : "=".repeat(4 - t.length % 4), r = atob(t + n), i = new Uint8Array(r.length);
5526
5534
  for (let e = 0; e < r.length; e++) i[e] = r.charCodeAt(e);
5527
5535
  return i.buffer;
5528
5536
  }
5529
- function xi(e) {
5537
+ function Si(e) {
5530
5538
  let t = new Uint8Array(e), n = "";
5531
5539
  for (let e of t) n += String.fromCharCode(e);
5532
5540
  return btoa(n).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
5533
5541
  }
5534
- function Si() {
5542
+ function Ci() {
5535
5543
  let { t: e } = L(), [t] = _(), n = t.get("challengeId") || "", i = t.get("returnUrl") || "", a = t.get("methods") || "", o = a ? a.split(",") : [], c = o.includes("webauthn"), [d, f] = s(c ? "webauthn" : o.includes("totp") ? "totp" : o[0] || "totp"), [p, m] = s(""), [h, g] = s(""), [v, y] = s(!1), b = r(() => {
5536
- i && yi(i) ? window.location.href = i : window.location.href = "/";
5544
+ i && bi(i) ? window.location.href = i : window.location.href = "/";
5537
5545
  }, [i]), x = r((t) => {
5538
- if (t instanceof Gr) switch (t.error) {
5546
+ if (t instanceof Kr) switch (t.error) {
5539
5547
  case "invalid_code":
5540
5548
  case "assertion_failed":
5541
5549
  g(e("mfaInvalidCode"));
@@ -5556,12 +5564,12 @@ function Si() {
5556
5564
  return;
5557
5565
  }
5558
5566
  let i = JSON.parse(r), a = {
5559
- challenge: bi(i.challenge),
5567
+ challenge: xi(i.challenge),
5560
5568
  rpId: i.rpId,
5561
5569
  timeout: i.timeout || 6e4,
5562
5570
  userVerification: i.userVerification || "preferred",
5563
5571
  allowCredentials: (i.allowCredentials || []).map((e) => ({
5564
- id: bi(e.id),
5572
+ id: xi(e.id),
5565
5573
  type: e.type,
5566
5574
  transports: e.transports
5567
5575
  }))
@@ -5571,15 +5579,15 @@ function Si() {
5571
5579
  return;
5572
5580
  }
5573
5581
  let s = o.response;
5574
- await ni(n, "webauthn", void 0, JSON.stringify({
5582
+ await ri(n, "webauthn", void 0, JSON.stringify({
5575
5583
  id: o.id,
5576
- rawId: xi(o.rawId),
5584
+ rawId: Si(o.rawId),
5577
5585
  type: o.type,
5578
5586
  response: {
5579
- authenticatorData: xi(s.authenticatorData),
5580
- clientDataJSON: xi(s.clientDataJSON),
5581
- signature: xi(s.signature),
5582
- userHandle: s.userHandle ? xi(s.userHandle) : null
5587
+ authenticatorData: Si(s.authenticatorData),
5588
+ clientDataJSON: Si(s.clientDataJSON),
5589
+ signature: Si(s.signature),
5590
+ userHandle: s.userHandle ? Si(s.userHandle) : null
5583
5591
  }
5584
5592
  })), b();
5585
5593
  } catch (t) {
@@ -5592,7 +5600,7 @@ function Si() {
5592
5600
  if (e.preventDefault(), p.trim()) {
5593
5601
  g(""), y(!0);
5594
5602
  try {
5595
- await ni(n, d, p), b();
5603
+ await ri(n, d, p), b();
5596
5604
  } catch (e) {
5597
5605
  x(e);
5598
5606
  } finally {
@@ -5686,7 +5694,7 @@ function Si() {
5686
5694
  }
5687
5695
  //#endregion
5688
5696
  //#region src/pages/MfaSetupPage.tsx
5689
- function Ci(e) {
5697
+ function wi(e) {
5690
5698
  if (!e) return !1;
5691
5699
  try {
5692
5700
  return new URL(e, window.location.origin).origin === window.location.origin && e.startsWith("/");
@@ -5694,24 +5702,24 @@ function Ci(e) {
5694
5702
  return !1;
5695
5703
  }
5696
5704
  }
5697
- function wi(e) {
5705
+ function Ti(e) {
5698
5706
  let t = e.replace(/-/g, "+").replace(/_/g, "/"), n = t.length % 4 == 0 ? "" : "=".repeat(4 - t.length % 4), r = atob(t + n), i = new Uint8Array(r.length);
5699
5707
  for (let e = 0; e < r.length; e++) i[e] = r.charCodeAt(e);
5700
5708
  return i.buffer;
5701
5709
  }
5702
- function Ti(e) {
5710
+ function Ei(e) {
5703
5711
  let t = new Uint8Array(e), n = "";
5704
5712
  for (let e of t) n += String.fromCharCode(e);
5705
5713
  return btoa(n).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
5706
5714
  }
5707
- function Ei() {
5715
+ function Di() {
5708
5716
  let { t: e } = L(), [t] = _(), n = t.get("setupToken") || void 0, r = t.get("returnUrl") || "", i = t.get("backUrl") || "", [o, c] = s(!1), [d, f] = s([]), [p, m] = s(""), [h, g] = s(!0), [v, y] = s(null), [b, x] = s(""), [S, C] = s(!1), [w, T] = s(!1), [E, D] = s(null), [O, k] = s(!1);
5709
5717
  a(() => {
5710
5718
  A();
5711
5719
  }, []);
5712
5720
  async function A() {
5713
5721
  try {
5714
- let e = await ri(n);
5722
+ let e = await ii(n);
5715
5723
  c(e.enabled), f(e.methods);
5716
5724
  } catch {
5717
5725
  m(e("errorUnexpected"));
@@ -5720,14 +5728,14 @@ function Ei() {
5720
5728
  }
5721
5729
  }
5722
5730
  function j() {
5723
- n && (r && Ci(r) ? window.location.href = r : window.location.href = "/");
5731
+ n && (r && wi(r) ? window.location.href = r : window.location.href = "/");
5724
5732
  }
5725
5733
  async function M() {
5726
5734
  m(""), C(!0);
5727
5735
  try {
5728
- y(await ii(n));
5736
+ y(await ai(n));
5729
5737
  } catch (t) {
5730
- t instanceof Gr && t.error === "totp_already_enrolled" ? m(e("mfaTotpAlreadyEnrolled")) : m(e("errorUnexpected"));
5738
+ t instanceof Kr && t.error === "totp_already_enrolled" ? m(e("mfaTotpAlreadyEnrolled")) : m(e("errorUnexpected"));
5731
5739
  } finally {
5732
5740
  C(!1);
5733
5741
  }
@@ -5736,9 +5744,9 @@ function Ei() {
5736
5744
  if (!(!v || !b)) {
5737
5745
  m(""), C(!0);
5738
5746
  try {
5739
- await ai(v.setupToken, b, n), y(null), x(""), j(), await A();
5747
+ await oi(v.setupToken, b, n), y(null), x(""), j(), await A();
5740
5748
  } catch (t) {
5741
- t instanceof Gr && t.error === "invalid_code" ? m(e("mfaInvalidCode")) : m(e("errorUnexpected"));
5749
+ t instanceof Kr && t.error === "invalid_code" ? m(e("mfaInvalidCode")) : m(e("errorUnexpected"));
5742
5750
  } finally {
5743
5751
  C(!1);
5744
5752
  }
@@ -5747,19 +5755,19 @@ function Ei() {
5747
5755
  async function ee() {
5748
5756
  m(""), T(!0);
5749
5757
  try {
5750
- let { setupToken: t, options: r } = await si(n), i = {
5751
- challenge: wi(r.challenge),
5758
+ let { setupToken: t, options: r } = await ci(n), i = {
5759
+ challenge: Ti(r.challenge),
5752
5760
  rp: r.rp,
5753
5761
  user: {
5754
5762
  ...r.user,
5755
- id: wi(r.user.id)
5763
+ id: Ti(r.user.id)
5756
5764
  },
5757
5765
  pubKeyCredParams: r.pubKeyCredParams,
5758
5766
  timeout: r.timeout || 6e4,
5759
5767
  attestation: r.attestation || "none",
5760
5768
  authenticatorSelection: r.authenticatorSelection,
5761
5769
  excludeCredentials: (r.excludeCredentials || []).map((e) => ({
5762
- id: wi(e.id),
5770
+ id: Ti(e.id),
5763
5771
  type: e.type,
5764
5772
  transports: e.transports
5765
5773
  }))
@@ -5769,17 +5777,17 @@ function Ei() {
5769
5777
  return;
5770
5778
  }
5771
5779
  let o = a.response;
5772
- await ci(t, JSON.stringify({
5780
+ await li(t, JSON.stringify({
5773
5781
  id: a.id,
5774
- rawId: Ti(a.rawId),
5782
+ rawId: Ei(a.rawId),
5775
5783
  type: a.type,
5776
5784
  response: {
5777
- attestationObject: Ti(o.attestationObject),
5778
- clientDataJSON: Ti(o.clientDataJSON)
5785
+ attestationObject: Ei(o.attestationObject),
5786
+ clientDataJSON: Ei(o.clientDataJSON)
5779
5787
  }
5780
5788
  }), n), j(), await A();
5781
5789
  } catch (t) {
5782
- t instanceof DOMException && t.name === "NotAllowedError" ? m(e("mfaWebAuthnCancelled")) : t instanceof Gr ? m(t.message || e("errorUnexpected")) : m(e("errorUnexpected"));
5790
+ t instanceof DOMException && t.name === "NotAllowedError" ? m(e("mfaWebAuthnCancelled")) : t instanceof Kr ? m(t.message || e("errorUnexpected")) : m(e("errorUnexpected"));
5783
5791
  } finally {
5784
5792
  T(!1);
5785
5793
  }
@@ -5787,9 +5795,9 @@ function Ei() {
5787
5795
  async function te() {
5788
5796
  m(""), k(!0);
5789
5797
  try {
5790
- D((await oi(n)).codes), await A();
5798
+ D((await si(n)).codes), await A();
5791
5799
  } catch (t) {
5792
- t instanceof Gr && t.error === "primary_method_required" ? m(e("mfaRecoveryRequiresPrimary")) : m(e("errorUnexpected"));
5800
+ t instanceof Kr && t.error === "primary_method_required" ? m(e("mfaRecoveryRequiresPrimary")) : m(e("errorUnexpected"));
5793
5801
  } finally {
5794
5802
  k(!1);
5795
5803
  }
@@ -5797,7 +5805,7 @@ function Ei() {
5797
5805
  async function P(t) {
5798
5806
  m("");
5799
5807
  try {
5800
- await li(t, n), await A();
5808
+ await ui(t, n), await A();
5801
5809
  } catch {
5802
5810
  m(e("errorUnexpected"));
5803
5811
  }
@@ -5954,13 +5962,13 @@ function Ei() {
5954
5962
  type: "button",
5955
5963
  className: "bg-transparent border-none cursor-pointer text-[13px] text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200",
5956
5964
  onClick: () => {
5957
- let e = r && Ci(r) ? r : "/";
5965
+ let e = r && wi(r) ? r : "/";
5958
5966
  window.location.href = e;
5959
5967
  },
5960
5968
  children: e("mfaSkipSetup")
5961
5969
  })
5962
5970
  }),
5963
- i && /* @__PURE__ */ l("div", {
5971
+ i && wi(i) && /* @__PURE__ */ l("div", {
5964
5972
  className: "mt-6 text-center pt-4 border-t border-gray-200 dark:border-gray-800",
5965
5973
  children: /* @__PURE__ */ u("a", {
5966
5974
  href: i,
@@ -5972,11 +5980,11 @@ function Ei() {
5972
5980
  }
5973
5981
  //#endregion
5974
5982
  //#region src/pages/DevicePage.tsx
5975
- var Di = "";
5976
- function Oi() {
5983
+ var Oi = "";
5984
+ function ki() {
5977
5985
  let e = g(), [t] = _(), [n, r] = s(t.get("user_code") || ""), [i, o] = s(!1), [c, d] = s(!0), [f, p] = s(!1), [m, h] = s(!1), [v, y] = s("");
5978
5986
  a(() => {
5979
- Qr().then((e) => {
5987
+ $r().then((e) => {
5980
5988
  p(!!e?.userId);
5981
5989
  }).catch(() => p(!1)).finally(() => d(!1));
5982
5990
  }, []);
@@ -5988,7 +5996,7 @@ function Oi() {
5988
5996
  return;
5989
5997
  }
5990
5998
  try {
5991
- let e = await fetch(`${Di}/api/auth/device/approve`, {
5999
+ let e = await fetch(`${Oi}/api/auth/device/approve`, {
5992
6000
  method: "POST",
5993
6001
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
5994
6002
  credentials: "include",
@@ -6103,7 +6111,7 @@ function Oi() {
6103
6111
  }
6104
6112
  //#endregion
6105
6113
  //#region src/pages/ConsentPage.tsx
6106
- var ki = {
6114
+ var Ai = {
6107
6115
  openid: "consent.scopeOpenid",
6108
6116
  profile: "consent.scopeProfile",
6109
6117
  email: "consent.scopeEmail",
@@ -6111,7 +6119,7 @@ var ki = {
6111
6119
  address: "consent.scopeAddress",
6112
6120
  phone: "consent.scopePhone"
6113
6121
  };
6114
- function Ai() {
6122
+ function ji() {
6115
6123
  let { t: e } = L(), [t] = _(), n = t.get("client_id") ?? "", r = t.get("scope") ?? "openid", i = t.get("returnUrl") ?? "/", [o, c] = s(null), [d, f] = s(!0), [p, m] = s(!1), [h, g] = s("");
6116
6124
  a(() => {
6117
6125
  fetch(`/consent/info?client_id=${encodeURIComponent(n)}&scope=${encodeURIComponent(r)}`).then(async (e) => {
@@ -6141,10 +6149,10 @@ function Ai() {
6141
6149
  g(e("consent.submitError")), m(!1);
6142
6150
  }
6143
6151
  }
6144
- return d ? /* @__PURE__ */ l(Lr, { children: /* @__PURE__ */ l("p", {
6152
+ return d ? /* @__PURE__ */ l(Rr, { children: /* @__PURE__ */ l("p", {
6145
6153
  className: "text-sm text-gray-500 dark:text-gray-400 text-center",
6146
6154
  children: e("consent.loading")
6147
- }) }) : /* @__PURE__ */ u(Lr, { children: [
6155
+ }) }) : /* @__PURE__ */ u(Rr, { children: [
6148
6156
  o?.logoUri && /* @__PURE__ */ l("div", {
6149
6157
  className: "flex justify-center mb-4",
6150
6158
  children: /* @__PURE__ */ l("img", {
@@ -6182,7 +6190,7 @@ function Ai() {
6182
6190
  /* @__PURE__ */ l("div", {
6183
6191
  className: "space-y-2 mb-6",
6184
6192
  children: (o?.scopes ?? r.split(" ")).map((t) => {
6185
- let n = ki[t];
6193
+ let n = Ai[t];
6186
6194
  return /* @__PURE__ */ u("div", {
6187
6195
  className: "flex items-center gap-3 p-3 bg-gray-50 dark:bg-gray-800/60 rounded-lg",
6188
6196
  children: [/* @__PURE__ */ l("div", { className: "w-2 h-2 bg-primary rounded-full shrink-0" }), /* @__PURE__ */ l("span", {
@@ -6215,7 +6223,7 @@ function Ai() {
6215
6223
  }
6216
6224
  //#endregion
6217
6225
  //#region src/pages/GrantsPage.tsx
6218
- function ji() {
6226
+ function Mi() {
6219
6227
  let { t: e } = L(), [t, n] = s([]), [r, i] = s(!0), [o, c] = s(""), [d, f] = s("");
6220
6228
  a(() => {
6221
6229
  fetch("/consent/grants").then(async (e) => {
@@ -6235,7 +6243,7 @@ function ji() {
6235
6243
  }
6236
6244
  }
6237
6245
  }
6238
- return /* @__PURE__ */ u(Lr, { children: [
6246
+ return /* @__PURE__ */ u(Rr, { children: [
6239
6247
  /* @__PURE__ */ l(W, { children: e("grants.title") }),
6240
6248
  /* @__PURE__ */ l("p", {
6241
6249
  className: "text-sm text-gray-500 dark:text-gray-400 mb-4",
@@ -6281,43 +6289,43 @@ function ji() {
6281
6289
  }
6282
6290
  //#endregion
6283
6291
  //#region src/App.tsx
6284
- function Mi() {
6285
- return /* @__PURE__ */ l(d, { children: /* @__PURE__ */ l(Lr, { children: /* @__PURE__ */ u(h, { children: [
6292
+ function Ni() {
6293
+ return /* @__PURE__ */ l(d, { children: /* @__PURE__ */ l(Rr, { children: /* @__PURE__ */ u(h, { children: [
6286
6294
  /* @__PURE__ */ l(m, {
6287
6295
  path: "/login",
6288
- element: /* @__PURE__ */ l(fi, {})
6296
+ element: /* @__PURE__ */ l(pi, {})
6289
6297
  }),
6290
6298
  /* @__PURE__ */ l(m, {
6291
6299
  path: "/register",
6292
- element: /* @__PURE__ */ l(pi, {})
6300
+ element: /* @__PURE__ */ l(mi, {})
6293
6301
  }),
6294
6302
  /* @__PURE__ */ l(m, {
6295
6303
  path: "/forgot-password",
6296
- element: /* @__PURE__ */ l(mi, {})
6304
+ element: /* @__PURE__ */ l(hi, {})
6297
6305
  }),
6298
6306
  /* @__PURE__ */ l(m, {
6299
6307
  path: "/reset-password",
6300
- element: /* @__PURE__ */ l(vi, {})
6308
+ element: /* @__PURE__ */ l(yi, {})
6301
6309
  }),
6302
6310
  /* @__PURE__ */ l(m, {
6303
6311
  path: "/mfa-challenge",
6304
- element: /* @__PURE__ */ l(Si, {})
6312
+ element: /* @__PURE__ */ l(Ci, {})
6305
6313
  }),
6306
6314
  /* @__PURE__ */ l(m, {
6307
6315
  path: "/mfa-setup",
6308
- element: /* @__PURE__ */ l(Ei, {})
6316
+ element: /* @__PURE__ */ l(Di, {})
6309
6317
  }),
6310
6318
  /* @__PURE__ */ l(m, {
6311
6319
  path: "/device",
6312
- element: /* @__PURE__ */ l(Oi, {})
6320
+ element: /* @__PURE__ */ l(ki, {})
6313
6321
  }),
6314
6322
  /* @__PURE__ */ l(m, {
6315
6323
  path: "/consent",
6316
- element: /* @__PURE__ */ l(Ai, {})
6324
+ element: /* @__PURE__ */ l(ji, {})
6317
6325
  }),
6318
6326
  /* @__PURE__ */ l(m, {
6319
6327
  path: "/grants",
6320
- element: /* @__PURE__ */ l(ji, {})
6328
+ element: /* @__PURE__ */ l(Mi, {})
6321
6329
  }),
6322
6330
  /* @__PURE__ */ l(m, {
6323
6331
  path: "*",
@@ -6329,4 +6337,4 @@ function Mi() {
6329
6337
  ] }) }) });
6330
6338
  }
6331
6339
  //#endregion
6332
- export { Q as Alert, Gr as ApiRequestError, Mi as App, Lr as AuthLayout, R as BrandingContext, Y as Button, Lt as Card, Bt as CardContent, zt as CardDescription, G as CardFooter, Rt as CardHeader, W as CardTitle, mi as ForgotPasswordPage, X as Input, Z as Label, fi as LoginPage, Si as MfaChallengePage, Ei as MfaSetupPage, pi as RegisterPage, vi as ResetPasswordPage, Ur as Separator, U as cn, Xr as forgotPassword, ti as getPasswordPolicy, ei as getProviders, Qr as getSession, Pr as i18n, oe as loadBranding, qr as login, Yr as logout, li as mfaDeleteCredential, oi as mfaRecoveryGenerate, ri as mfaStatus, ai as mfaTotpConfirm, ii as mfaTotpSetup, ni as mfaVerify, ci as mfaWebAuthnConfirm, si as mfaWebAuthnSetup, Zr as resetPassword, ce as resolveLocalized, $r as ssoCheck, se as useBranding, L as useTranslation };
6340
+ export { Q as Alert, Kr as ApiRequestError, Ni as App, Rr as AuthLayout, R as BrandingContext, Y as Button, Lt as Card, Bt as CardContent, zt as CardDescription, G as CardFooter, Rt as CardHeader, W as CardTitle, hi as ForgotPasswordPage, X as Input, Z as Label, pi as LoginPage, Ci as MfaChallengePage, Di as MfaSetupPage, mi as RegisterPage, yi as ResetPasswordPage, Wr as Separator, U as cn, Zr as forgotPassword, ni as getPasswordPolicy, ti as getProviders, $r as getSession, Pr as i18n, oe as loadBranding, Jr as login, Xr as logout, ui as mfaDeleteCredential, si as mfaRecoveryGenerate, ii as mfaStatus, oi as mfaTotpConfirm, ai as mfaTotpSetup, ri as mfaVerify, li as mfaWebAuthnConfirm, ci as mfaWebAuthnSetup, Qr as resetPassword, ce as resolveLocalized, ei as ssoCheck, se as useBranding, L as useTranslation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authagonal/login",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Default login UI for Authagonal — runtime-configurable via branding.json",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -13,6 +13,12 @@ interface AuthLayoutProps {
13
13
  children: ReactNode;
14
14
  }
15
15
 
16
+ // Accept only hex (#rgb/#rrggbb/#rrggbbaa) or rgb()/rgba()/hsl()/hsla() forms.
17
+ function isSafeCssColor(color: string): boolean {
18
+ return /^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color)
19
+ || /^(?:rgb|rgba|hsl|hsla)\([0-9.,%\s/]+\)$/i.test(color);
20
+ }
21
+
16
22
  const ALL_LANGUAGES: { code: string; label: string }[] = [
17
23
  { code: 'en', label: 'English' },
18
24
  { code: 'zh-Hans', label: '中文' },
@@ -60,15 +66,24 @@ export default function AuthLayout({ children }: AuthLayoutProps) {
60
66
  useDarkMode();
61
67
 
62
68
  useEffect(() => {
63
- document.documentElement.style.setProperty('--brand-primary', branding.primaryColor);
69
+ if (branding.primaryColor && isSafeCssColor(branding.primaryColor)) {
70
+ document.documentElement.style.setProperty('--brand-primary', branding.primaryColor);
71
+ }
64
72
 
65
73
  if (branding.customCssUrl) {
66
- const link = document.createElement('link');
67
- link.rel = 'stylesheet';
68
- link.href = branding.customCssUrl;
69
- link.id = 'branding-css';
70
- document.head.appendChild(link);
71
- return () => { link.remove(); };
74
+ try {
75
+ const parsed = new URL(branding.customCssUrl, window.location.origin);
76
+ if (parsed.origin === window.location.origin) {
77
+ const link = document.createElement('link');
78
+ link.rel = 'stylesheet';
79
+ link.href = branding.customCssUrl;
80
+ link.id = 'branding-css';
81
+ document.head.appendChild(link);
82
+ return () => { link.remove(); };
83
+ }
84
+ } catch {
85
+ // Invalid URL — skip injecting custom CSS.
86
+ }
72
87
  }
73
88
  }, [branding]);
74
89
 
@@ -354,7 +354,7 @@ export default function MfaSetupPage() {
354
354
  )}
355
355
 
356
356
  {/* Back to app link — shown when navigating from an external app */}
357
- {backUrl && (
357
+ {backUrl && isSafeReturnUrl(backUrl) && (
358
358
  <div className="mt-6 text-center pt-4 border-t border-gray-200 dark:border-gray-800">
359
359
  <a href={backUrl} className="text-sm text-primary no-underline hover:underline">
360
360
  &larr; {t('mfaBackToApp')}