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.js CHANGED
@@ -105,10 +105,29 @@ async function unseal(sealed, key) {
105
105
  // src/system.ts
106
106
  var import_jose2 = require("jose");
107
107
 
108
+ // src/url.ts
109
+ function withoutTrailingSlashes(s) {
110
+ let end = s.length;
111
+ while (end > 0 && s.charCodeAt(end - 1) === 47) end--;
112
+ return s.slice(0, end);
113
+ }
114
+
108
115
  // src/theme.ts
109
116
  var MAX_RADIUS = 40;
117
+ function withoutComments(css) {
118
+ let out2 = "";
119
+ let i = 0;
120
+ for (; ; ) {
121
+ const open = css.indexOf("/*", i);
122
+ if (open < 0) return out2 + css.slice(i);
123
+ out2 += css.slice(i, open);
124
+ const close = css.indexOf("*/", open + 2);
125
+ if (close < 0) return out2;
126
+ i = close + 2;
127
+ }
128
+ }
110
129
  function declarations(css) {
111
- const text = css.replace(/\/\*[\s\S]*?\*\//g, "");
130
+ const text = withoutComments(css);
112
131
  const out2 = [];
113
132
  const within = [];
114
133
  let chunk = "";
@@ -203,7 +222,11 @@ function tokenValue(value) {
203
222
  if (/^\(|[ ,(]\(/.test(v)) return null;
204
223
  return v;
205
224
  }
206
- var THEME_SCOPE = /^(?:\s*(?::root|html|body|\[data-(?:theme|mode|color-scheme)(?:=["']?[\w-]+["']?)?\])\s*,?)+$/i;
225
+ var THEME_SELECTOR = /^(?::root|html|body|\[data-(?:theme|mode|color-scheme)(?:=["']?[\w-]+["']?)?\])$/i;
226
+ var isThemeScope = (selectors) => {
227
+ const parts = selectors.split(/[\s,]+/).filter(Boolean);
228
+ return parts.length > 0 && parts.every((one) => THEME_SELECTOR.test(one));
229
+ };
207
230
  function tokensFromStackmyth(css, options = {}) {
208
231
  const mode = options.mode ?? "light";
209
232
  const all = (Array.isArray(css) ? css : [css]).flatMap(declarations);
@@ -211,7 +234,7 @@ function tokensFromStackmyth(css, options = {}) {
211
234
  const vars = /* @__PURE__ */ new Map();
212
235
  for (const d of all) {
213
236
  if (!applies(d, { mode, theme: named })) continue;
214
- if (!d.within.every((w) => w.startsWith("@") || THEME_SCOPE.test(w))) continue;
237
+ if (!d.within.every((w) => w.startsWith("@") || isThemeScope(w))) continue;
215
238
  vars.set(d.name, d.value);
216
239
  }
217
240
  const inline = (value, depth = 0) => {
@@ -433,7 +456,7 @@ function fromWire(wire) {
433
456
  }
434
457
  async function pushTheme(o) {
435
458
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
436
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
459
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
437
460
  const clientId = o.clientId ?? env4("CAUTHY_CLIENT_ID") ?? "";
438
461
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
439
462
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
@@ -501,7 +524,7 @@ async function loadKey(k) {
501
524
  return jwk ? (0, import_jose2.importJWK)(jwk, "RS256") : (0, import_jose2.importPKCS8)(k.privateKey, "RS256", { extractable: true });
502
525
  }
503
526
  function createSystem(given = {}) {
504
- const issuer = (given.issuer ?? env("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
527
+ const issuer = withoutTrailingSlashes(given.issuer ?? env("CAUTHY_ISSUER") ?? "");
505
528
  const clientId = given.clientId ?? env("CAUTHY_CLIENT_ID") ?? "";
506
529
  const clientSecret = given.clientSecret ?? env("CAUTHY_CLIENT_SECRET") ?? "";
507
530
  const envKey = env("CAUTHY_SYSTEM_KEY");
@@ -690,7 +713,7 @@ function keysOf(issuer) {
690
713
  var hex = (s) => typeof s === "string" && s !== "" ? s : void 0;
691
714
  async function verifyWebhook(request, options = {}) {
692
715
  const env4 = typeof process !== "undefined" ? process.env?.CAUTHY_ISSUER : void 0;
693
- const issuer = (options.issuer ?? env4 ?? "").replace(/\/+$/, "");
716
+ const issuer = withoutTrailingSlashes(options.issuer ?? env4 ?? "");
694
717
  if (issuer === "") throw new CauthyWebhookError("issuer (CAUTHY_ISSUER) is not set");
695
718
  const signature = request.headers.get("x-cauthy-signature-jwt");
696
719
  if (!signature) throw new CauthyWebhookError("no signature");
@@ -700,7 +723,6 @@ async function verifyWebhook(request, options = {}) {
700
723
  try {
701
724
  const verified = await (0, import_jose3.jwtVerify)(signature, options.jwks ?? keysOf(issuer), {
702
725
  algorithms: ["RS256"],
703
- issuer,
704
726
  audience,
705
727
  typ: "cauthy-webhook+jwt",
706
728
  requiredClaims: ["exp", "iat", "jti", "body_sha256"],
@@ -711,6 +733,9 @@ async function verifyWebhook(request, options = {}) {
711
733
  } catch (err) {
712
734
  throw new CauthyWebhookError(err instanceof Error ? err.message : "bad signature");
713
735
  }
736
+ if (claims.iss !== issuer && claims.domain_iss !== issuer) {
737
+ throw new CauthyWebhookError('unexpected "iss" claim value');
738
+ }
714
739
  const now = Math.floor((options.now ?? /* @__PURE__ */ new Date()).getTime() / 1e3);
715
740
  if (typeof claims.iat !== "number" || claims.iat > now + 30) throw new CauthyWebhookError("signed in the future");
716
741
  const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", raw));
@@ -781,7 +806,7 @@ function redirect(location, cookies = []) {
781
806
  return new Response(null, { status: 302, headers: h });
782
807
  }
783
808
  function createCauthy(given = {}) {
784
- const issuer = (given.issuer ?? env2("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
809
+ const issuer = withoutTrailingSlashes(given.issuer ?? env2("CAUTHY_ISSUER") ?? "");
785
810
  const clientId = given.clientId ?? env2("CAUTHY_CLIENT_ID") ?? "";
786
811
  const clientSecret = given.clientSecret ?? env2("CAUTHY_CLIENT_SECRET");
787
812
  const secret = given.secret ?? env2("CAUTHY_SECRET") ?? "";
@@ -805,7 +830,7 @@ function createCauthy(given = {}) {
805
830
  verifyEmail: given.pages?.verifyEmail ? localPath(given.pages.verifyEmail, "/") : void 0
806
831
  };
807
832
  const ownSystem = createSystem({ issuer, clientId, clientSecret, key: given.systemKey, fetch: given.fetch });
808
- const originOf = (request) => (given.baseURL ?? new URL(request.url).origin).replace(/\/+$/, "");
833
+ const originOf = (request) => withoutTrailingSlashes(given.baseURL ?? new URL(request.url).origin);
809
834
  const attrs = (request, maxAge) => ({ secure: originOf(request).startsWith("https://"), maxAge });
810
835
  async function token(form) {
811
836
  const body2 = new URLSearchParams({ client_id: clientId, ...form });
@@ -1804,7 +1829,7 @@ function createCauthy(given = {}) {
1804
1829
  async function handler(request) {
1805
1830
  const url = new URL(request.url);
1806
1831
  if (url.pathname !== basePath && !url.pathname.startsWith(`${basePath}/`)) return new Response("Not found", { status: 404 });
1807
- const route = url.pathname.slice(basePath.length).replace(/\/+$/, "") || "/";
1832
+ const route = withoutTrailingSlashes(url.pathname.slice(basePath.length)) || "/";
1808
1833
  const get = request.method === "GET" || request.method === "HEAD";
1809
1834
  const mine = await ownRoute(request, url, route);
1810
1835
  if (mine !== null) return mine;
@@ -1951,7 +1976,7 @@ export type Permission = PermissionOf<typeof policy>
1951
1976
  }
1952
1977
  async function pullPolicy(o = {}) {
1953
1978
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
1954
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
1979
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
1955
1980
  const system = o.system ?? env4("CAUTHY_SYSTEM") ?? "";
1956
1981
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
1957
1982
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
@@ -1967,7 +1992,7 @@ async function pullPolicy(o = {}) {
1967
1992
  }
1968
1993
  async function pushPolicy(o) {
1969
1994
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
1970
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
1995
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
1971
1996
  const system = o.system ?? env4("CAUTHY_SYSTEM") ?? "";
1972
1997
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
1973
1998
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
@@ -1994,7 +2019,7 @@ function sessionSecret() {
1994
2019
  }
1995
2020
  async function connectSystem(o) {
1996
2021
  const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
1997
- const issuer = (o.issuer ?? env4("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
2022
+ const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
1998
2023
  const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
1999
2024
  const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
2000
2025
  for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {
@@ -2057,7 +2082,7 @@ function bearer(from) {
2057
2082
  return /^Bearer\s+/i.test(header) ? header.replace(/^Bearer\s+/i, "").trim() : "";
2058
2083
  }
2059
2084
  async function verifyToken(from, options = {}) {
2060
- const issuer = (options.issuer ?? env3("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
2085
+ const issuer = withoutTrailingSlashes(options.issuer ?? env3("CAUTHY_ISSUER") ?? "");
2061
2086
  if (issuer === "") throw new CauthyTokenError("issuer (CAUTHY_ISSUER) is not set");
2062
2087
  const token = bearer(from);
2063
2088
  if (token === "") throw new CauthyTokenError("no token");