@insforge/sdk 1.0.1-refresh.4 → 1.0.1-refresh.6

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.mts CHANGED
@@ -146,8 +146,9 @@ interface SessionStorageStrategy {
146
146
  * Secure Session Storage Strategy
147
147
  *
148
148
  * Stores access token in memory only (cleared on page refresh).
149
- * Refresh token is stored in httpOnly cookie by the backend.
150
- * The `isAuthenticated` cookie is set by the backend to signal that a refresh token exists.
149
+ * Refresh token is stored in httpOnly cookie by the backend (on backend domain).
150
+ * The `isAuthenticated` cookie is set by the SDK on the frontend domain to signal
151
+ * that a secure session exists and token refresh should be attempted on page reload.
151
152
  *
152
153
  * Security benefits:
153
154
  * - Access token not accessible to XSS attacks (in memory only)
@@ -281,12 +282,17 @@ declare class Auth {
281
282
  private database;
282
283
  constructor(http: HttpClient, tokenManager: TokenManager);
283
284
  /**
284
- * Check if the isAuthenticated cookie flag exists
285
+ * Set the isAuthenticated cookie flag on the frontend domain
286
+ * This is managed by SDK, not backend, to work in cross-origin scenarios
285
287
  */
286
- private hasAuthenticatedCookie;
288
+ private setAuthenticatedCookie;
289
+ /**
290
+ * Clear the isAuthenticated cookie flag from the frontend domain
291
+ */
292
+ private clearAuthenticatedCookie;
287
293
  /**
288
294
  * Switch to SecureSessionStorage (cookie-based auth)
289
- * Called when we detect backend supports secure cookie mode
295
+ * Called when backend returns sessionMode: 'secure'
290
296
  * @internal
291
297
  */
292
298
  _switchToSecureStorage(): void;
@@ -297,11 +303,11 @@ declare class Auth {
297
303
  */
298
304
  _switchToLocalStorage(): void;
299
305
  /**
300
- * Detect storage strategy after successful auth
301
- * Checks for isAuthenticated cookie to determine backend mode
306
+ * Detect storage strategy based on backend response
307
+ * @param sessionMode - The sessionMode returned by backend ('secure' or undefined)
302
308
  * @internal
303
309
  */
304
- private _detectStorageAfterAuth;
310
+ private _detectStorageFromResponse;
305
311
  /**
306
312
  * Automatically detect and handle OAuth callback parameters in the URL
307
313
  * This runs on initialization to seamlessly complete the OAuth flow
package/dist/index.d.ts CHANGED
@@ -146,8 +146,9 @@ interface SessionStorageStrategy {
146
146
  * Secure Session Storage Strategy
147
147
  *
148
148
  * Stores access token in memory only (cleared on page refresh).
149
- * Refresh token is stored in httpOnly cookie by the backend.
150
- * The `isAuthenticated` cookie is set by the backend to signal that a refresh token exists.
149
+ * Refresh token is stored in httpOnly cookie by the backend (on backend domain).
150
+ * The `isAuthenticated` cookie is set by the SDK on the frontend domain to signal
151
+ * that a secure session exists and token refresh should be attempted on page reload.
151
152
  *
152
153
  * Security benefits:
153
154
  * - Access token not accessible to XSS attacks (in memory only)
@@ -281,12 +282,17 @@ declare class Auth {
281
282
  private database;
282
283
  constructor(http: HttpClient, tokenManager: TokenManager);
283
284
  /**
284
- * Check if the isAuthenticated cookie flag exists
285
+ * Set the isAuthenticated cookie flag on the frontend domain
286
+ * This is managed by SDK, not backend, to work in cross-origin scenarios
285
287
  */
286
- private hasAuthenticatedCookie;
288
+ private setAuthenticatedCookie;
289
+ /**
290
+ * Clear the isAuthenticated cookie flag from the frontend domain
291
+ */
292
+ private clearAuthenticatedCookie;
287
293
  /**
288
294
  * Switch to SecureSessionStorage (cookie-based auth)
289
- * Called when we detect backend supports secure cookie mode
295
+ * Called when backend returns sessionMode: 'secure'
290
296
  * @internal
291
297
  */
292
298
  _switchToSecureStorage(): void;
@@ -297,11 +303,11 @@ declare class Auth {
297
303
  */
298
304
  _switchToLocalStorage(): void;
299
305
  /**
300
- * Detect storage strategy after successful auth
301
- * Checks for isAuthenticated cookie to determine backend mode
306
+ * Detect storage strategy based on backend response
307
+ * @param sessionMode - The sessionMode returned by backend ('secure' or undefined)
302
308
  * @internal
303
309
  */
304
- private _detectStorageAfterAuth;
310
+ private _detectStorageFromResponse;
305
311
  /**
306
312
  * Automatically detect and handle OAuth callback parameters in the URL
307
313
  * This runs on initialization to seamlessly complete the OAuth flow
package/dist/index.js CHANGED
@@ -267,7 +267,7 @@ var SecureSessionStorage = class {
267
267
  if (this.accessToken) return false;
268
268
  return this.hasAuthFlag();
269
269
  }
270
- // --- Private: Auth Flag Cookie Detection (read-only) ---
270
+ // --- Private: Auth Flag Cookie Detection (SDK-managed on frontend domain) ---
271
271
  hasAuthFlag() {
272
272
  if (typeof document === "undefined") return false;
273
273
  return document.cookie.split(";").some(
@@ -531,27 +531,41 @@ var Auth = class {
531
531
  this.detectAuthCallback();
532
532
  }
533
533
  /**
534
- * Check if the isAuthenticated cookie flag exists
534
+ * Set the isAuthenticated cookie flag on the frontend domain
535
+ * This is managed by SDK, not backend, to work in cross-origin scenarios
535
536
  */
536
- hasAuthenticatedCookie() {
537
- if (typeof document === "undefined") return false;
538
- return document.cookie.split(";").some(
539
- (c) => c.trim().startsWith(`${AUTH_FLAG_COOKIE}=`)
540
- );
537
+ setAuthenticatedCookie() {
538
+ if (typeof document === "undefined") return;
539
+ const maxAge = 7 * 24 * 60 * 60;
540
+ document.cookie = `${AUTH_FLAG_COOKIE}=true; path=/; max-age=${maxAge}; SameSite=Lax`;
541
+ }
542
+ /**
543
+ * Clear the isAuthenticated cookie flag from the frontend domain
544
+ */
545
+ clearAuthenticatedCookie() {
546
+ if (typeof document === "undefined") return;
547
+ document.cookie = `${AUTH_FLAG_COOKIE}=; path=/; max-age=0; SameSite=Lax`;
541
548
  }
542
549
  /**
543
550
  * Switch to SecureSessionStorage (cookie-based auth)
544
- * Called when we detect backend supports secure cookie mode
551
+ * Called when backend returns sessionMode: 'secure'
545
552
  * @internal
546
553
  */
547
554
  _switchToSecureStorage() {
548
- if (this.tokenManager.getStrategyId() === "secure") return;
555
+ console.log("[InsForge:Auth] _switchToSecureStorage() called, current strategy:", this.tokenManager.getStrategyId());
556
+ if (this.tokenManager.getStrategyId() === "secure") {
557
+ console.log("[InsForge:Auth] _switchToSecureStorage() - already in secure mode, skipping");
558
+ return;
559
+ }
549
560
  const currentSession = this.tokenManager.getSession();
550
561
  this.tokenManager.setStrategy(new SecureSessionStorage());
551
562
  if (typeof localStorage !== "undefined") {
563
+ console.log("[InsForge:Auth] _switchToSecureStorage() - clearing localStorage");
552
564
  localStorage.removeItem(TOKEN_KEY);
553
565
  localStorage.removeItem(USER_KEY);
554
566
  }
567
+ console.log("[InsForge:Auth] _switchToSecureStorage() - setting isAuthenticated cookie");
568
+ this.setAuthenticatedCookie();
555
569
  if (currentSession) {
556
570
  this.tokenManager.saveSession(currentSession);
557
571
  }
@@ -565,17 +579,19 @@ var Auth = class {
565
579
  if (this.tokenManager.getStrategyId() === "local") return;
566
580
  const currentSession = this.tokenManager.getSession();
567
581
  this.tokenManager.setStrategy(new LocalSessionStorage());
582
+ this.clearAuthenticatedCookie();
568
583
  if (currentSession) {
569
584
  this.tokenManager.saveSession(currentSession);
570
585
  }
571
586
  }
572
587
  /**
573
- * Detect storage strategy after successful auth
574
- * Checks for isAuthenticated cookie to determine backend mode
588
+ * Detect storage strategy based on backend response
589
+ * @param sessionMode - The sessionMode returned by backend ('secure' or undefined)
575
590
  * @internal
576
591
  */
577
- _detectStorageAfterAuth() {
578
- if (this.hasAuthenticatedCookie()) {
592
+ _detectStorageFromResponse(sessionMode) {
593
+ console.log("[InsForge:Auth] _detectStorageFromResponse() - sessionMode:", sessionMode);
594
+ if (sessionMode === "secure") {
579
595
  this._switchToSecureStorage();
580
596
  }
581
597
  }
@@ -592,8 +608,9 @@ var Auth = class {
592
608
  const userId = params.get("user_id");
593
609
  const email = params.get("email");
594
610
  const name = params.get("name");
611
+ const sessionMode = params.get("session_mode");
595
612
  if (accessToken && userId && email) {
596
- this._detectStorageAfterAuth();
613
+ this._detectStorageFromResponse(sessionMode || void 0);
597
614
  const session = {
598
615
  accessToken,
599
616
  user: {
@@ -614,6 +631,7 @@ var Auth = class {
614
631
  url.searchParams.delete("user_id");
615
632
  url.searchParams.delete("email");
616
633
  url.searchParams.delete("name");
634
+ url.searchParams.delete("session_mode");
617
635
  if (params.has("error")) {
618
636
  url.searchParams.delete("error");
619
637
  }
@@ -629,6 +647,8 @@ var Auth = class {
629
647
  async signUp(request) {
630
648
  try {
631
649
  const response = await this.http.post("/api/auth/users", request);
650
+ const sessionMode = response.sessionMode;
651
+ this._detectStorageFromResponse(sessionMode);
632
652
  if (response.accessToken && response.user) {
633
653
  const session = {
634
654
  accessToken: response.accessToken,
@@ -638,7 +658,6 @@ var Auth = class {
638
658
  this.tokenManager.saveSession(session);
639
659
  }
640
660
  this.http.setAuthToken(response.accessToken);
641
- this._detectStorageAfterAuth();
642
661
  }
643
662
  return {
644
663
  data: response,
@@ -664,6 +683,8 @@ var Auth = class {
664
683
  async signInWithPassword(request) {
665
684
  try {
666
685
  const response = await this.http.post("/api/auth/sessions", request);
686
+ const sessionMode = response.sessionMode;
687
+ this._detectStorageFromResponse(sessionMode);
667
688
  const session = {
668
689
  accessToken: response.accessToken || "",
669
690
  user: response.user || {
@@ -679,7 +700,6 @@ var Auth = class {
679
700
  this.tokenManager.saveSession(session);
680
701
  }
681
702
  this.http.setAuthToken(response.accessToken || "");
682
- this._detectStorageAfterAuth();
683
703
  return {
684
704
  data: response,
685
705
  error: null
@@ -737,17 +757,25 @@ var Auth = class {
737
757
  * In modern mode, also calls backend to clear the refresh token cookie
738
758
  */
739
759
  async signOut() {
760
+ console.log("[InsForge:Auth] signOut() called");
761
+ console.log("[InsForge:Auth] signOut() stack trace:", new Error().stack);
740
762
  try {
741
763
  if (this.tokenManager.getStrategyId() === "secure") {
764
+ console.log("[InsForge:Auth] signOut() - calling backend /api/auth/logout");
742
765
  try {
743
766
  await this.http.post("/api/auth/logout");
744
- } catch {
767
+ console.log("[InsForge:Auth] signOut() - backend logout successful");
768
+ } catch (e) {
769
+ console.log("[InsForge:Auth] signOut() - backend logout failed (ignored):", e);
745
770
  }
746
771
  }
747
772
  this.tokenManager.clearSession();
748
773
  this.http.setAuthToken(null);
774
+ this.clearAuthenticatedCookie();
775
+ console.log("[InsForge:Auth] signOut() - completed");
749
776
  return { error: null };
750
777
  } catch (error) {
778
+ console.error("[InsForge:Auth] signOut() - error:", error);
751
779
  return {
752
780
  error: new InsForgeError(
753
781
  "Failed to sign out",
@@ -764,16 +792,20 @@ var Auth = class {
764
792
  * @returns New access token or throws an error
765
793
  */
766
794
  async refreshToken() {
795
+ console.log("[InsForge:Auth] refreshToken() called");
767
796
  try {
768
797
  const response = await this.http.post(
769
798
  "/api/auth/refresh"
770
799
  );
800
+ console.log("[InsForge:Auth] refreshToken() - response received, hasAccessToken:", !!response.accessToken);
771
801
  if (response.accessToken) {
802
+ this._detectStorageFromResponse(response.sessionMode);
772
803
  this.tokenManager.setAccessToken(response.accessToken);
773
804
  this.http.setAuthToken(response.accessToken);
774
805
  if (response.user) {
775
806
  this.tokenManager.setUser(response.user);
776
807
  }
808
+ console.log("[InsForge:Auth] refreshToken() - success");
777
809
  return response.accessToken;
778
810
  }
779
811
  throw new InsForgeError(
@@ -782,10 +814,13 @@ var Auth = class {
782
814
  "REFRESH_FAILED"
783
815
  );
784
816
  } catch (error) {
817
+ console.error("[InsForge:Auth] refreshToken() - error:", error);
785
818
  if (error instanceof InsForgeError) {
786
819
  if (error.statusCode === 401 || error.statusCode === 403) {
820
+ console.log("[InsForge:Auth] refreshToken() - clearing session due to 401/403");
787
821
  this.tokenManager.clearSession();
788
822
  this.http.setAuthToken(null);
823
+ this.clearAuthenticatedCookie();
789
824
  }
790
825
  throw error;
791
826
  }
@@ -841,12 +876,17 @@ var Auth = class {
841
876
  * to refresh the session if no access token is available (e.g., after page reload).
842
877
  */
843
878
  async getCurrentUser() {
879
+ console.log("[InsForge:Auth] getCurrentUser() called");
844
880
  try {
845
881
  let accessToken = this.tokenManager.getAccessToken();
846
- if (!accessToken && this.tokenManager.shouldAttemptRefresh()) {
882
+ const shouldRefresh = this.tokenManager.shouldAttemptRefresh();
883
+ console.log("[InsForge:Auth] getCurrentUser() - hasAccessToken:", !!accessToken, "shouldAttemptRefresh:", shouldRefresh);
884
+ if (!accessToken && shouldRefresh) {
885
+ console.log("[InsForge:Auth] getCurrentUser() - attempting refresh");
847
886
  try {
848
887
  accessToken = await this.refreshToken();
849
888
  } catch (error) {
889
+ console.log("[InsForge:Auth] getCurrentUser() - refresh failed:", error);
850
890
  if (error instanceof InsForgeError && (error.statusCode === 401 || error.statusCode === 403)) {
851
891
  return { data: null, error };
852
892
  }
@@ -854,14 +894,17 @@ var Auth = class {
854
894
  }
855
895
  }
856
896
  if (!accessToken) {
897
+ console.log("[InsForge:Auth] getCurrentUser() - no access token, returning null");
857
898
  return { data: null, error: null };
858
899
  }
859
900
  this.http.setAuthToken(accessToken);
901
+ console.log("[InsForge:Auth] getCurrentUser() - fetching user from API");
860
902
  const authResponse = await this.http.get("/api/auth/sessions/current");
861
903
  const { data: profile, error: profileError } = await this.database.from("users").select("*").eq("id", authResponse.user.id).single();
862
904
  if (profileError && profileError.code !== "PGRST116") {
863
905
  return { data: null, error: profileError };
864
906
  }
907
+ console.log("[InsForge:Auth] getCurrentUser() - success");
865
908
  return {
866
909
  data: {
867
910
  user: authResponse.user,
@@ -870,8 +913,12 @@ var Auth = class {
870
913
  error: null
871
914
  };
872
915
  } catch (error) {
916
+ console.error("[InsForge:Auth] getCurrentUser() - catch error:", error);
873
917
  if (error instanceof InsForgeError && error.statusCode === 401) {
874
- await this.signOut();
918
+ console.log("[InsForge:Auth] getCurrentUser() - 401 error, clearing local session only (NOT calling signOut)");
919
+ this.tokenManager.clearSession();
920
+ this.http.setAuthToken(null);
921
+ this.clearAuthenticatedCookie();
875
922
  return { data: null, error: null };
876
923
  }
877
924
  if (error instanceof InsForgeError) {
@@ -1119,6 +1166,8 @@ var Auth = class {
1119
1166
  "/api/auth/email/verify",
1120
1167
  request
1121
1168
  );
1169
+ const sessionMode = response.sessionMode;
1170
+ this._detectStorageFromResponse(sessionMode);
1122
1171
  if (response.accessToken) {
1123
1172
  const session = {
1124
1173
  accessToken: response.accessToken,
@@ -1677,9 +1726,14 @@ function hasAuthenticatedCookie() {
1677
1726
  }
1678
1727
  var InsForgeClient = class {
1679
1728
  constructor(config = {}) {
1729
+ console.log("[InsForge:Client] Initializing SDK");
1680
1730
  this.http = new HttpClient(config);
1681
1731
  this.tokenManager = new TokenManager(config.storage);
1682
- if (hasAuthenticatedCookie()) {
1732
+ const hasAuthCookie = hasAuthenticatedCookie();
1733
+ console.log("[InsForge:Client] hasAuthenticatedCookie:", hasAuthCookie);
1734
+ console.log("[InsForge:Client] document.cookie:", typeof document !== "undefined" ? document.cookie : "N/A (SSR)");
1735
+ if (hasAuthCookie) {
1736
+ console.log("[InsForge:Client] Switching to SecureSessionStorage");
1683
1737
  this.tokenManager.setStrategy(new SecureSessionStorage());
1684
1738
  }
1685
1739
  if (config.edgeFunctionToken) {
@@ -1691,25 +1745,31 @@ var InsForgeClient = class {
1691
1745
  });
1692
1746
  }
1693
1747
  this.http.setRefreshCallback(async () => {
1748
+ console.log("[InsForge:Client] HTTP 401 refresh callback triggered");
1694
1749
  try {
1695
1750
  return await this.auth.refreshToken();
1696
- } catch {
1751
+ } catch (e) {
1752
+ console.log("[InsForge:Client] Refresh callback failed:", e);
1697
1753
  if (this.tokenManager.getStrategyId() === "secure") {
1754
+ console.log("[InsForge:Client] Falling back to LocalSessionStorage");
1698
1755
  this.auth._switchToLocalStorage();
1699
1756
  }
1700
1757
  return null;
1701
1758
  }
1702
1759
  });
1703
1760
  const existingSession = this.tokenManager.getSession();
1761
+ console.log("[InsForge:Client] existingSession:", !!existingSession, "strategyId:", this.tokenManager.getStrategyId());
1704
1762
  if (existingSession?.accessToken) {
1705
1763
  this.http.setAuthToken(existingSession.accessToken);
1706
1764
  } else if (this.tokenManager.getStrategyId() === "secure") {
1765
+ console.log("[InsForge:Client] Secure mode, no session in memory - will refresh on first API call");
1707
1766
  }
1708
1767
  this.auth = new Auth(this.http, this.tokenManager);
1709
1768
  this.database = new Database(this.http, this.tokenManager);
1710
1769
  this.storage = new Storage(this.http);
1711
1770
  this.ai = new AI(this.http);
1712
1771
  this.functions = new Functions(this.http);
1772
+ console.log("[InsForge:Client] SDK initialized");
1713
1773
  }
1714
1774
  /**
1715
1775
  * Get the underlying HTTP client for custom requests