cauthy-auth 0.23.0 → 0.24.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.mjs CHANGED
@@ -57,10 +57,29 @@ async function unseal(sealed, key) {
57
57
  // src/system.ts
58
58
  import { exportJWK, importJWK, importPKCS8, SignJWT } from "jose";
59
59
 
60
+ // src/url.ts
61
+ function withoutTrailingSlashes(s) {
62
+ let end = s.length;
63
+ while (end > 0 && s.charCodeAt(end - 1) === 47) end--;
64
+ return s.slice(0, end);
65
+ }
66
+
60
67
  // src/theme.ts
61
68
  var MAX_RADIUS = 40;
69
+ function withoutComments(css) {
70
+ let out2 = "";
71
+ let i = 0;
72
+ for (; ; ) {
73
+ const open = css.indexOf("/*", i);
74
+ if (open < 0) return out2 + css.slice(i);
75
+ out2 += css.slice(i, open);
76
+ const close = css.indexOf("*/", open + 2);
77
+ if (close < 0) return out2;
78
+ i = close + 2;
79
+ }
80
+ }
62
81
  function declarations(css) {
63
- const text = css.replace(/\/\*[\s\S]*?\*\//g, "");
82
+ const text = withoutComments(css);
64
83
  const out2 = [];
65
84
  const within = [];
66
85
  let chunk = "";
@@ -155,7 +174,11 @@ function tokenValue(value) {
155
174
  if (/^\(|[ ,(]\(/.test(v)) return null;
156
175
  return v;
157
176
  }
158
- var THEME_SCOPE = /^(?:\s*(?::root|html|body|\[data-(?:theme|mode|color-scheme)(?:=["']?[\w-]+["']?)?\])\s*,?)+$/i;
177
+ var THEME_SELECTOR = /^(?::root|html|body|\[data-(?:theme|mode|color-scheme)(?:=["']?[\w-]+["']?)?\])$/i;
178
+ var isThemeScope = (selectors) => {
179
+ const parts = selectors.split(/[\s,]+/).filter(Boolean);
180
+ return parts.length > 0 && parts.every((one) => THEME_SELECTOR.test(one));
181
+ };
159
182
  function tokensFromStackmyth(css, options = {}) {
160
183
  const mode = options.mode ?? "light";
161
184
  const all = (Array.isArray(css) ? css : [css]).flatMap(declarations);
@@ -163,7 +186,7 @@ function tokensFromStackmyth(css, options = {}) {
163
186
  const vars = /* @__PURE__ */ new Map();
164
187
  for (const d of all) {
165
188
  if (!applies(d, { mode, theme: named })) continue;
166
- if (!d.within.every((w) => w.startsWith("@") || THEME_SCOPE.test(w))) continue;
189
+ if (!d.within.every((w) => w.startsWith("@") || isThemeScope(w))) continue;
167
190
  vars.set(d.name, d.value);
168
191
  }
169
192
  const inline = (value, depth = 0) => {
@@ -385,7 +408,7 @@ function fromWire(wire) {
385
408
  }
386
409
  async function pushTheme(o) {
387
410
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
388
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
411
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
389
412
  const clientId = o.clientId ?? env4("CAUTHY_CLIENT_ID") ?? "";
390
413
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
391
414
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
@@ -453,7 +476,7 @@ async function loadKey(k) {
453
476
  return jwk ? importJWK(jwk, "RS256") : importPKCS8(k.privateKey, "RS256", { extractable: true });
454
477
  }
455
478
  function createSystem(given = {}) {
456
- const issuer = (given.issuer ?? env("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
479
+ const issuer = withoutTrailingSlashes(given.issuer ?? env("CAUTHY_ISSUER") ?? "");
457
480
  const clientId = given.clientId ?? env("CAUTHY_CLIENT_ID") ?? "";
458
481
  const clientSecret = given.clientSecret ?? env("CAUTHY_CLIENT_SECRET") ?? "";
459
482
  const envKey = env("CAUTHY_SYSTEM_KEY");
@@ -642,7 +665,7 @@ function keysOf(issuer) {
642
665
  var hex = (s) => typeof s === "string" && s !== "" ? s : void 0;
643
666
  async function verifyWebhook(request, options = {}) {
644
667
  const env4 = typeof process !== "undefined" ? process.env?.CAUTHY_ISSUER : void 0;
645
- const issuer = (options.issuer ?? env4 ?? "").replace(/\/+$/, "");
668
+ const issuer = withoutTrailingSlashes(options.issuer ?? env4 ?? "");
646
669
  if (issuer === "") throw new CauthyWebhookError("issuer (CAUTHY_ISSUER) is not set");
647
670
  const signature = request.headers.get("x-cauthy-signature-jwt");
648
671
  if (!signature) throw new CauthyWebhookError("no signature");
@@ -652,7 +675,6 @@ async function verifyWebhook(request, options = {}) {
652
675
  try {
653
676
  const verified = await jwtVerify(signature, options.jwks ?? keysOf(issuer), {
654
677
  algorithms: ["RS256"],
655
- issuer,
656
678
  audience,
657
679
  typ: "cauthy-webhook+jwt",
658
680
  requiredClaims: ["exp", "iat", "jti", "body_sha256"],
@@ -663,6 +685,9 @@ async function verifyWebhook(request, options = {}) {
663
685
  } catch (err) {
664
686
  throw new CauthyWebhookError(err instanceof Error ? err.message : "bad signature");
665
687
  }
688
+ if (claims.iss !== issuer && claims.domain_iss !== issuer) {
689
+ throw new CauthyWebhookError('unexpected "iss" claim value');
690
+ }
666
691
  const now = Math.floor((options.now ?? /* @__PURE__ */ new Date()).getTime() / 1e3);
667
692
  if (typeof claims.iat !== "number" || claims.iat > now + 30) throw new CauthyWebhookError("signed in the future");
668
693
  const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", raw));
@@ -733,7 +758,7 @@ function redirect(location, cookies = []) {
733
758
  return new Response(null, { status: 302, headers: h });
734
759
  }
735
760
  function createCauthy(given = {}) {
736
- const issuer = (given.issuer ?? env2("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
761
+ const issuer = withoutTrailingSlashes(given.issuer ?? env2("CAUTHY_ISSUER") ?? "");
737
762
  const clientId = given.clientId ?? env2("CAUTHY_CLIENT_ID") ?? "";
738
763
  const clientSecret = given.clientSecret ?? env2("CAUTHY_CLIENT_SECRET");
739
764
  const secret = given.secret ?? env2("CAUTHY_SECRET") ?? "";
@@ -757,7 +782,7 @@ function createCauthy(given = {}) {
757
782
  verifyEmail: given.pages?.verifyEmail ? localPath(given.pages.verifyEmail, "/") : void 0
758
783
  };
759
784
  const ownSystem = createSystem({ issuer, clientId, clientSecret, key: given.systemKey, fetch: given.fetch });
760
- const originOf = (request) => (given.baseURL ?? new URL(request.url).origin).replace(/\/+$/, "");
785
+ const originOf = (request) => withoutTrailingSlashes(given.baseURL ?? new URL(request.url).origin);
761
786
  const attrs = (request, maxAge) => ({ secure: originOf(request).startsWith("https://"), maxAge });
762
787
  async function token(form) {
763
788
  const body2 = new URLSearchParams({ client_id: clientId, ...form });
@@ -1756,7 +1781,7 @@ function createCauthy(given = {}) {
1756
1781
  async function handler(request) {
1757
1782
  const url = new URL(request.url);
1758
1783
  if (url.pathname !== basePath && !url.pathname.startsWith(`${basePath}/`)) return new Response("Not found", { status: 404 });
1759
- const route = url.pathname.slice(basePath.length).replace(/\/+$/, "") || "/";
1784
+ const route = withoutTrailingSlashes(url.pathname.slice(basePath.length)) || "/";
1760
1785
  const get = request.method === "GET" || request.method === "HEAD";
1761
1786
  const mine = await ownRoute(request, url, route);
1762
1787
  if (mine !== null) return mine;
@@ -1903,7 +1928,7 @@ export type Permission = PermissionOf<typeof policy>
1903
1928
  }
1904
1929
  async function pullPolicy(o = {}) {
1905
1930
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
1906
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
1931
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
1907
1932
  const system = o.system ?? env4("CAUTHY_SYSTEM") ?? "";
1908
1933
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
1909
1934
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
@@ -1919,7 +1944,7 @@ async function pullPolicy(o = {}) {
1919
1944
  }
1920
1945
  async function pushPolicy(o) {
1921
1946
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
1922
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
1947
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
1923
1948
  const system = o.system ?? env4("CAUTHY_SYSTEM") ?? "";
1924
1949
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
1925
1950
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
@@ -1946,7 +1971,7 @@ function sessionSecret() {
1946
1971
  }
1947
1972
  async function connectSystem(o) {
1948
1973
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
1949
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
1974
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
1950
1975
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
1951
1976
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
1952
1977
  for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {
@@ -2009,7 +2034,7 @@ function bearer(from) {
2009
2034
  return /^Bearer\s+/i.test(header) ? header.replace(/^Bearer\s+/i, "").trim() : "";
2010
2035
  }
2011
2036
  async function verifyToken(from, options = {}) {
2012
- const issuer = (options.issuer ?? env3("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
2037
+ const issuer = withoutTrailingSlashes(options.issuer ?? env3("CAUTHY_ISSUER") ?? "");
2013
2038
  if (issuer === "") throw new CauthyTokenError("issuer (CAUTHY_ISSUER) is not set");
2014
2039
  const token = bearer(from);
2015
2040
  if (token === "") throw new CauthyTokenError("no token");