@nauth-toolkit/client 0.1.21 → 0.1.23

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.
@@ -21,6 +21,13 @@ interface AuthUser {
21
21
  mfaEnabled?: boolean;
22
22
  socialProviders?: string[] | null;
23
23
  hasPasswordHash: boolean;
24
+ /**
25
+ * Authentication method used to create the current session.
26
+ *
27
+ * This is session-scoped (how the user logged in this time), not an account capability.
28
+ * Use `hasPasswordHash` and `socialProviders` to determine what login methods the account supports.
29
+ */
30
+ sessionAuthMethod?: string | null;
24
31
  createdAt?: string | Date;
25
32
  updatedAt?: string | Date;
26
33
  }
@@ -456,6 +463,16 @@ interface AuthResponse {
456
463
  refreshToken?: string;
457
464
  accessTokenExpiresAt?: number;
458
465
  refreshTokenExpiresAt?: number;
466
+ /**
467
+ * Authentication method used to create the current session.
468
+ *
469
+ * Examples:
470
+ * - `password`
471
+ * - `google`
472
+ * - `apple`
473
+ * - `facebook`
474
+ */
475
+ authMethod?: string;
459
476
  trusted?: boolean;
460
477
  deviceToken?: string;
461
478
  challengeName?: AuthChallenge;
@@ -796,12 +813,6 @@ interface SocialLoginOptions {
796
813
  * Default: 'login'
797
814
  */
798
815
  action?: 'login' | 'link';
799
- /**
800
- * Optional delivery preference for redirect-first flows.
801
- *
802
- * Useful for hybrid deployments where provider callbacks do not contain a reliable `Origin`.
803
- */
804
- delivery?: 'cookies' | 'json';
805
816
  }
806
817
  /**
807
818
  * Linked social accounts response.
@@ -1405,6 +1416,20 @@ declare class AuthService {
1405
1416
  * Refresh tokens.
1406
1417
  */
1407
1418
  refresh(): Observable<TokenResponse>;
1419
+ /**
1420
+ * Refresh tokens (promise-based).
1421
+ *
1422
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1423
+ * Useful for async/await patterns in guards and interceptors.
1424
+ *
1425
+ * @returns Promise of TokenResponse
1426
+ *
1427
+ * @example
1428
+ * ```typescript
1429
+ * const tokens = await auth.refreshTokensPromise();
1430
+ * ```
1431
+ */
1432
+ refreshTokensPromise(): Promise<TokenResponse>;
1408
1433
  /**
1409
1434
  * Request a password reset code (forgot password).
1410
1435
  */
@@ -1448,6 +1473,20 @@ declare class AuthService {
1448
1473
  * ```
1449
1474
  */
1450
1475
  getProfile(): Observable<AuthUser>;
1476
+ /**
1477
+ * Get current user profile (promise-based).
1478
+ *
1479
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1480
+ * Useful for async/await patterns in guards and interceptors.
1481
+ *
1482
+ * @returns Promise of current user profile
1483
+ *
1484
+ * @example
1485
+ * ```typescript
1486
+ * const user = await auth.getProfilePromise();
1487
+ * ```
1488
+ */
1489
+ getProfilePromise(): Promise<AuthUser>;
1451
1490
  /**
1452
1491
  * Update user profile.
1453
1492
  *
@@ -1513,6 +1552,21 @@ declare class AuthService {
1513
1552
  * @returns Observable of AuthResponse
1514
1553
  */
1515
1554
  exchangeSocialRedirect(exchangeToken: string): Observable<AuthResponse>;
1555
+ /**
1556
+ * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse (promise-based).
1557
+ *
1558
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1559
+ * Useful for async/await patterns in guards and interceptors.
1560
+ *
1561
+ * @param exchangeToken - One-time exchange token from the callback URL
1562
+ * @returns Promise of AuthResponse
1563
+ *
1564
+ * @example
1565
+ * ```typescript
1566
+ * const response = await auth.exchangeSocialRedirectPromise(exchangeToken);
1567
+ * ```
1568
+ */
1569
+ exchangeSocialRedirectPromise(exchangeToken: string): Promise<AuthResponse>;
1516
1570
  /**
1517
1571
  * Verify native social token (mobile).
1518
1572
  *
@@ -1757,7 +1811,7 @@ declare class AuthGuard {
1757
1811
  *
1758
1812
  * Behavior:
1759
1813
  * - If `exchangeToken` exists: exchanges it via backend and redirects to success or challenge routes.
1760
- * - If no `exchangeToken`: allow the route to activate so the app can display `appState`.
1814
+ * - If no `exchangeToken`: treat as cookie-success path and redirect to success route.
1761
1815
  * - If `error` exists: redirects to oauthError route.
1762
1816
  *
1763
1817
  * @example
@@ -21,6 +21,13 @@ interface AuthUser {
21
21
  mfaEnabled?: boolean;
22
22
  socialProviders?: string[] | null;
23
23
  hasPasswordHash: boolean;
24
+ /**
25
+ * Authentication method used to create the current session.
26
+ *
27
+ * This is session-scoped (how the user logged in this time), not an account capability.
28
+ * Use `hasPasswordHash` and `socialProviders` to determine what login methods the account supports.
29
+ */
30
+ sessionAuthMethod?: string | null;
24
31
  createdAt?: string | Date;
25
32
  updatedAt?: string | Date;
26
33
  }
@@ -456,6 +463,16 @@ interface AuthResponse {
456
463
  refreshToken?: string;
457
464
  accessTokenExpiresAt?: number;
458
465
  refreshTokenExpiresAt?: number;
466
+ /**
467
+ * Authentication method used to create the current session.
468
+ *
469
+ * Examples:
470
+ * - `password`
471
+ * - `google`
472
+ * - `apple`
473
+ * - `facebook`
474
+ */
475
+ authMethod?: string;
459
476
  trusted?: boolean;
460
477
  deviceToken?: string;
461
478
  challengeName?: AuthChallenge;
@@ -796,12 +813,6 @@ interface SocialLoginOptions {
796
813
  * Default: 'login'
797
814
  */
798
815
  action?: 'login' | 'link';
799
- /**
800
- * Optional delivery preference for redirect-first flows.
801
- *
802
- * Useful for hybrid deployments where provider callbacks do not contain a reliable `Origin`.
803
- */
804
- delivery?: 'cookies' | 'json';
805
816
  }
806
817
  /**
807
818
  * Linked social accounts response.
@@ -1405,6 +1416,20 @@ declare class AuthService {
1405
1416
  * Refresh tokens.
1406
1417
  */
1407
1418
  refresh(): Observable<TokenResponse>;
1419
+ /**
1420
+ * Refresh tokens (promise-based).
1421
+ *
1422
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1423
+ * Useful for async/await patterns in guards and interceptors.
1424
+ *
1425
+ * @returns Promise of TokenResponse
1426
+ *
1427
+ * @example
1428
+ * ```typescript
1429
+ * const tokens = await auth.refreshTokensPromise();
1430
+ * ```
1431
+ */
1432
+ refreshTokensPromise(): Promise<TokenResponse>;
1408
1433
  /**
1409
1434
  * Request a password reset code (forgot password).
1410
1435
  */
@@ -1448,6 +1473,20 @@ declare class AuthService {
1448
1473
  * ```
1449
1474
  */
1450
1475
  getProfile(): Observable<AuthUser>;
1476
+ /**
1477
+ * Get current user profile (promise-based).
1478
+ *
1479
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1480
+ * Useful for async/await patterns in guards and interceptors.
1481
+ *
1482
+ * @returns Promise of current user profile
1483
+ *
1484
+ * @example
1485
+ * ```typescript
1486
+ * const user = await auth.getProfilePromise();
1487
+ * ```
1488
+ */
1489
+ getProfilePromise(): Promise<AuthUser>;
1451
1490
  /**
1452
1491
  * Update user profile.
1453
1492
  *
@@ -1513,6 +1552,21 @@ declare class AuthService {
1513
1552
  * @returns Observable of AuthResponse
1514
1553
  */
1515
1554
  exchangeSocialRedirect(exchangeToken: string): Observable<AuthResponse>;
1555
+ /**
1556
+ * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse (promise-based).
1557
+ *
1558
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1559
+ * Useful for async/await patterns in guards and interceptors.
1560
+ *
1561
+ * @param exchangeToken - One-time exchange token from the callback URL
1562
+ * @returns Promise of AuthResponse
1563
+ *
1564
+ * @example
1565
+ * ```typescript
1566
+ * const response = await auth.exchangeSocialRedirectPromise(exchangeToken);
1567
+ * ```
1568
+ */
1569
+ exchangeSocialRedirectPromise(exchangeToken: string): Promise<AuthResponse>;
1516
1570
  /**
1517
1571
  * Verify native social token (mobile).
1518
1572
  *
@@ -1757,7 +1811,7 @@ declare class AuthGuard {
1757
1811
  *
1758
1812
  * Behavior:
1759
1813
  * - If `exchangeToken` exists: exchanges it via backend and redirects to success or challenge routes.
1760
- * - If no `exchangeToken`: allow the route to activate so the app can display `appState`.
1814
+ * - If no `exchangeToken`: treat as cookie-success path and redirect to success route.
1761
1815
  * - If `error` exists: redirects to oauthError route.
1762
1816
  *
1763
1817
  * @example
@@ -814,7 +814,9 @@ var _NAuthClient = class _NAuthClient {
814
814
  */
815
815
  async confirmForgotPassword(identifier, code, newPassword) {
816
816
  const payload = { identifier, code, newPassword };
817
- return this.post(this.config.endpoints.confirmForgotPassword, payload);
817
+ const result = await this.post(this.config.endpoints.confirmForgotPassword, payload);
818
+ await this.clearAuthState(false);
819
+ return result;
818
820
  }
819
821
  /**
820
822
  * Request password change (must change on next login).
@@ -950,11 +952,9 @@ var _NAuthClient = class _NAuthClient {
950
952
  const base = this.config.baseUrl.replace(/\/$/, "");
951
953
  const startUrl = new URL(`${base}${startPath}`);
952
954
  const returnTo = options?.returnTo ?? this.config.redirects?.success ?? "/";
953
- const action = options?.action ?? "login";
954
955
  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);
956
+ if (options?.action === "link") {
957
+ startUrl.searchParams.set("action", "link");
958
958
  }
959
959
  if (typeof options?.appState === "string" && options.appState.trim() !== "") {
960
960
  startUrl.searchParams.set("appState", options.appState);
@@ -1165,7 +1165,9 @@ var _NAuthClient = class _NAuthClient {
1165
1165
  await this.setDeviceToken(response.deviceToken);
1166
1166
  }
1167
1167
  if (response.user) {
1168
- await this.setUser(response.user);
1168
+ const user = response.user;
1169
+ user.sessionAuthMethod = response.authMethod ?? null;
1170
+ await this.setUser(user);
1169
1171
  }
1170
1172
  await this.clearChallenge();
1171
1173
  }
@@ -1237,6 +1239,15 @@ var _NAuthClient = class _NAuthClient {
1237
1239
  headers["Authorization"] = `Bearer ${accessToken}`;
1238
1240
  }
1239
1241
  }
1242
+ if (this.config.tokenDelivery === "json") {
1243
+ try {
1244
+ const deviceToken = await this.config.storage.getItem(this.config.deviceTrust.storageKey);
1245
+ if (deviceToken) {
1246
+ headers[this.config.deviceTrust.headerName] = deviceToken;
1247
+ }
1248
+ } catch {
1249
+ }
1250
+ }
1240
1251
  if (this.config.tokenDelivery === "cookies" && hasWindow()) {
1241
1252
  const csrfToken = this.getCsrfToken();
1242
1253
  if (csrfToken) {
@@ -1485,6 +1496,22 @@ var AuthService = class {
1485
1496
  refresh() {
1486
1497
  return from(this.client.refreshTokens());
1487
1498
  }
1499
+ /**
1500
+ * Refresh tokens (promise-based).
1501
+ *
1502
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1503
+ * Useful for async/await patterns in guards and interceptors.
1504
+ *
1505
+ * @returns Promise of TokenResponse
1506
+ *
1507
+ * @example
1508
+ * ```typescript
1509
+ * const tokens = await auth.refreshTokensPromise();
1510
+ * ```
1511
+ */
1512
+ refreshTokensPromise() {
1513
+ return this.client.refreshTokens();
1514
+ }
1488
1515
  // ============================================================================
1489
1516
  // Account Recovery (Forgot Password)
1490
1517
  // ============================================================================
@@ -1549,6 +1576,25 @@ var AuthService = class {
1549
1576
  })
1550
1577
  );
1551
1578
  }
1579
+ /**
1580
+ * Get current user profile (promise-based).
1581
+ *
1582
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1583
+ * Useful for async/await patterns in guards and interceptors.
1584
+ *
1585
+ * @returns Promise of current user profile
1586
+ *
1587
+ * @example
1588
+ * ```typescript
1589
+ * const user = await auth.getProfilePromise();
1590
+ * ```
1591
+ */
1592
+ getProfilePromise() {
1593
+ return this.client.getProfile().then((user) => {
1594
+ this.currentUserSubject.next(user);
1595
+ return user;
1596
+ });
1597
+ }
1552
1598
  /**
1553
1599
  * Update user profile.
1554
1600
  *
@@ -1643,6 +1689,23 @@ var AuthService = class {
1643
1689
  exchangeSocialRedirect(exchangeToken) {
1644
1690
  return from(this.client.exchangeSocialRedirect(exchangeToken).then((res) => this.updateChallengeState(res)));
1645
1691
  }
1692
+ /**
1693
+ * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse (promise-based).
1694
+ *
1695
+ * Returns a promise instead of an Observable, matching the core NAuthClient API.
1696
+ * Useful for async/await patterns in guards and interceptors.
1697
+ *
1698
+ * @param exchangeToken - One-time exchange token from the callback URL
1699
+ * @returns Promise of AuthResponse
1700
+ *
1701
+ * @example
1702
+ * ```typescript
1703
+ * const response = await auth.exchangeSocialRedirectPromise(exchangeToken);
1704
+ * ```
1705
+ */
1706
+ exchangeSocialRedirectPromise(exchangeToken) {
1707
+ return this.client.exchangeSocialRedirect(exchangeToken).then((res) => this.updateChallengeState(res));
1708
+ }
1646
1709
  /**
1647
1710
  * Verify native social token (mobile).
1648
1711
  *
@@ -1922,7 +1985,7 @@ var authInterceptor = /* @__PURE__ */ __name((req, next) => {
1922
1985
  if (config.debug) {
1923
1986
  console.warn("[nauth-interceptor] Starting refresh...");
1924
1987
  }
1925
- const refresh$ = tokenDelivery === "cookies" ? http.post(refreshUrl, {}, { withCredentials: true }) : from2(authService.getClient().refreshTokens());
1988
+ const refresh$ = tokenDelivery === "cookies" ? http.post(refreshUrl, {}, { withCredentials: true }) : from2(authService.refreshTokensPromise());
1926
1989
  return refresh$.pipe(
1927
1990
  switchMap((response) => {
1928
1991
  if (config.debug) {
@@ -2049,9 +2112,18 @@ var socialRedirectCallbackGuard = /* @__PURE__ */ __name(async () => {
2049
2112
  return false;
2050
2113
  }
2051
2114
  if (!exchangeToken) {
2052
- return true;
2115
+ try {
2116
+ await auth.getProfilePromise();
2117
+ } catch {
2118
+ const errorUrl = config.redirects?.oauthError || "/login";
2119
+ window.location.replace(errorUrl);
2120
+ return false;
2121
+ }
2122
+ const successUrl2 = config.redirects?.success || "/";
2123
+ window.location.replace(successUrl2);
2124
+ return false;
2053
2125
  }
2054
- const response = await auth.getClient().exchangeSocialRedirect(exchangeToken);
2126
+ const response = await auth.exchangeSocialRedirectPromise(exchangeToken);
2055
2127
  if (response.challengeName) {
2056
2128
  const challengeBase = config.redirects?.challengeBase || "/auth/challenge";
2057
2129
  const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, "-");