@mastra/auth-studio 1.3.2 → 1.3.3-alpha.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.js CHANGED
@@ -1,3 +1,7 @@
1
+ import { createHash } from 'crypto';
2
+
3
+ // src/index.ts
4
+
1
5
  // ../../packages/_internals/auth/dist/chunk-LZCWL5CT.js
2
6
  var RESOURCE_EXPANSIONS = {
3
7
  stored: [
@@ -264,6 +268,8 @@ function getRequestHeader2(request, name) {
264
268
  return request.raw?.headers.get(name) ?? request.headers?.get(name) ?? request.header(name) ?? null;
265
269
  }
266
270
  var COOKIE_NAME = "wos-session";
271
+ var VERIFY_FETCH_TIMEOUT_MS = 15e3;
272
+ var VERIFY_CACHE_TTL_MS = 3e4;
267
273
  var MastraAuthStudio = class extends MastraAuthProvider {
268
274
  isMastraCloudAuth = true;
269
275
  sharedApiUrl;
@@ -279,6 +285,15 @@ var MastraAuthStudio = class extends MastraAuthProvider {
279
285
  */
280
286
  userSessionCookies = /* @__PURE__ */ new Map();
281
287
  maxCachedSessions = 1e3;
288
+ /**
289
+ * Short-TTL cache of SUCCESSFUL credential verifications, keyed by a
290
+ * sha256 of the credential (never the raw cookie/token). Every protected
291
+ * request re-verifies against the shared API otherwise — one network
292
+ * round trip per request. Failures are never cached, so a rejected
293
+ * credential is always re-checked. Bounded + insert-order evicted.
294
+ */
295
+ verifiedCredentials = /* @__PURE__ */ new Map();
296
+ maxCachedVerifications = 1e3;
282
297
  /**
283
298
  * In-flight `ensureOrganization` promises keyed by userId. Concurrent calls
284
299
  * for the same brand-new user (multiple tabs, parallel requests) would
@@ -633,6 +648,27 @@ var MastraAuthStudio = class extends MastraAuthProvider {
633
648
  if (oldest !== void 0) this.userSessionCookies.delete(oldest);
634
649
  }
635
650
  }
651
+ /** Cache key for a verified credential — hash, never the raw secret. */
652
+ verificationKey(kind, credential) {
653
+ return createHash("sha256").update(`${kind}:${credential}`).digest("hex");
654
+ }
655
+ getCachedVerification(key) {
656
+ const entry = this.verifiedCredentials.get(key);
657
+ if (!entry) return null;
658
+ if (entry.expiresAt <= Date.now()) {
659
+ this.verifiedCredentials.delete(key);
660
+ return null;
661
+ }
662
+ return entry.user;
663
+ }
664
+ cacheVerification(key, user) {
665
+ this.verifiedCredentials.delete(key);
666
+ this.verifiedCredentials.set(key, { user, expiresAt: Date.now() + VERIFY_CACHE_TTL_MS });
667
+ if (this.verifiedCredentials.size > this.maxCachedVerifications) {
668
+ const oldest = this.verifiedCredentials.keys().next().value;
669
+ if (oldest !== void 0) this.verifiedCredentials.delete(oldest);
670
+ }
671
+ }
636
672
  /**
637
673
  * Fetch the shared API's `/auth/me` and return the raw response body, or
638
674
  * `null` on any non-OK / network error. Split out so `ensureOrganization`
@@ -641,7 +677,8 @@ var MastraAuthStudio = class extends MastraAuthProvider {
641
677
  async fetchMe(sessionCookie) {
642
678
  try {
643
679
  const res = await fetch(`${this.sharedApiUrl}/auth/me`, {
644
- headers: { Cookie: `${COOKIE_NAME}=${sessionCookie}` }
680
+ headers: { Cookie: `${COOKIE_NAME}=${sessionCookie}` },
681
+ signal: AbortSignal.timeout(VERIFY_FETCH_TIMEOUT_MS)
645
682
  });
646
683
  if (!res.ok) return null;
647
684
  return await res.json();
@@ -654,11 +691,18 @@ var MastraAuthStudio = class extends MastraAuthProvider {
654
691
  * to validate it and get user info.
655
692
  */
656
693
  async verifySessionCookie(sessionCookie) {
694
+ const cacheKey = this.verificationKey("cookie", sessionCookie);
695
+ const cached = this.getCachedVerification(cacheKey);
696
+ if (cached) {
697
+ this.rememberUserSession(cached.id, sessionCookie);
698
+ return cached;
699
+ }
657
700
  try {
658
701
  const res = await fetch(`${this.sharedApiUrl}/auth/me`, {
659
702
  headers: {
660
703
  Cookie: `${COOKIE_NAME}=${sessionCookie}`
661
- }
704
+ },
705
+ signal: AbortSignal.timeout(VERIFY_FETCH_TIMEOUT_MS)
662
706
  });
663
707
  if (!res.ok) {
664
708
  this.logger.warn("verifySessionCookie: shared API returned non-OK status", {
@@ -670,7 +714,7 @@ var MastraAuthStudio = class extends MastraAuthProvider {
670
714
  }
671
715
  const data = await res.json();
672
716
  this.rememberUserSession(data.user.id, sessionCookie);
673
- return {
717
+ const user = {
674
718
  id: data.user.id,
675
719
  email: data.user.email,
676
720
  name: [data.user.firstName, data.user.lastName].filter(Boolean).join(" ") || void 0,
@@ -680,6 +724,8 @@ var MastraAuthStudio = class extends MastraAuthProvider {
680
724
  permissions: data.permissions,
681
725
  memberOrgIds: data.memberOrgIds
682
726
  };
727
+ if (user.organizationId) this.cacheVerification(cacheKey, user);
728
+ return user;
683
729
  } catch (error) {
684
730
  this.logger.error("verifySessionCookie: fetch to shared API failed", {
685
731
  url: `${this.sharedApiUrl}/auth/me`,
@@ -693,11 +739,15 @@ var MastraAuthStudio = class extends MastraAuthProvider {
693
739
  * to validate it and get user info (used for CLI tokens).
694
740
  */
695
741
  async verifyBearerToken(token) {
742
+ const cacheKey = this.verificationKey("bearer", token);
743
+ const cached = this.getCachedVerification(cacheKey);
744
+ if (cached) return cached;
696
745
  try {
697
746
  const res = await fetch(`${this.sharedApiUrl}/auth/verify`, {
698
747
  headers: {
699
748
  Authorization: `Bearer ${token}`
700
- }
749
+ },
750
+ signal: AbortSignal.timeout(VERIFY_FETCH_TIMEOUT_MS)
701
751
  });
702
752
  if (!res.ok) {
703
753
  this.logger.warn("verifyBearerToken: shared API returned non-OK status", {
@@ -707,7 +757,7 @@ var MastraAuthStudio = class extends MastraAuthProvider {
707
757
  return null;
708
758
  }
709
759
  const data = await res.json();
710
- return {
760
+ const user = {
711
761
  id: data.user.id,
712
762
  email: data.user.email,
713
763
  name: [data.user.firstName, data.user.lastName].filter(Boolean).join(" ") || void 0,
@@ -715,6 +765,8 @@ var MastraAuthStudio = class extends MastraAuthProvider {
715
765
  role: data.role,
716
766
  memberOrgIds: data.memberOrgIds
717
767
  };
768
+ if (user.organizationId) this.cacheVerification(cacheKey, user);
769
+ return user;
718
770
  } catch (error) {
719
771
  this.logger.error("verifyBearerToken: fetch to shared API failed", {
720
772
  url: `${this.sharedApiUrl}/auth/verify`,