@insforge/sdk 1.1.2-pkce.0 → 1.1.2-pkce.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
@@ -304,21 +304,12 @@ var TokenManager = class {
304
304
  }
305
305
  };
306
306
 
307
- // src/modules/auth.ts
308
- function isHostedAuthEnvironment() {
309
- if (typeof window === "undefined") {
310
- return false;
311
- }
312
- const { hostname, port, protocol } = window.location;
313
- if (hostname === "localhost" && port === "7130") {
314
- return true;
315
- }
316
- if (protocol === "https:" && hostname.endsWith(".insforge.app")) {
317
- return true;
318
- }
319
- return false;
320
- }
307
+ // src/modules/auth/helpers.ts
321
308
  var PKCE_VERIFIER_KEY = "insforge_pkce_verifier";
309
+ function base64UrlEncode(buffer) {
310
+ const base64 = btoa(String.fromCharCode(...buffer));
311
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
312
+ }
322
313
  function generateCodeVerifier() {
323
314
  const array = new Uint8Array(32);
324
315
  crypto.getRandomValues(array);
@@ -330,10 +321,6 @@ async function generateCodeChallenge(verifier) {
330
321
  const hash = await crypto.subtle.digest("SHA-256", data);
331
322
  return base64UrlEncode(new Uint8Array(hash));
332
323
  }
333
- function base64UrlEncode(buffer) {
334
- const base64 = btoa(String.fromCharCode(...buffer));
335
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
336
- }
337
324
  function storePkceVerifier(verifier) {
338
325
  if (typeof sessionStorage !== "undefined") {
339
326
  sessionStorage.setItem(PKCE_VERIFIER_KEY, verifier);
@@ -349,6 +336,42 @@ function retrievePkceVerifier() {
349
336
  }
350
337
  return verifier;
351
338
  }
339
+ function isHostedAuthEnvironment() {
340
+ if (typeof window === "undefined") {
341
+ return false;
342
+ }
343
+ const { hostname, port, protocol } = window.location;
344
+ if (hostname === "localhost" && port === "7130") {
345
+ return true;
346
+ }
347
+ if (protocol === "https:" && hostname.endsWith(".insforge.app")) {
348
+ return true;
349
+ }
350
+ return false;
351
+ }
352
+ function wrapError(error, fallbackMessage) {
353
+ if (error instanceof InsForgeError) {
354
+ return { data: null, error };
355
+ }
356
+ return {
357
+ data: null,
358
+ error: new InsForgeError(
359
+ error instanceof Error ? error.message : fallbackMessage,
360
+ 500,
361
+ "UNEXPECTED_ERROR"
362
+ )
363
+ };
364
+ }
365
+ function cleanUrlParams(...params) {
366
+ if (typeof window === "undefined") {
367
+ return;
368
+ }
369
+ const url = new URL(window.location.href);
370
+ params.forEach((p) => url.searchParams.delete(p));
371
+ window.history.replaceState({}, document.title, url.toString());
372
+ }
373
+
374
+ // src/modules/auth/auth.ts
352
375
  var Auth = class {
353
376
  constructor(http, tokenManager) {
354
377
  this.http = http;
@@ -356,12 +379,31 @@ var Auth = class {
356
379
  this.authCallbackHandled = this.detectAuthCallback();
357
380
  }
358
381
  /**
359
- * Automatically detect and handle OAuth callback parameters in the URL
360
- * This runs after initialization to seamlessly complete the OAuth flow
361
- *
362
- * Supports two flows:
363
- * - PKCE flow (new): Backend returns `insforge_code` param, exchanged for tokens
364
- * - Legacy flow: Backend returns tokens directly in URL (backward compatible)
382
+ * Save session from API response
383
+ * Handles token storage, CSRF token, and HTTP client auth header
384
+ */
385
+ saveSessionFromResponse(response) {
386
+ if (isHostedAuthEnvironment() || !response.accessToken || !response.user) {
387
+ return false;
388
+ }
389
+ const session = {
390
+ accessToken: response.accessToken,
391
+ user: response.user
392
+ };
393
+ if (response.csrfToken) {
394
+ this.tokenManager.setMemoryMode();
395
+ setCsrfToken(response.csrfToken);
396
+ }
397
+ this.tokenManager.saveSession(session);
398
+ this.http.setAuthToken(response.accessToken);
399
+ return true;
400
+ }
401
+ // ============================================================================
402
+ // OAuth Callback Detection (runs on initialization)
403
+ // ============================================================================
404
+ /**
405
+ * Detect and handle OAuth callback parameters in URL
406
+ * Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)
365
407
  */
366
408
  async detectAuthCallback() {
367
409
  if (typeof window === "undefined") return;
@@ -369,17 +411,13 @@ var Auth = class {
369
411
  const params = new URLSearchParams(window.location.search);
370
412
  const error = params.get("error");
371
413
  if (error) {
372
- const url = new URL(window.location.href);
373
- url.searchParams.delete("error");
374
- window.history.replaceState({}, document.title, url.toString());
414
+ cleanUrlParams("error");
375
415
  console.debug("OAuth callback error:", error);
376
416
  return;
377
417
  }
378
418
  const code = params.get("insforge_code");
379
419
  if (code) {
380
- const url = new URL(window.location.href);
381
- url.searchParams.delete("insforge_code");
382
- window.history.replaceState({}, document.title, url.toString());
420
+ cleanUrlParams("insforge_code");
383
421
  const { error: exchangeError } = await this.exchangeOAuthCode(code);
384
422
  if (exchangeError) {
385
423
  console.debug("OAuth code exchange failed:", exchangeError.message);
@@ -389,9 +427,9 @@ var Auth = class {
389
427
  const accessToken = params.get("access_token");
390
428
  const userId = params.get("user_id");
391
429
  const email = params.get("email");
392
- const name = params.get("name");
393
- const csrfToken = params.get("csrf_token");
394
430
  if (accessToken && userId && email) {
431
+ const csrfToken = params.get("csrf_token");
432
+ const name = params.get("name");
395
433
  if (csrfToken) {
396
434
  this.tokenManager.setMemoryMode();
397
435
  setCsrfToken(csrfToken);
@@ -410,93 +448,62 @@ var Auth = class {
410
448
  };
411
449
  this.tokenManager.saveSession(session);
412
450
  this.http.setAuthToken(accessToken);
413
- const url = new URL(window.location.href);
414
- url.searchParams.delete("access_token");
415
- url.searchParams.delete("user_id");
416
- url.searchParams.delete("email");
417
- url.searchParams.delete("name");
418
- url.searchParams.delete("csrf_token");
419
- window.history.replaceState({}, document.title, url.toString());
451
+ cleanUrlParams("access_token", "user_id", "email", "name", "csrf_token");
420
452
  }
421
453
  } catch (error) {
422
454
  console.debug("OAuth callback detection skipped:", error);
423
455
  }
424
456
  }
425
- /**
426
- * Sign up a new user
427
- */
457
+ // ============================================================================
458
+ // Sign Up / Sign In / Sign Out
459
+ // ============================================================================
428
460
  async signUp(request) {
429
461
  try {
430
- const response = await this.http.post("/api/auth/users", request, { credentials: "include" });
431
- if (response.accessToken && response.user && !isHostedAuthEnvironment()) {
432
- const session = {
433
- accessToken: response.accessToken,
434
- user: response.user
435
- };
436
- if (response.csrfToken) {
437
- this.tokenManager.setMemoryMode();
438
- setCsrfToken(response.csrfToken);
439
- }
440
- this.tokenManager.saveSession(session);
441
- this.http.setAuthToken(response.accessToken);
462
+ const response = await this.http.post(
463
+ "/api/auth/users",
464
+ request,
465
+ { credentials: "include" }
466
+ );
467
+ if (response.accessToken && response.user) {
468
+ this.saveSessionFromResponse(response);
442
469
  }
443
- return {
444
- data: response,
445
- error: null
446
- };
470
+ return { data: response, error: null };
447
471
  } catch (error) {
448
- if (error instanceof InsForgeError) {
449
- return { data: null, error };
450
- }
451
- return {
452
- data: null,
453
- error: new InsForgeError(
454
- error instanceof Error ? error.message : "An unexpected error occurred during sign up",
455
- 500,
456
- "UNEXPECTED_ERROR"
457
- )
458
- };
472
+ return wrapError(error, "An unexpected error occurred during sign up");
459
473
  }
460
474
  }
461
- /**
462
- * Sign in with email and password
463
- */
464
475
  async signInWithPassword(request) {
465
476
  try {
466
- const response = await this.http.post("/api/auth/sessions", request, { credentials: "include" });
467
- if (!isHostedAuthEnvironment()) {
468
- const session = {
469
- accessToken: response.accessToken,
470
- user: response.user
471
- };
472
- if (response.csrfToken) {
473
- this.tokenManager.setMemoryMode();
474
- setCsrfToken(response.csrfToken);
475
- }
476
- this.tokenManager.saveSession(session);
477
- this.http.setAuthToken(response.accessToken);
478
- }
479
- return {
480
- data: response,
481
- error: null
482
- };
477
+ const response = await this.http.post(
478
+ "/api/auth/sessions",
479
+ request,
480
+ { credentials: "include" }
481
+ );
482
+ this.saveSessionFromResponse(response);
483
+ return { data: response, error: null };
483
484
  } catch (error) {
484
- if (error instanceof InsForgeError) {
485
- return { data: null, error };
485
+ return wrapError(error, "An unexpected error occurred during sign in");
486
+ }
487
+ }
488
+ async signOut() {
489
+ try {
490
+ try {
491
+ await this.http.post("/api/auth/logout", void 0, { credentials: "include" });
492
+ } catch {
486
493
  }
487
- return {
488
- data: null,
489
- error: new InsForgeError(
490
- "An unexpected error occurred during sign in",
491
- 500,
492
- "UNEXPECTED_ERROR"
493
- )
494
- };
494
+ this.tokenManager.clearSession();
495
+ this.http.setAuthToken(null);
496
+ clearCsrfToken();
497
+ return { error: null };
498
+ } catch {
499
+ return { error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR") };
495
500
  }
496
501
  }
502
+ // ============================================================================
503
+ // OAuth Authentication
504
+ // ============================================================================
497
505
  /**
498
- * Sign in with OAuth provider
499
- * Uses PKCE (Proof Key for Code Exchange) for enhanced security
506
+ * Sign in with OAuth provider using PKCE flow
500
507
  */
501
508
  async signInWithOAuth(options) {
502
509
  try {
@@ -504,25 +511,18 @@ var Auth = class {
504
511
  const codeVerifier = generateCodeVerifier();
505
512
  const codeChallenge = await generateCodeChallenge(codeVerifier);
506
513
  storePkceVerifier(codeVerifier);
507
- const params = {
508
- code_challenge: codeChallenge
509
- };
510
- if (redirectTo) {
511
- params.redirect_uri = redirectTo;
512
- }
513
- const endpoint = `/api/auth/oauth/${provider}`;
514
- const response = await this.http.get(endpoint, { params });
514
+ const params = { code_challenge: codeChallenge };
515
+ if (redirectTo) params.redirect_uri = redirectTo;
516
+ const response = await this.http.get(
517
+ `/api/auth/oauth/${provider}`,
518
+ { params }
519
+ );
515
520
  if (typeof window !== "undefined" && !skipBrowserRedirect) {
516
521
  window.location.href = response.authUrl;
517
522
  return { data: {}, error: null };
518
523
  }
519
524
  return {
520
- data: {
521
- url: response.authUrl,
522
- provider,
523
- codeVerifier
524
- // Return verifier for manual flow (skipBrowserRedirect)
525
- },
525
+ data: { url: response.authUrl, provider, codeVerifier },
526
526
  error: null
527
527
  };
528
528
  } catch (error) {
@@ -541,30 +541,7 @@ var Auth = class {
541
541
  }
542
542
  /**
543
543
  * Exchange OAuth authorization code for tokens (PKCE flow)
544
- *
545
- * After OAuth callback redirects with an `insforge_code` parameter, call this method
546
- * to exchange it for access tokens. The code verifier is automatically
547
- * retrieved from sessionStorage if available.
548
- *
549
- * Note: This is called automatically by the SDK on initialization. You typically
550
- * don't need to call this directly unless using `skipBrowserRedirect: true`.
551
- *
552
- * @param code - The authorization code from OAuth callback URL
553
- * @param codeVerifier - Optional code verifier (auto-retrieved from sessionStorage if not provided)
554
- * @returns Session data with access token and user info
555
- *
556
- * @example
557
- * ```ts
558
- * // Automatic verifier retrieval (recommended for browser)
559
- * const params = new URLSearchParams(window.location.search);
560
- * const code = params.get('insforge_code');
561
- * if (code) {
562
- * const { data, error } = await insforge.auth.exchangeOAuthCode(code);
563
- * }
564
- *
565
- * // Manual verifier (for custom flows)
566
- * const { data, error } = await insforge.auth.exchangeOAuthCode(code, codeVerifier);
567
- * ```
544
+ * Called automatically on initialization when insforge_code is in URL
568
545
  */
569
546
  async exchangeOAuthCode(code, codeVerifier) {
570
547
  try {
@@ -579,23 +556,9 @@ var Auth = class {
579
556
  )
580
557
  };
581
558
  }
582
- const request = {
583
- code,
584
- code_verifier: verifier
585
- };
559
+ const request = { code, code_verifier: verifier };
586
560
  const response = await this.http.post("/api/auth/oauth/exchange", request, { credentials: "include" });
587
- if (!isHostedAuthEnvironment()) {
588
- const session = {
589
- accessToken: response.accessToken,
590
- user: response.user
591
- };
592
- if (response.csrfToken) {
593
- this.tokenManager.setMemoryMode();
594
- setCsrfToken(response.csrfToken);
595
- }
596
- this.tokenManager.saveSession(session);
597
- this.http.setAuthToken(response.accessToken);
598
- }
561
+ this.saveSessionFromResponse(response);
599
562
  return {
600
563
  data: {
601
564
  accessToken: response.accessToken,
@@ -605,108 +568,14 @@ var Auth = class {
605
568
  error: null
606
569
  };
607
570
  } catch (error) {
608
- if (error instanceof InsForgeError) {
609
- return { data: null, error };
610
- }
611
- return {
612
- data: null,
613
- error: new InsForgeError(
614
- "An unexpected error occurred during OAuth code exchange",
615
- 500,
616
- "UNEXPECTED_ERROR"
617
- )
618
- };
571
+ return wrapError(error, "An unexpected error occurred during OAuth code exchange");
619
572
  }
620
573
  }
574
+ // ============================================================================
575
+ // Session Management
576
+ // ============================================================================
621
577
  /**
622
- * Sign out the current user
623
- */
624
- async signOut() {
625
- try {
626
- try {
627
- await this.http.post("/api/auth/logout", void 0, { credentials: "include" });
628
- } catch {
629
- }
630
- this.tokenManager.clearSession();
631
- this.http.setAuthToken(null);
632
- clearCsrfToken();
633
- return { error: null };
634
- } catch (error) {
635
- return {
636
- error: new InsForgeError(
637
- "Failed to sign out",
638
- 500,
639
- "SIGNOUT_ERROR"
640
- )
641
- };
642
- }
643
- }
644
- /**
645
- * Get all public authentication configuration (OAuth + Email)
646
- * Returns both OAuth providers and email authentication settings in one request
647
- * This is a public endpoint that doesn't require authentication
648
- *
649
- * @returns Complete public authentication configuration including OAuth providers and email auth settings
650
- *
651
- * @example
652
- * ```ts
653
- * const { data, error } = await insforge.auth.getPublicAuthConfig();
654
- * if (data) {
655
- * console.log(`OAuth providers: ${data.oauth.data.length}`);
656
- * console.log(`Password min length: ${data.email.passwordMinLength}`);
657
- * }
658
- * ```
659
- */
660
- async getPublicAuthConfig() {
661
- try {
662
- const response = await this.http.get("/api/auth/public-config");
663
- return {
664
- data: response,
665
- error: null
666
- };
667
- } catch (error) {
668
- if (error instanceof InsForgeError) {
669
- return { data: null, error };
670
- }
671
- return {
672
- data: null,
673
- error: new InsForgeError(
674
- "An unexpected error occurred while fetching public authentication configuration",
675
- 500,
676
- "UNEXPECTED_ERROR"
677
- )
678
- };
679
- }
680
- }
681
- /**
682
- * Get any user's profile by ID
683
- * Returns profile information from the users table
684
- */
685
- async getProfile(userId) {
686
- try {
687
- const response = await this.http.get(`/api/auth/profiles/${userId}`);
688
- return {
689
- data: response,
690
- error: null
691
- };
692
- } catch (error) {
693
- if (error instanceof InsForgeError) {
694
- return { data: null, error };
695
- }
696
- return {
697
- data: null,
698
- error: new InsForgeError(
699
- "An unexpected error occurred while fetching user profile",
700
- 500,
701
- "UNEXPECTED_ERROR"
702
- )
703
- };
704
- }
705
- }
706
- /**
707
- * Get the current session (only session data, no API call)
708
- * Returns the stored JWT token and basic user info from local storage
709
- * Automatically waits for any pending OAuth callback to complete first
578
+ * Get current session, automatically waits for pending OAuth callback
710
579
  */
711
580
  async getCurrentSession() {
712
581
  await this.authCallbackHandled;
@@ -722,38 +591,24 @@ var Auth = class {
722
591
  if (typeof window !== "undefined") {
723
592
  try {
724
593
  const csrfToken = getCsrfToken();
725
- const response = await this.http.post(
726
- "/api/auth/refresh",
727
- void 0,
728
- {
729
- headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
730
- credentials: "include"
731
- }
732
- );
594
+ const response = await this.http.post("/api/auth/refresh", void 0, {
595
+ headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
596
+ credentials: "include"
597
+ });
733
598
  if (response.accessToken) {
734
599
  this.tokenManager.setMemoryMode();
735
600
  this.tokenManager.setAccessToken(response.accessToken);
736
601
  this.http.setAuthToken(response.accessToken);
737
- if (response.user) {
738
- this.tokenManager.setUser(response.user);
739
- }
740
- if (response.csrfToken) {
741
- setCsrfToken(response.csrfToken);
742
- }
743
- return {
744
- data: { session: this.tokenManager.getSession() },
745
- error: null
746
- };
602
+ if (response.user) this.tokenManager.setUser(response.user);
603
+ if (response.csrfToken) setCsrfToken(response.csrfToken);
604
+ return { data: { session: this.tokenManager.getSession() }, error: null };
747
605
  }
748
606
  } catch (error) {
749
607
  if (error instanceof InsForgeError) {
750
608
  if (error.statusCode === 404) {
751
609
  this.tokenManager.setStorageMode();
752
610
  const session2 = this.tokenManager.getSession();
753
- if (session2) {
754
- return { data: { session: session2 }, error: null };
755
- }
756
- return { data: { session: null }, error: null };
611
+ return { data: { session: session2 }, error: null };
757
612
  }
758
613
  return { data: { session: null }, error };
759
614
  }
@@ -774,11 +629,17 @@ var Auth = class {
774
629
  };
775
630
  }
776
631
  }
777
- /**
778
- * Set/Update the current user's profile
779
- * Updates profile information in the users table (supports any dynamic fields)
780
- * Requires authentication
781
- */
632
+ // ============================================================================
633
+ // Profile Management
634
+ // ============================================================================
635
+ async getProfile(userId) {
636
+ try {
637
+ const response = await this.http.get(`/api/auth/profiles/${userId}`);
638
+ return { data: response, error: null };
639
+ } catch (error) {
640
+ return wrapError(error, "An unexpected error occurred while fetching user profile");
641
+ }
642
+ }
782
643
  async setProfile(profile) {
783
644
  try {
784
645
  const response = await this.http.patch(
@@ -787,217 +648,89 @@ var Auth = class {
787
648
  );
788
649
  const currentUser = this.tokenManager.getUser();
789
650
  if (currentUser && response.profile !== void 0) {
790
- this.tokenManager.setUser({
791
- ...currentUser,
792
- profile: response.profile
793
- });
651
+ this.tokenManager.setUser({ ...currentUser, profile: response.profile });
794
652
  }
795
- return {
796
- data: response,
797
- error: null
798
- };
653
+ return { data: response, error: null };
799
654
  } catch (error) {
800
- if (error instanceof InsForgeError) {
801
- return { data: null, error };
802
- }
803
- return {
804
- data: null,
805
- error: new InsForgeError(
806
- "An unexpected error occurred while updating user profile",
807
- 500,
808
- "UNEXPECTED_ERROR"
809
- )
810
- };
655
+ return wrapError(error, "An unexpected error occurred while updating user profile");
811
656
  }
812
657
  }
813
- /**
814
- * Resend email verification (code or link based on config)
815
- *
816
- * Resend email verification when the previous OTP has expired or was not received.
817
- * Uses the method configured in auth settings (verifyEmailMethod).
818
- * When method is 'code', sends a 6-digit numeric code. When method is 'link', sends a magic link.
819
- * Prevents user enumeration by returning success even if email doesn't exist.
820
- */
658
+ // ============================================================================
659
+ // Email Verification
660
+ // ============================================================================
821
661
  async resendVerificationEmail(request) {
822
662
  try {
823
663
  const response = await this.http.post(
824
664
  "/api/auth/email/send-verification",
825
665
  request
826
666
  );
827
- return {
828
- data: response,
829
- error: null
830
- };
667
+ return { data: response, error: null };
831
668
  } catch (error) {
832
- if (error instanceof InsForgeError) {
833
- return { data: null, error };
834
- }
835
- return {
836
- data: null,
837
- error: new InsForgeError(
838
- "An unexpected error occurred while sending verification code",
839
- 500,
840
- "UNEXPECTED_ERROR"
841
- )
842
- };
669
+ return wrapError(error, "An unexpected error occurred while sending verification code");
843
670
  }
844
671
  }
845
- /**
846
- * @deprecated Use `resendVerificationEmail` instead. This method will be removed in a future version.
847
- */
672
+ /** @deprecated Use `resendVerificationEmail` instead */
848
673
  async sendVerificationEmail(request) {
849
674
  return this.resendVerificationEmail(request);
850
675
  }
851
- /**
852
- * Send password reset (code or link based on config)
853
- *
854
- * Send password reset email using the method configured in auth settings (resetPasswordMethod).
855
- * When method is 'code', sends a 6-digit numeric code for two-step flow.
856
- * When method is 'link', sends a magic link.
857
- * Prevents user enumeration by returning success even if email doesn't exist.
858
- */
676
+ async verifyEmail(request) {
677
+ try {
678
+ const response = await this.http.post(
679
+ "/api/auth/email/verify",
680
+ request,
681
+ { credentials: "include" }
682
+ );
683
+ this.saveSessionFromResponse(response);
684
+ return { data: response, error: null };
685
+ } catch (error) {
686
+ return wrapError(error, "An unexpected error occurred while verifying email");
687
+ }
688
+ }
689
+ // ============================================================================
690
+ // Password Reset
691
+ // ============================================================================
859
692
  async sendResetPasswordEmail(request) {
860
693
  try {
861
694
  const response = await this.http.post(
862
695
  "/api/auth/email/send-reset-password",
863
696
  request
864
697
  );
865
- return {
866
- data: response,
867
- error: null
868
- };
698
+ return { data: response, error: null };
869
699
  } catch (error) {
870
- if (error instanceof InsForgeError) {
871
- return { data: null, error };
872
- }
873
- return {
874
- data: null,
875
- error: new InsForgeError(
876
- "An unexpected error occurred while sending password reset code",
877
- 500,
878
- "UNEXPECTED_ERROR"
879
- )
880
- };
700
+ return wrapError(error, "An unexpected error occurred while sending password reset code");
881
701
  }
882
702
  }
883
- /**
884
- * Exchange reset password code for reset token
885
- *
886
- * Step 1 of two-step password reset flow (only used when resetPasswordMethod is 'code'):
887
- * 1. Verify the 6-digit code sent to user's email
888
- * 2. Return a reset token that can be used to actually reset the password
889
- *
890
- * This endpoint is not used when resetPasswordMethod is 'link' (magic link flow is direct).
891
- */
892
703
  async exchangeResetPasswordToken(request) {
893
704
  try {
894
705
  const response = await this.http.post(
895
706
  "/api/auth/email/exchange-reset-password-token",
896
707
  request
897
708
  );
898
- return {
899
- data: response,
900
- error: null
901
- };
709
+ return { data: response, error: null };
902
710
  } catch (error) {
903
- if (error instanceof InsForgeError) {
904
- return { data: null, error };
905
- }
906
- return {
907
- data: null,
908
- error: new InsForgeError(
909
- "An unexpected error occurred while verifying reset code",
910
- 500,
911
- "UNEXPECTED_ERROR"
912
- )
913
- };
711
+ return wrapError(error, "An unexpected error occurred while verifying reset code");
914
712
  }
915
713
  }
916
- /**
917
- * Reset password with token
918
- *
919
- * Reset user password with a token. The token can be:
920
- * - Magic link token (64-character hex token from send-reset-password when method is 'link')
921
- * - Reset token (from exchange-reset-password-token after code verification when method is 'code')
922
- *
923
- * Both token types use RESET_PASSWORD purpose and are verified the same way.
924
- *
925
- * Flow summary:
926
- * - Code method: send-reset-password → exchange-reset-password-token → reset-password (with resetToken)
927
- * - Link method: send-reset-password → reset-password (with link token directly)
928
- */
929
714
  async resetPassword(request) {
930
715
  try {
931
716
  const response = await this.http.post(
932
717
  "/api/auth/email/reset-password",
933
718
  request
934
719
  );
935
- return {
936
- data: response,
937
- error: null
938
- };
720
+ return { data: response, error: null };
939
721
  } catch (error) {
940
- if (error instanceof InsForgeError) {
941
- return { data: null, error };
942
- }
943
- return {
944
- data: null,
945
- error: new InsForgeError(
946
- "An unexpected error occurred while resetting password",
947
- 500,
948
- "UNEXPECTED_ERROR"
949
- )
950
- };
722
+ return wrapError(error, "An unexpected error occurred while resetting password");
951
723
  }
952
724
  }
953
- /**
954
- * Verify email with code or link
955
- *
956
- * Verify email address using the method configured in auth settings (verifyEmailMethod):
957
- * - Code verification: Provide both `email` and `otp` (6-digit numeric code)
958
- * - Link verification: Provide only `otp` (64-character hex token from magic link)
959
- *
960
- * Successfully verified users will receive a session token.
961
- *
962
- * The email verification link sent to users always points to the backend API endpoint.
963
- * If `verifyEmailRedirectTo` is configured, the backend will redirect to that URL after successful verification.
964
- * Otherwise, a default success page is displayed.
965
- */
966
- async verifyEmail(request) {
725
+ // ============================================================================
726
+ // Configuration
727
+ // ============================================================================
728
+ async getPublicAuthConfig() {
967
729
  try {
968
- const response = await this.http.post(
969
- "/api/auth/email/verify",
970
- request,
971
- { credentials: "include" }
972
- );
973
- if (!isHostedAuthEnvironment()) {
974
- const session = {
975
- accessToken: response.accessToken,
976
- user: response.user
977
- };
978
- if (response.csrfToken) {
979
- this.tokenManager.setMemoryMode();
980
- setCsrfToken(response.csrfToken);
981
- }
982
- this.tokenManager.saveSession(session);
983
- this.http.setAuthToken(response.accessToken);
984
- }
985
- return {
986
- data: response,
987
- error: null
988
- };
730
+ const response = await this.http.get("/api/auth/public-config");
731
+ return { data: response, error: null };
989
732
  } catch (error) {
990
- if (error instanceof InsForgeError) {
991
- return { data: null, error };
992
- }
993
- return {
994
- data: null,
995
- error: new InsForgeError(
996
- "An unexpected error occurred while verifying email",
997
- 500,
998
- "UNEXPECTED_ERROR"
999
- )
1000
- };
733
+ return wrapError(error, "An unexpected error occurred while fetching auth configuration");
1001
734
  }
1002
735
  }
1003
736
  };