@nauth-toolkit/client 0.1.18 → 0.1.21

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.
@@ -193,12 +193,12 @@ var defaultEndpoints = {
193
193
  mfaPreferred: "/mfa/preferred-method",
194
194
  mfaBackupCodes: "/mfa/backup-codes/generate",
195
195
  mfaExemption: "/mfa/exemption",
196
- socialAuthUrl: "/social/auth-url",
197
- socialCallback: "/social/callback",
198
196
  socialLinked: "/social/linked",
199
197
  socialLink: "/social/link",
200
198
  socialUnlink: "/social/unlink",
201
199
  socialVerify: "/social/:provider/verify",
200
+ socialRedirectStart: "/social/:provider/redirect",
201
+ socialExchange: "/social/exchange",
202
202
  trustDevice: "/trust-device",
203
203
  isTrustedDevice: "/is-trusted-device",
204
204
  auditHistory: "/audit/history",
@@ -350,6 +350,9 @@ var _BrowserStorage = class _BrowserStorage {
350
350
  async removeItem(key) {
351
351
  this.storage.removeItem(key);
352
352
  }
353
+ async clear() {
354
+ this.storage.clear();
355
+ }
353
356
  };
354
357
  __name(_BrowserStorage, "BrowserStorage");
355
358
  var BrowserStorage = _BrowserStorage;
@@ -368,6 +371,9 @@ var _InMemoryStorage = class _InMemoryStorage {
368
371
  async removeItem(key) {
369
372
  this.store.delete(key);
370
373
  }
374
+ async clear() {
375
+ this.store.clear();
376
+ }
371
377
  };
372
378
  __name(_InMemoryStorage, "InMemoryStorage");
373
379
  var InMemoryStorage = _InMemoryStorage;
@@ -492,9 +498,9 @@ var _FetchAdapter = class _FetchAdapter {
492
498
  });
493
499
  if (!response.ok) {
494
500
  const errorData = typeof data === "object" && data !== null ? data : {};
495
- const code = typeof errorData["code"] === "string" ? errorData.code : "INTERNAL_ERROR" /* INTERNAL_ERROR */;
496
- const message = typeof errorData["message"] === "string" ? errorData.message : `Request failed with status ${status}`;
497
- const timestamp = typeof errorData["timestamp"] === "string" ? errorData.timestamp : void 0;
501
+ const code = typeof errorData["code"] === "string" ? errorData["code"] : "INTERNAL_ERROR" /* INTERNAL_ERROR */;
502
+ const message = typeof errorData["message"] === "string" ? errorData["message"] : `Request failed with status ${status}`;
503
+ const timestamp = typeof errorData["timestamp"] === "string" ? errorData["timestamp"] : void 0;
498
504
  const details = errorData["details"];
499
505
  throw new NAuthClientError(code, message, {
500
506
  statusCode: status,
@@ -918,126 +924,59 @@ var _NAuthClient = class _NAuthClient {
918
924
  // Social Authentication
919
925
  // ============================================================================
920
926
  /**
921
- * Start social OAuth flow with automatic state management.
927
+ * Start redirect-first social OAuth flow (web).
928
+ *
929
+ * This performs a browser navigation to:
930
+ * `GET {baseUrl}/social/:provider/redirect?returnTo=...&appState=...`
922
931
  *
923
- * Generates a secure state token, stores OAuth context, and redirects to the OAuth provider.
924
- * After OAuth callback, use `handleOAuthCallback()` to complete authentication.
932
+ * The backend:
933
+ * - generates and stores CSRF state (cluster-safe)
934
+ * - redirects the user to the provider
935
+ * - completes OAuth on callback and sets cookies (or issues an exchange token)
936
+ * - redirects back to `returnTo` with `appState` (and `exchangeToken` for json/hybrid)
925
937
  *
926
938
  * @param provider - OAuth provider ('google', 'apple', 'facebook')
927
- * @param options - Optional configuration
939
+ * @param options - Optional redirect options
928
940
  *
929
941
  * @example
930
942
  * ```typescript
931
- * // Simple usage
932
- * await client.loginWithSocial('google');
933
- *
934
- * // With custom redirect URI
935
- * await client.loginWithSocial('apple', {
936
- * redirectUri: 'https://example.com/auth/callback'
937
- * });
943
+ * await client.loginWithSocial('google', { returnTo: '/auth/callback', appState: '12345' });
938
944
  * ```
939
945
  */
940
- async loginWithSocial(provider, _options) {
946
+ async loginWithSocial(provider, options) {
941
947
  this.eventEmitter.emit({ type: "oauth:started", data: { provider }, timestamp: Date.now() });
942
- const { url } = await this.getSocialAuthUrl({ provider });
943
948
  if (hasWindow()) {
944
- window.location.href = url;
945
- }
946
- }
947
- /**
948
- * Auto-detect and handle OAuth callback.
949
- *
950
- * Call this on app initialization or in callback route.
951
- * Returns null if not an OAuth callback (no provider/code params).
952
- *
953
- * The SDK validates the state token, completes authentication via backend,
954
- * and emits appropriate events.
955
- *
956
- * @param urlOrParams - Optional URL string or URLSearchParams (auto-detects from window.location if not provided)
957
- * @returns AuthResponse if OAuth callback detected, null otherwise
958
- *
959
- * @example
960
- * ```typescript
961
- * // Auto-detect on app init
962
- * const response = await client.handleOAuthCallback();
963
- * if (response) {
964
- * if (response.challengeName) {
965
- * router.navigate(['/challenge', response.challengeName]);
966
- * } else {
967
- * router.navigate(['/']); // Navigate to your app's home route
968
- * }
969
- * }
970
- *
971
- * // In callback route
972
- * const response = await client.handleOAuthCallback(window.location.search);
973
- * ```
974
- */
975
- async handleOAuthCallback(urlOrParams) {
976
- let params;
977
- if (urlOrParams instanceof URLSearchParams) {
978
- params = urlOrParams;
979
- } else if (typeof urlOrParams === "string") {
980
- params = new URLSearchParams(urlOrParams);
981
- } else if (hasWindow()) {
982
- params = new URLSearchParams(window.location.search);
983
- } else {
984
- return null;
985
- }
986
- const provider = params.get("provider");
987
- const code = params.get("code");
988
- const state = params.get("state");
989
- const error = params.get("error");
990
- if (!provider || !code && !error) {
991
- return null;
992
- }
993
- this.eventEmitter.emit({ type: "oauth:callback", data: { provider }, timestamp: Date.now() });
994
- try {
995
- if (error) {
996
- const authError = new NAuthClientError(
997
- "SOCIAL_TOKEN_INVALID" /* SOCIAL_TOKEN_INVALID */,
998
- params.get("error_description") || error,
999
- { details: { error, provider } }
1000
- );
1001
- this.eventEmitter.emit({ type: "oauth:error", data: authError, timestamp: Date.now() });
1002
- throw authError;
1003
- }
1004
- if (!state) {
1005
- throw new NAuthClientError("CHALLENGE_INVALID" /* CHALLENGE_INVALID */, "Missing OAuth state parameter");
949
+ const startPath = this.config.endpoints.socialRedirectStart.replace(":provider", provider);
950
+ const base = this.config.baseUrl.replace(/\/$/, "");
951
+ const startUrl = new URL(`${base}${startPath}`);
952
+ const returnTo = options?.returnTo ?? this.config.redirects?.success ?? "/";
953
+ const action = options?.action ?? "login";
954
+ startUrl.searchParams.set("returnTo", returnTo);
955
+ startUrl.searchParams.set("action", action);
956
+ if (options?.delivery === "cookies" || options?.delivery === "json") {
957
+ startUrl.searchParams.set("delivery", options.delivery);
1006
958
  }
1007
- const response = await this.handleSocialCallback({
1008
- provider,
1009
- code,
1010
- state
1011
- });
1012
- if (response.challengeName) {
1013
- this.eventEmitter.emit({ type: "auth:challenge", data: response, timestamp: Date.now() });
1014
- } else {
1015
- this.eventEmitter.emit({ type: "auth:success", data: response, timestamp: Date.now() });
959
+ if (typeof options?.appState === "string" && options.appState.trim() !== "") {
960
+ startUrl.searchParams.set("appState", options.appState);
1016
961
  }
1017
- this.eventEmitter.emit({ type: "oauth:completed", data: response, timestamp: Date.now() });
1018
- return response;
1019
- } catch (error2) {
1020
- const authError = error2 instanceof NAuthClientError ? error2 : new NAuthClientError(
1021
- "SOCIAL_TOKEN_INVALID" /* SOCIAL_TOKEN_INVALID */,
1022
- error2.message || "OAuth callback failed"
1023
- );
1024
- this.eventEmitter.emit({ type: "oauth:error", data: authError, timestamp: Date.now() });
1025
- throw authError;
962
+ window.location.href = startUrl.toString();
1026
963
  }
1027
964
  }
1028
965
  /**
1029
- * Get social auth URL (low-level API).
966
+ * Exchange an `exchangeToken` (from redirect callback URL) into an AuthResponse.
1030
967
  *
1031
- * For most cases, use `loginWithSocial()` which handles state management automatically.
1032
- */
1033
- async getSocialAuthUrl(request) {
1034
- return this.post(this.config.endpoints.socialAuthUrl, request);
1035
- }
1036
- /**
1037
- * Handle social callback.
968
+ * Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back
969
+ * with `exchangeToken` instead of setting cookies.
970
+ *
971
+ * @param exchangeToken - One-time exchange token from the callback URL
972
+ * @returns AuthResponse
1038
973
  */
1039
- async handleSocialCallback(request) {
1040
- const result = await this.post(this.config.endpoints.socialCallback, request);
974
+ async exchangeSocialRedirect(exchangeToken) {
975
+ const token = exchangeToken?.trim();
976
+ if (!token) {
977
+ throw new NAuthClientError("CHALLENGE_INVALID" /* CHALLENGE_INVALID */, "Missing exchangeToken");
978
+ }
979
+ const result = await this.post(this.config.endpoints.socialExchange, { exchangeToken: token });
1041
980
  await this.handleAuthResponse(result);
1042
981
  return result;
1043
982
  }
@@ -1561,6 +1500,76 @@ var AuthService = class {
1561
1500
  confirmForgotPassword(identifier, code, newPassword) {
1562
1501
  return from(this.client.confirmForgotPassword(identifier, code, newPassword));
1563
1502
  }
1503
+ /**
1504
+ * Change user password (requires current password).
1505
+ *
1506
+ * @param oldPassword - Current password
1507
+ * @param newPassword - New password (must meet requirements)
1508
+ * @returns Observable that completes when password is changed
1509
+ *
1510
+ * @example
1511
+ * ```typescript
1512
+ * this.auth.changePassword('oldPassword123', 'newSecurePassword456!').subscribe({
1513
+ * next: () => console.log('Password changed successfully'),
1514
+ * error: (err) => console.error('Failed to change password:', err)
1515
+ * });
1516
+ * ```
1517
+ */
1518
+ changePassword(oldPassword, newPassword) {
1519
+ return from(this.client.changePassword(oldPassword, newPassword));
1520
+ }
1521
+ /**
1522
+ * Request password change (must change on next login).
1523
+ *
1524
+ * @returns Observable that completes when request is sent
1525
+ */
1526
+ requestPasswordChange() {
1527
+ return from(this.client.requestPasswordChange());
1528
+ }
1529
+ // ============================================================================
1530
+ // Profile Management
1531
+ // ============================================================================
1532
+ /**
1533
+ * Get current user profile.
1534
+ *
1535
+ * @returns Observable of current user profile
1536
+ *
1537
+ * @example
1538
+ * ```typescript
1539
+ * this.auth.getProfile().subscribe(user => {
1540
+ * console.log('User profile:', user);
1541
+ * });
1542
+ * ```
1543
+ */
1544
+ getProfile() {
1545
+ return from(
1546
+ this.client.getProfile().then((user) => {
1547
+ this.currentUserSubject.next(user);
1548
+ return user;
1549
+ })
1550
+ );
1551
+ }
1552
+ /**
1553
+ * Update user profile.
1554
+ *
1555
+ * @param updates - Profile fields to update
1556
+ * @returns Observable of updated user profile
1557
+ *
1558
+ * @example
1559
+ * ```typescript
1560
+ * this.auth.updateProfile({ firstName: 'John', lastName: 'Doe' }).subscribe(user => {
1561
+ * console.log('Profile updated:', user);
1562
+ * });
1563
+ * ```
1564
+ */
1565
+ updateProfile(updates) {
1566
+ return from(
1567
+ this.client.updateProfile(updates).then((user) => {
1568
+ this.currentUserSubject.next(user);
1569
+ return user;
1570
+ })
1571
+ );
1572
+ }
1564
1573
  // ============================================================================
1565
1574
  // Challenge Flow Methods (Essential for any auth flow)
1566
1575
  // ============================================================================
@@ -1617,26 +1626,172 @@ var AuthService = class {
1617
1626
  // ============================================================================
1618
1627
  /**
1619
1628
  * Initiate social OAuth login flow.
1620
- * Redirects to OAuth provider with automatic state management.
1629
+ * Redirects the browser to backend `/auth/social/:provider/redirect`.
1621
1630
  */
1622
1631
  loginWithSocial(provider, options) {
1623
1632
  return this.client.loginWithSocial(provider, options);
1624
1633
  }
1625
1634
  /**
1626
- * Get social auth URL to redirect user for OAuth (low-level API).
1635
+ * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse.
1636
+ *
1637
+ * Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back
1638
+ * with `exchangeToken` instead of setting cookies.
1639
+ *
1640
+ * @param exchangeToken - One-time exchange token from the callback URL
1641
+ * @returns Observable of AuthResponse
1627
1642
  */
1628
- getSocialAuthUrl(provider, redirectUri) {
1629
- return from(
1630
- this.client.getSocialAuthUrl({ provider, redirectUri })
1631
- );
1643
+ exchangeSocialRedirect(exchangeToken) {
1644
+ return from(this.client.exchangeSocialRedirect(exchangeToken).then((res) => this.updateChallengeState(res)));
1632
1645
  }
1633
1646
  /**
1634
- * Handle social auth callback (low-level API).
1647
+ * Verify native social token (mobile).
1648
+ *
1649
+ * @param request - Social verification request with provider and token
1650
+ * @returns Observable of AuthResponse
1635
1651
  */
1636
- handleSocialCallback(provider, code, state) {
1637
- return from(
1638
- this.client.handleSocialCallback({ provider, code, state }).then((res) => this.updateChallengeState(res))
1639
- );
1652
+ verifyNativeSocial(request) {
1653
+ return from(this.client.verifyNativeSocial(request).then((res) => this.updateChallengeState(res)));
1654
+ }
1655
+ /**
1656
+ * Get linked social accounts.
1657
+ *
1658
+ * @returns Observable of linked accounts response
1659
+ */
1660
+ getLinkedAccounts() {
1661
+ return from(this.client.getLinkedAccounts());
1662
+ }
1663
+ /**
1664
+ * Link social account.
1665
+ *
1666
+ * @param provider - Social provider to link
1667
+ * @param code - OAuth authorization code
1668
+ * @param state - OAuth state parameter
1669
+ * @returns Observable with success message
1670
+ */
1671
+ linkSocialAccount(provider, code, state) {
1672
+ return from(this.client.linkSocialAccount(provider, code, state));
1673
+ }
1674
+ /**
1675
+ * Unlink social account.
1676
+ *
1677
+ * @param provider - Social provider to unlink
1678
+ * @returns Observable with success message
1679
+ */
1680
+ unlinkSocialAccount(provider) {
1681
+ return from(this.client.unlinkSocialAccount(provider));
1682
+ }
1683
+ // ============================================================================
1684
+ // MFA Management
1685
+ // ============================================================================
1686
+ /**
1687
+ * Get MFA status for the current user.
1688
+ *
1689
+ * @returns Observable of MFA status
1690
+ */
1691
+ getMfaStatus() {
1692
+ return from(this.client.getMfaStatus());
1693
+ }
1694
+ /**
1695
+ * Get MFA devices for the current user.
1696
+ *
1697
+ * @returns Observable of MFA devices array
1698
+ */
1699
+ getMfaDevices() {
1700
+ return from(this.client.getMfaDevices());
1701
+ }
1702
+ /**
1703
+ * Setup MFA device (authenticated user).
1704
+ *
1705
+ * @param method - MFA method to set up
1706
+ * @returns Observable of setup data
1707
+ */
1708
+ setupMfaDevice(method) {
1709
+ return from(this.client.setupMfaDevice(method));
1710
+ }
1711
+ /**
1712
+ * Verify MFA setup (authenticated user).
1713
+ *
1714
+ * @param method - MFA method
1715
+ * @param setupData - Setup data from setupMfaDevice
1716
+ * @param deviceName - Optional device name
1717
+ * @returns Observable with device ID
1718
+ */
1719
+ verifyMfaSetup(method, setupData, deviceName) {
1720
+ return from(this.client.verifyMfaSetup(method, setupData, deviceName));
1721
+ }
1722
+ /**
1723
+ * Remove MFA device.
1724
+ *
1725
+ * @param method - MFA method to remove
1726
+ * @returns Observable with success message
1727
+ */
1728
+ removeMfaDevice(method) {
1729
+ return from(this.client.removeMfaDevice(method));
1730
+ }
1731
+ /**
1732
+ * Set preferred MFA method.
1733
+ *
1734
+ * @param method - Device method to set as preferred ('totp', 'sms', 'email', or 'passkey')
1735
+ * @returns Observable with success message
1736
+ */
1737
+ setPreferredMfaMethod(method) {
1738
+ return from(this.client.setPreferredMfaMethod(method));
1739
+ }
1740
+ /**
1741
+ * Generate backup codes.
1742
+ *
1743
+ * @returns Observable of backup codes array
1744
+ */
1745
+ generateBackupCodes() {
1746
+ return from(this.client.generateBackupCodes());
1747
+ }
1748
+ /**
1749
+ * Set MFA exemption (admin/test scenarios).
1750
+ *
1751
+ * @param exempt - Whether to exempt user from MFA
1752
+ * @param reason - Optional reason for exemption
1753
+ * @returns Observable that completes when exemption is set
1754
+ */
1755
+ setMfaExemption(exempt, reason) {
1756
+ return from(this.client.setMfaExemption(exempt, reason));
1757
+ }
1758
+ // ============================================================================
1759
+ // Device Trust
1760
+ // ============================================================================
1761
+ /**
1762
+ * Trust current device.
1763
+ *
1764
+ * @returns Observable with device token
1765
+ */
1766
+ trustDevice() {
1767
+ return from(this.client.trustDevice());
1768
+ }
1769
+ /**
1770
+ * Check if the current device is trusted.
1771
+ *
1772
+ * @returns Observable with trusted status
1773
+ */
1774
+ isTrustedDevice() {
1775
+ return from(this.client.isTrustedDevice());
1776
+ }
1777
+ // ============================================================================
1778
+ // Audit History
1779
+ // ============================================================================
1780
+ /**
1781
+ * Get paginated audit history for the current user.
1782
+ *
1783
+ * @param params - Query parameters for filtering and pagination
1784
+ * @returns Observable of audit history response
1785
+ *
1786
+ * @example
1787
+ * ```typescript
1788
+ * this.auth.getAuditHistory({ page: 1, limit: 20, eventType: 'LOGIN_SUCCESS' }).subscribe(history => {
1789
+ * console.log('Audit history:', history);
1790
+ * });
1791
+ * ```
1792
+ */
1793
+ getAuditHistory(params) {
1794
+ return from(this.client.getAuditHistory(params));
1640
1795
  }
1641
1796
  // ============================================================================
1642
1797
  // Escape Hatch
@@ -1644,20 +1799,19 @@ var AuthService = class {
1644
1799
  /**
1645
1800
  * Expose underlying NAuthClient for advanced scenarios.
1646
1801
  *
1647
- * Use this for operations not directly exposed by this service:
1648
- * - Profile management (getProfile, updateProfile)
1649
- * - MFA management (getMfaStatus, setupMfaDevice, etc.)
1650
- * - Social account linking (linkSocialAccount, unlinkSocialAccount)
1651
- * - Audit history (getAuditHistory)
1652
- * - Device trust (trustDevice)
1802
+ * @deprecated All core functionality is now exposed directly on AuthService as Observables.
1803
+ * Use the direct methods on AuthService instead (e.g., `auth.changePassword()` instead of `auth.getClient().changePassword()`).
1804
+ * This method is kept for backward compatibility only and may be removed in a future version.
1805
+ *
1806
+ * @returns The underlying NAuthClient instance
1653
1807
  *
1654
1808
  * @example
1655
1809
  * ```typescript
1656
- * // Get MFA status
1810
+ * // Deprecated - use direct methods instead
1657
1811
  * const status = await this.auth.getClient().getMfaStatus();
1658
1812
  *
1659
- * // Update profile
1660
- * const user = await this.auth.getClient().updateProfile({ firstName: 'John' });
1813
+ * // Preferred - use Observable-based methods
1814
+ * this.auth.getMfaStatus().subscribe(status => ...);
1661
1815
  * ```
1662
1816
  */
1663
1817
  getClient() {
@@ -1736,12 +1890,11 @@ var authInterceptor = /* @__PURE__ */ __name((req, next) => {
1736
1890
  const refreshPath = endpoints.refresh ?? "/refresh";
1737
1891
  const loginPath = endpoints.login ?? "/login";
1738
1892
  const signupPath = endpoints.signup ?? "/signup";
1739
- const socialAuthUrlPath = endpoints.socialAuthUrl ?? "/social/auth-url";
1740
- const socialCallbackPath = endpoints.socialCallback ?? "/social/callback";
1893
+ const socialExchangePath = endpoints.socialExchange ?? "/social/exchange";
1741
1894
  const refreshUrl = `${baseUrl}${refreshPath}`;
1742
1895
  const isAuthApiRequest = req.url.includes(baseUrl);
1743
1896
  const isRefreshEndpoint = req.url.includes(refreshPath);
1744
- const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialAuthUrlPath) || req.url.includes(socialCallbackPath);
1897
+ const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
1745
1898
  let authReq = req;
1746
1899
  if (tokenDelivery === "cookies") {
1747
1900
  authReq = authReq.clone({ withCredentials: true });
@@ -1876,10 +2029,10 @@ var _AuthGuard = class _AuthGuard {
1876
2029
  __name(_AuthGuard, "AuthGuard");
1877
2030
  var AuthGuard = _AuthGuard;
1878
2031
 
1879
- // src/angular/oauth-callback.guard.ts
2032
+ // src/angular/social-redirect-callback.guard.ts
1880
2033
  import { inject as inject5, PLATFORM_ID as PLATFORM_ID2 } from "@angular/core";
1881
2034
  import { isPlatformBrowser as isPlatformBrowser2 } from "@angular/common";
1882
- var oauthCallbackGuard = /* @__PURE__ */ __name(async () => {
2035
+ var socialRedirectCallbackGuard = /* @__PURE__ */ __name(async () => {
1883
2036
  const auth = inject5(AuthService);
1884
2037
  const config = inject5(NAUTH_CLIENT_CONFIG);
1885
2038
  const platformId = inject5(PLATFORM_ID2);
@@ -1887,38 +2040,28 @@ var oauthCallbackGuard = /* @__PURE__ */ __name(async () => {
1887
2040
  if (!isBrowser) {
1888
2041
  return false;
1889
2042
  }
1890
- try {
1891
- const response = await auth.getClient().handleOAuthCallback();
1892
- if (!response) {
1893
- const homeUrl = config.redirects?.success || "/";
1894
- window.location.replace(homeUrl);
1895
- return false;
1896
- }
1897
- if (response.challengeName) {
1898
- const challengeBase = config.redirects?.challengeBase || "/auth/challenge";
1899
- const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, "-");
1900
- const challengePath = `${challengeBase}/${challengeRoute}`;
1901
- if (config.debug) {
1902
- console.warn("[oauth-callback-guard] Redirecting to challenge:", challengePath);
1903
- }
1904
- window.location.replace(challengePath);
1905
- } else {
1906
- const successUrl = config.redirects?.success || "/";
1907
- if (config.debug) {
1908
- console.warn("[oauth-callback-guard] Redirecting to success URL:", successUrl);
1909
- }
1910
- window.location.replace(successUrl);
1911
- }
1912
- } catch (error) {
1913
- console.error("[oauth-callback-guard] OAuth callback failed:", error);
2043
+ const params = new URLSearchParams(window.location.search);
2044
+ const error = params.get("error");
2045
+ const exchangeToken = params.get("exchangeToken");
2046
+ if (error) {
1914
2047
  const errorUrl = config.redirects?.oauthError || "/login";
1915
- if (config.debug) {
1916
- console.warn("[oauth-callback-guard] Redirecting to error URL:", errorUrl);
1917
- }
1918
2048
  window.location.replace(errorUrl);
2049
+ return false;
2050
+ }
2051
+ if (!exchangeToken) {
2052
+ return true;
2053
+ }
2054
+ const response = await auth.getClient().exchangeSocialRedirect(exchangeToken);
2055
+ if (response.challengeName) {
2056
+ const challengeBase = config.redirects?.challengeBase || "/auth/challenge";
2057
+ const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, "-");
2058
+ window.location.replace(`${challengeBase}/${challengeRoute}`);
2059
+ return false;
1919
2060
  }
2061
+ const successUrl = config.redirects?.success || "/";
2062
+ window.location.replace(successUrl);
1920
2063
  return false;
1921
- }, "oauthCallbackGuard");
2064
+ }, "socialRedirectCallbackGuard");
1922
2065
 
1923
2066
  // src/angular/auth.module.ts
1924
2067
  import { NgModule } from "@angular/core";
@@ -1952,6 +2095,6 @@ export {
1952
2095
  NAuthModule,
1953
2096
  authGuard,
1954
2097
  authInterceptor,
1955
- oauthCallbackGuard
2098
+ socialRedirectCallbackGuard
1956
2099
  };
1957
2100
  //# sourceMappingURL=index.mjs.map