@nauth-toolkit/client 0.1.18 → 0.1.22
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/angular/index.cjs +381 -166
- package/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.d.mts +331 -127
- package/dist/angular/index.d.ts +331 -127
- package/dist/angular/index.mjs +380 -165
- package/dist/angular/index.mjs.map +1 -1
- package/dist/index.cjs +60 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +65 -72
- package/dist/index.d.ts +65 -72
- package/dist/index.mjs +60 -110
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/angular/index.cjs
CHANGED
|
@@ -40,7 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
NAuthModule: () => NAuthModule,
|
|
41
41
|
authGuard: () => authGuard,
|
|
42
42
|
authInterceptor: () => authInterceptor,
|
|
43
|
-
|
|
43
|
+
socialRedirectCallbackGuard: () => socialRedirectCallbackGuard
|
|
44
44
|
});
|
|
45
45
|
module.exports = __toCommonJS(index_exports);
|
|
46
46
|
|
|
@@ -224,12 +224,12 @@ var defaultEndpoints = {
|
|
|
224
224
|
mfaPreferred: "/mfa/preferred-method",
|
|
225
225
|
mfaBackupCodes: "/mfa/backup-codes/generate",
|
|
226
226
|
mfaExemption: "/mfa/exemption",
|
|
227
|
-
socialAuthUrl: "/social/auth-url",
|
|
228
|
-
socialCallback: "/social/callback",
|
|
229
227
|
socialLinked: "/social/linked",
|
|
230
228
|
socialLink: "/social/link",
|
|
231
229
|
socialUnlink: "/social/unlink",
|
|
232
230
|
socialVerify: "/social/:provider/verify",
|
|
231
|
+
socialRedirectStart: "/social/:provider/redirect",
|
|
232
|
+
socialExchange: "/social/exchange",
|
|
233
233
|
trustDevice: "/trust-device",
|
|
234
234
|
isTrustedDevice: "/is-trusted-device",
|
|
235
235
|
auditHistory: "/audit/history",
|
|
@@ -381,6 +381,9 @@ var _BrowserStorage = class _BrowserStorage {
|
|
|
381
381
|
async removeItem(key) {
|
|
382
382
|
this.storage.removeItem(key);
|
|
383
383
|
}
|
|
384
|
+
async clear() {
|
|
385
|
+
this.storage.clear();
|
|
386
|
+
}
|
|
384
387
|
};
|
|
385
388
|
__name(_BrowserStorage, "BrowserStorage");
|
|
386
389
|
var BrowserStorage = _BrowserStorage;
|
|
@@ -399,6 +402,9 @@ var _InMemoryStorage = class _InMemoryStorage {
|
|
|
399
402
|
async removeItem(key) {
|
|
400
403
|
this.store.delete(key);
|
|
401
404
|
}
|
|
405
|
+
async clear() {
|
|
406
|
+
this.store.clear();
|
|
407
|
+
}
|
|
402
408
|
};
|
|
403
409
|
__name(_InMemoryStorage, "InMemoryStorage");
|
|
404
410
|
var InMemoryStorage = _InMemoryStorage;
|
|
@@ -523,9 +529,9 @@ var _FetchAdapter = class _FetchAdapter {
|
|
|
523
529
|
});
|
|
524
530
|
if (!response.ok) {
|
|
525
531
|
const errorData = typeof data === "object" && data !== null ? data : {};
|
|
526
|
-
const code = typeof errorData["code"] === "string" ? errorData
|
|
527
|
-
const message = typeof errorData["message"] === "string" ? errorData
|
|
528
|
-
const timestamp = typeof errorData["timestamp"] === "string" ? errorData
|
|
532
|
+
const code = typeof errorData["code"] === "string" ? errorData["code"] : "INTERNAL_ERROR" /* INTERNAL_ERROR */;
|
|
533
|
+
const message = typeof errorData["message"] === "string" ? errorData["message"] : `Request failed with status ${status}`;
|
|
534
|
+
const timestamp = typeof errorData["timestamp"] === "string" ? errorData["timestamp"] : void 0;
|
|
529
535
|
const details = errorData["details"];
|
|
530
536
|
throw new NAuthClientError(code, message, {
|
|
531
537
|
statusCode: status,
|
|
@@ -839,7 +845,9 @@ var _NAuthClient = class _NAuthClient {
|
|
|
839
845
|
*/
|
|
840
846
|
async confirmForgotPassword(identifier, code, newPassword) {
|
|
841
847
|
const payload = { identifier, code, newPassword };
|
|
842
|
-
|
|
848
|
+
const result = await this.post(this.config.endpoints.confirmForgotPassword, payload);
|
|
849
|
+
await this.clearAuthState(false);
|
|
850
|
+
return result;
|
|
843
851
|
}
|
|
844
852
|
/**
|
|
845
853
|
* Request password change (must change on next login).
|
|
@@ -949,126 +957,57 @@ var _NAuthClient = class _NAuthClient {
|
|
|
949
957
|
// Social Authentication
|
|
950
958
|
// ============================================================================
|
|
951
959
|
/**
|
|
952
|
-
* Start social OAuth flow
|
|
960
|
+
* Start redirect-first social OAuth flow (web).
|
|
961
|
+
*
|
|
962
|
+
* This performs a browser navigation to:
|
|
963
|
+
* `GET {baseUrl}/social/:provider/redirect?returnTo=...&appState=...`
|
|
953
964
|
*
|
|
954
|
-
*
|
|
955
|
-
*
|
|
965
|
+
* The backend:
|
|
966
|
+
* - generates and stores CSRF state (cluster-safe)
|
|
967
|
+
* - redirects the user to the provider
|
|
968
|
+
* - completes OAuth on callback and sets cookies (or issues an exchange token)
|
|
969
|
+
* - redirects back to `returnTo` with `appState` (and `exchangeToken` for json/hybrid)
|
|
956
970
|
*
|
|
957
971
|
* @param provider - OAuth provider ('google', 'apple', 'facebook')
|
|
958
|
-
* @param options - Optional
|
|
972
|
+
* @param options - Optional redirect options
|
|
959
973
|
*
|
|
960
974
|
* @example
|
|
961
975
|
* ```typescript
|
|
962
|
-
*
|
|
963
|
-
* await client.loginWithSocial('google');
|
|
964
|
-
*
|
|
965
|
-
* // With custom redirect URI
|
|
966
|
-
* await client.loginWithSocial('apple', {
|
|
967
|
-
* redirectUri: 'https://example.com/auth/callback'
|
|
968
|
-
* });
|
|
976
|
+
* await client.loginWithSocial('google', { returnTo: '/auth/callback', appState: '12345' });
|
|
969
977
|
* ```
|
|
970
978
|
*/
|
|
971
|
-
async loginWithSocial(provider,
|
|
979
|
+
async loginWithSocial(provider, options) {
|
|
972
980
|
this.eventEmitter.emit({ type: "oauth:started", data: { provider }, timestamp: Date.now() });
|
|
973
|
-
const { url } = await this.getSocialAuthUrl({ provider });
|
|
974
981
|
if (hasWindow()) {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
* Returns null if not an OAuth callback (no provider/code params).
|
|
983
|
-
*
|
|
984
|
-
* The SDK validates the state token, completes authentication via backend,
|
|
985
|
-
* and emits appropriate events.
|
|
986
|
-
*
|
|
987
|
-
* @param urlOrParams - Optional URL string or URLSearchParams (auto-detects from window.location if not provided)
|
|
988
|
-
* @returns AuthResponse if OAuth callback detected, null otherwise
|
|
989
|
-
*
|
|
990
|
-
* @example
|
|
991
|
-
* ```typescript
|
|
992
|
-
* // Auto-detect on app init
|
|
993
|
-
* const response = await client.handleOAuthCallback();
|
|
994
|
-
* if (response) {
|
|
995
|
-
* if (response.challengeName) {
|
|
996
|
-
* router.navigate(['/challenge', response.challengeName]);
|
|
997
|
-
* } else {
|
|
998
|
-
* router.navigate(['/']); // Navigate to your app's home route
|
|
999
|
-
* }
|
|
1000
|
-
* }
|
|
1001
|
-
*
|
|
1002
|
-
* // In callback route
|
|
1003
|
-
* const response = await client.handleOAuthCallback(window.location.search);
|
|
1004
|
-
* ```
|
|
1005
|
-
*/
|
|
1006
|
-
async handleOAuthCallback(urlOrParams) {
|
|
1007
|
-
let params;
|
|
1008
|
-
if (urlOrParams instanceof URLSearchParams) {
|
|
1009
|
-
params = urlOrParams;
|
|
1010
|
-
} else if (typeof urlOrParams === "string") {
|
|
1011
|
-
params = new URLSearchParams(urlOrParams);
|
|
1012
|
-
} else if (hasWindow()) {
|
|
1013
|
-
params = new URLSearchParams(window.location.search);
|
|
1014
|
-
} else {
|
|
1015
|
-
return null;
|
|
1016
|
-
}
|
|
1017
|
-
const provider = params.get("provider");
|
|
1018
|
-
const code = params.get("code");
|
|
1019
|
-
const state = params.get("state");
|
|
1020
|
-
const error = params.get("error");
|
|
1021
|
-
if (!provider || !code && !error) {
|
|
1022
|
-
return null;
|
|
1023
|
-
}
|
|
1024
|
-
this.eventEmitter.emit({ type: "oauth:callback", data: { provider }, timestamp: Date.now() });
|
|
1025
|
-
try {
|
|
1026
|
-
if (error) {
|
|
1027
|
-
const authError = new NAuthClientError(
|
|
1028
|
-
"SOCIAL_TOKEN_INVALID" /* SOCIAL_TOKEN_INVALID */,
|
|
1029
|
-
params.get("error_description") || error,
|
|
1030
|
-
{ details: { error, provider } }
|
|
1031
|
-
);
|
|
1032
|
-
this.eventEmitter.emit({ type: "oauth:error", data: authError, timestamp: Date.now() });
|
|
1033
|
-
throw authError;
|
|
982
|
+
const startPath = this.config.endpoints.socialRedirectStart.replace(":provider", provider);
|
|
983
|
+
const base = this.config.baseUrl.replace(/\/$/, "");
|
|
984
|
+
const startUrl = new URL(`${base}${startPath}`);
|
|
985
|
+
const returnTo = options?.returnTo ?? this.config.redirects?.success ?? "/";
|
|
986
|
+
startUrl.searchParams.set("returnTo", returnTo);
|
|
987
|
+
if (options?.action === "link") {
|
|
988
|
+
startUrl.searchParams.set("action", "link");
|
|
1034
989
|
}
|
|
1035
|
-
if (
|
|
1036
|
-
|
|
990
|
+
if (typeof options?.appState === "string" && options.appState.trim() !== "") {
|
|
991
|
+
startUrl.searchParams.set("appState", options.appState);
|
|
1037
992
|
}
|
|
1038
|
-
|
|
1039
|
-
provider,
|
|
1040
|
-
code,
|
|
1041
|
-
state
|
|
1042
|
-
});
|
|
1043
|
-
if (response.challengeName) {
|
|
1044
|
-
this.eventEmitter.emit({ type: "auth:challenge", data: response, timestamp: Date.now() });
|
|
1045
|
-
} else {
|
|
1046
|
-
this.eventEmitter.emit({ type: "auth:success", data: response, timestamp: Date.now() });
|
|
1047
|
-
}
|
|
1048
|
-
this.eventEmitter.emit({ type: "oauth:completed", data: response, timestamp: Date.now() });
|
|
1049
|
-
return response;
|
|
1050
|
-
} catch (error2) {
|
|
1051
|
-
const authError = error2 instanceof NAuthClientError ? error2 : new NAuthClientError(
|
|
1052
|
-
"SOCIAL_TOKEN_INVALID" /* SOCIAL_TOKEN_INVALID */,
|
|
1053
|
-
error2.message || "OAuth callback failed"
|
|
1054
|
-
);
|
|
1055
|
-
this.eventEmitter.emit({ type: "oauth:error", data: authError, timestamp: Date.now() });
|
|
1056
|
-
throw authError;
|
|
993
|
+
window.location.href = startUrl.toString();
|
|
1057
994
|
}
|
|
1058
995
|
}
|
|
1059
996
|
/**
|
|
1060
|
-
*
|
|
997
|
+
* Exchange an `exchangeToken` (from redirect callback URL) into an AuthResponse.
|
|
1061
998
|
*
|
|
1062
|
-
*
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
/**
|
|
1068
|
-
* Handle social callback.
|
|
999
|
+
* Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back
|
|
1000
|
+
* with `exchangeToken` instead of setting cookies.
|
|
1001
|
+
*
|
|
1002
|
+
* @param exchangeToken - One-time exchange token from the callback URL
|
|
1003
|
+
* @returns AuthResponse
|
|
1069
1004
|
*/
|
|
1070
|
-
async
|
|
1071
|
-
const
|
|
1005
|
+
async exchangeSocialRedirect(exchangeToken) {
|
|
1006
|
+
const token = exchangeToken?.trim();
|
|
1007
|
+
if (!token) {
|
|
1008
|
+
throw new NAuthClientError("CHALLENGE_INVALID" /* CHALLENGE_INVALID */, "Missing exchangeToken");
|
|
1009
|
+
}
|
|
1010
|
+
const result = await this.post(this.config.endpoints.socialExchange, { exchangeToken: token });
|
|
1072
1011
|
await this.handleAuthResponse(result);
|
|
1073
1012
|
return result;
|
|
1074
1013
|
}
|
|
@@ -1257,7 +1196,9 @@ var _NAuthClient = class _NAuthClient {
|
|
|
1257
1196
|
await this.setDeviceToken(response.deviceToken);
|
|
1258
1197
|
}
|
|
1259
1198
|
if (response.user) {
|
|
1260
|
-
|
|
1199
|
+
const user = response.user;
|
|
1200
|
+
user.sessionAuthMethod = response.authMethod ?? null;
|
|
1201
|
+
await this.setUser(user);
|
|
1261
1202
|
}
|
|
1262
1203
|
await this.clearChallenge();
|
|
1263
1204
|
}
|
|
@@ -1329,6 +1270,15 @@ var _NAuthClient = class _NAuthClient {
|
|
|
1329
1270
|
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
1330
1271
|
}
|
|
1331
1272
|
}
|
|
1273
|
+
if (this.config.tokenDelivery === "json") {
|
|
1274
|
+
try {
|
|
1275
|
+
const deviceToken = await this.config.storage.getItem(this.config.deviceTrust.storageKey);
|
|
1276
|
+
if (deviceToken) {
|
|
1277
|
+
headers[this.config.deviceTrust.headerName] = deviceToken;
|
|
1278
|
+
}
|
|
1279
|
+
} catch {
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1332
1282
|
if (this.config.tokenDelivery === "cookies" && hasWindow()) {
|
|
1333
1283
|
const csrfToken = this.getCsrfToken();
|
|
1334
1284
|
if (csrfToken) {
|
|
@@ -1577,6 +1527,22 @@ var AuthService = class {
|
|
|
1577
1527
|
refresh() {
|
|
1578
1528
|
return (0, import_rxjs2.from)(this.client.refreshTokens());
|
|
1579
1529
|
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Refresh tokens (promise-based).
|
|
1532
|
+
*
|
|
1533
|
+
* Returns a promise instead of an Observable, matching the core NAuthClient API.
|
|
1534
|
+
* Useful for async/await patterns in guards and interceptors.
|
|
1535
|
+
*
|
|
1536
|
+
* @returns Promise of TokenResponse
|
|
1537
|
+
*
|
|
1538
|
+
* @example
|
|
1539
|
+
* ```typescript
|
|
1540
|
+
* const tokens = await auth.refreshTokensPromise();
|
|
1541
|
+
* ```
|
|
1542
|
+
*/
|
|
1543
|
+
refreshTokensPromise() {
|
|
1544
|
+
return this.client.refreshTokens();
|
|
1545
|
+
}
|
|
1580
1546
|
// ============================================================================
|
|
1581
1547
|
// Account Recovery (Forgot Password)
|
|
1582
1548
|
// ============================================================================
|
|
@@ -1592,6 +1558,95 @@ var AuthService = class {
|
|
|
1592
1558
|
confirmForgotPassword(identifier, code, newPassword) {
|
|
1593
1559
|
return (0, import_rxjs2.from)(this.client.confirmForgotPassword(identifier, code, newPassword));
|
|
1594
1560
|
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Change user password (requires current password).
|
|
1563
|
+
*
|
|
1564
|
+
* @param oldPassword - Current password
|
|
1565
|
+
* @param newPassword - New password (must meet requirements)
|
|
1566
|
+
* @returns Observable that completes when password is changed
|
|
1567
|
+
*
|
|
1568
|
+
* @example
|
|
1569
|
+
* ```typescript
|
|
1570
|
+
* this.auth.changePassword('oldPassword123', 'newSecurePassword456!').subscribe({
|
|
1571
|
+
* next: () => console.log('Password changed successfully'),
|
|
1572
|
+
* error: (err) => console.error('Failed to change password:', err)
|
|
1573
|
+
* });
|
|
1574
|
+
* ```
|
|
1575
|
+
*/
|
|
1576
|
+
changePassword(oldPassword, newPassword) {
|
|
1577
|
+
return (0, import_rxjs2.from)(this.client.changePassword(oldPassword, newPassword));
|
|
1578
|
+
}
|
|
1579
|
+
/**
|
|
1580
|
+
* Request password change (must change on next login).
|
|
1581
|
+
*
|
|
1582
|
+
* @returns Observable that completes when request is sent
|
|
1583
|
+
*/
|
|
1584
|
+
requestPasswordChange() {
|
|
1585
|
+
return (0, import_rxjs2.from)(this.client.requestPasswordChange());
|
|
1586
|
+
}
|
|
1587
|
+
// ============================================================================
|
|
1588
|
+
// Profile Management
|
|
1589
|
+
// ============================================================================
|
|
1590
|
+
/**
|
|
1591
|
+
* Get current user profile.
|
|
1592
|
+
*
|
|
1593
|
+
* @returns Observable of current user profile
|
|
1594
|
+
*
|
|
1595
|
+
* @example
|
|
1596
|
+
* ```typescript
|
|
1597
|
+
* this.auth.getProfile().subscribe(user => {
|
|
1598
|
+
* console.log('User profile:', user);
|
|
1599
|
+
* });
|
|
1600
|
+
* ```
|
|
1601
|
+
*/
|
|
1602
|
+
getProfile() {
|
|
1603
|
+
return (0, import_rxjs2.from)(
|
|
1604
|
+
this.client.getProfile().then((user) => {
|
|
1605
|
+
this.currentUserSubject.next(user);
|
|
1606
|
+
return user;
|
|
1607
|
+
})
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Get current user profile (promise-based).
|
|
1612
|
+
*
|
|
1613
|
+
* Returns a promise instead of an Observable, matching the core NAuthClient API.
|
|
1614
|
+
* Useful for async/await patterns in guards and interceptors.
|
|
1615
|
+
*
|
|
1616
|
+
* @returns Promise of current user profile
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```typescript
|
|
1620
|
+
* const user = await auth.getProfilePromise();
|
|
1621
|
+
* ```
|
|
1622
|
+
*/
|
|
1623
|
+
getProfilePromise() {
|
|
1624
|
+
return this.client.getProfile().then((user) => {
|
|
1625
|
+
this.currentUserSubject.next(user);
|
|
1626
|
+
return user;
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Update user profile.
|
|
1631
|
+
*
|
|
1632
|
+
* @param updates - Profile fields to update
|
|
1633
|
+
* @returns Observable of updated user profile
|
|
1634
|
+
*
|
|
1635
|
+
* @example
|
|
1636
|
+
* ```typescript
|
|
1637
|
+
* this.auth.updateProfile({ firstName: 'John', lastName: 'Doe' }).subscribe(user => {
|
|
1638
|
+
* console.log('Profile updated:', user);
|
|
1639
|
+
* });
|
|
1640
|
+
* ```
|
|
1641
|
+
*/
|
|
1642
|
+
updateProfile(updates) {
|
|
1643
|
+
return (0, import_rxjs2.from)(
|
|
1644
|
+
this.client.updateProfile(updates).then((user) => {
|
|
1645
|
+
this.currentUserSubject.next(user);
|
|
1646
|
+
return user;
|
|
1647
|
+
})
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1595
1650
|
// ============================================================================
|
|
1596
1651
|
// Challenge Flow Methods (Essential for any auth flow)
|
|
1597
1652
|
// ============================================================================
|
|
@@ -1648,26 +1703,189 @@ var AuthService = class {
|
|
|
1648
1703
|
// ============================================================================
|
|
1649
1704
|
/**
|
|
1650
1705
|
* Initiate social OAuth login flow.
|
|
1651
|
-
* Redirects to
|
|
1706
|
+
* Redirects the browser to backend `/auth/social/:provider/redirect`.
|
|
1652
1707
|
*/
|
|
1653
1708
|
loginWithSocial(provider, options) {
|
|
1654
1709
|
return this.client.loginWithSocial(provider, options);
|
|
1655
1710
|
}
|
|
1656
1711
|
/**
|
|
1657
|
-
*
|
|
1712
|
+
* Exchange an exchangeToken (from redirect callback URL) into an AuthResponse.
|
|
1713
|
+
*
|
|
1714
|
+
* Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back
|
|
1715
|
+
* with `exchangeToken` instead of setting cookies.
|
|
1716
|
+
*
|
|
1717
|
+
* @param exchangeToken - One-time exchange token from the callback URL
|
|
1718
|
+
* @returns Observable of AuthResponse
|
|
1658
1719
|
*/
|
|
1659
|
-
|
|
1660
|
-
return (0, import_rxjs2.from)(
|
|
1661
|
-
this.client.getSocialAuthUrl({ provider, redirectUri })
|
|
1662
|
-
);
|
|
1720
|
+
exchangeSocialRedirect(exchangeToken) {
|
|
1721
|
+
return (0, import_rxjs2.from)(this.client.exchangeSocialRedirect(exchangeToken).then((res) => this.updateChallengeState(res)));
|
|
1663
1722
|
}
|
|
1664
1723
|
/**
|
|
1665
|
-
*
|
|
1724
|
+
* Exchange an exchangeToken (from redirect callback URL) into an AuthResponse (promise-based).
|
|
1725
|
+
*
|
|
1726
|
+
* Returns a promise instead of an Observable, matching the core NAuthClient API.
|
|
1727
|
+
* Useful for async/await patterns in guards and interceptors.
|
|
1728
|
+
*
|
|
1729
|
+
* @param exchangeToken - One-time exchange token from the callback URL
|
|
1730
|
+
* @returns Promise of AuthResponse
|
|
1731
|
+
*
|
|
1732
|
+
* @example
|
|
1733
|
+
* ```typescript
|
|
1734
|
+
* const response = await auth.exchangeSocialRedirectPromise(exchangeToken);
|
|
1735
|
+
* ```
|
|
1666
1736
|
*/
|
|
1667
|
-
|
|
1668
|
-
return (
|
|
1669
|
-
|
|
1670
|
-
|
|
1737
|
+
exchangeSocialRedirectPromise(exchangeToken) {
|
|
1738
|
+
return this.client.exchangeSocialRedirect(exchangeToken).then((res) => this.updateChallengeState(res));
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Verify native social token (mobile).
|
|
1742
|
+
*
|
|
1743
|
+
* @param request - Social verification request with provider and token
|
|
1744
|
+
* @returns Observable of AuthResponse
|
|
1745
|
+
*/
|
|
1746
|
+
verifyNativeSocial(request) {
|
|
1747
|
+
return (0, import_rxjs2.from)(this.client.verifyNativeSocial(request).then((res) => this.updateChallengeState(res)));
|
|
1748
|
+
}
|
|
1749
|
+
/**
|
|
1750
|
+
* Get linked social accounts.
|
|
1751
|
+
*
|
|
1752
|
+
* @returns Observable of linked accounts response
|
|
1753
|
+
*/
|
|
1754
|
+
getLinkedAccounts() {
|
|
1755
|
+
return (0, import_rxjs2.from)(this.client.getLinkedAccounts());
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Link social account.
|
|
1759
|
+
*
|
|
1760
|
+
* @param provider - Social provider to link
|
|
1761
|
+
* @param code - OAuth authorization code
|
|
1762
|
+
* @param state - OAuth state parameter
|
|
1763
|
+
* @returns Observable with success message
|
|
1764
|
+
*/
|
|
1765
|
+
linkSocialAccount(provider, code, state) {
|
|
1766
|
+
return (0, import_rxjs2.from)(this.client.linkSocialAccount(provider, code, state));
|
|
1767
|
+
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Unlink social account.
|
|
1770
|
+
*
|
|
1771
|
+
* @param provider - Social provider to unlink
|
|
1772
|
+
* @returns Observable with success message
|
|
1773
|
+
*/
|
|
1774
|
+
unlinkSocialAccount(provider) {
|
|
1775
|
+
return (0, import_rxjs2.from)(this.client.unlinkSocialAccount(provider));
|
|
1776
|
+
}
|
|
1777
|
+
// ============================================================================
|
|
1778
|
+
// MFA Management
|
|
1779
|
+
// ============================================================================
|
|
1780
|
+
/**
|
|
1781
|
+
* Get MFA status for the current user.
|
|
1782
|
+
*
|
|
1783
|
+
* @returns Observable of MFA status
|
|
1784
|
+
*/
|
|
1785
|
+
getMfaStatus() {
|
|
1786
|
+
return (0, import_rxjs2.from)(this.client.getMfaStatus());
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Get MFA devices for the current user.
|
|
1790
|
+
*
|
|
1791
|
+
* @returns Observable of MFA devices array
|
|
1792
|
+
*/
|
|
1793
|
+
getMfaDevices() {
|
|
1794
|
+
return (0, import_rxjs2.from)(this.client.getMfaDevices());
|
|
1795
|
+
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Setup MFA device (authenticated user).
|
|
1798
|
+
*
|
|
1799
|
+
* @param method - MFA method to set up
|
|
1800
|
+
* @returns Observable of setup data
|
|
1801
|
+
*/
|
|
1802
|
+
setupMfaDevice(method) {
|
|
1803
|
+
return (0, import_rxjs2.from)(this.client.setupMfaDevice(method));
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Verify MFA setup (authenticated user).
|
|
1807
|
+
*
|
|
1808
|
+
* @param method - MFA method
|
|
1809
|
+
* @param setupData - Setup data from setupMfaDevice
|
|
1810
|
+
* @param deviceName - Optional device name
|
|
1811
|
+
* @returns Observable with device ID
|
|
1812
|
+
*/
|
|
1813
|
+
verifyMfaSetup(method, setupData, deviceName) {
|
|
1814
|
+
return (0, import_rxjs2.from)(this.client.verifyMfaSetup(method, setupData, deviceName));
|
|
1815
|
+
}
|
|
1816
|
+
/**
|
|
1817
|
+
* Remove MFA device.
|
|
1818
|
+
*
|
|
1819
|
+
* @param method - MFA method to remove
|
|
1820
|
+
* @returns Observable with success message
|
|
1821
|
+
*/
|
|
1822
|
+
removeMfaDevice(method) {
|
|
1823
|
+
return (0, import_rxjs2.from)(this.client.removeMfaDevice(method));
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Set preferred MFA method.
|
|
1827
|
+
*
|
|
1828
|
+
* @param method - Device method to set as preferred ('totp', 'sms', 'email', or 'passkey')
|
|
1829
|
+
* @returns Observable with success message
|
|
1830
|
+
*/
|
|
1831
|
+
setPreferredMfaMethod(method) {
|
|
1832
|
+
return (0, import_rxjs2.from)(this.client.setPreferredMfaMethod(method));
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1835
|
+
* Generate backup codes.
|
|
1836
|
+
*
|
|
1837
|
+
* @returns Observable of backup codes array
|
|
1838
|
+
*/
|
|
1839
|
+
generateBackupCodes() {
|
|
1840
|
+
return (0, import_rxjs2.from)(this.client.generateBackupCodes());
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Set MFA exemption (admin/test scenarios).
|
|
1844
|
+
*
|
|
1845
|
+
* @param exempt - Whether to exempt user from MFA
|
|
1846
|
+
* @param reason - Optional reason for exemption
|
|
1847
|
+
* @returns Observable that completes when exemption is set
|
|
1848
|
+
*/
|
|
1849
|
+
setMfaExemption(exempt, reason) {
|
|
1850
|
+
return (0, import_rxjs2.from)(this.client.setMfaExemption(exempt, reason));
|
|
1851
|
+
}
|
|
1852
|
+
// ============================================================================
|
|
1853
|
+
// Device Trust
|
|
1854
|
+
// ============================================================================
|
|
1855
|
+
/**
|
|
1856
|
+
* Trust current device.
|
|
1857
|
+
*
|
|
1858
|
+
* @returns Observable with device token
|
|
1859
|
+
*/
|
|
1860
|
+
trustDevice() {
|
|
1861
|
+
return (0, import_rxjs2.from)(this.client.trustDevice());
|
|
1862
|
+
}
|
|
1863
|
+
/**
|
|
1864
|
+
* Check if the current device is trusted.
|
|
1865
|
+
*
|
|
1866
|
+
* @returns Observable with trusted status
|
|
1867
|
+
*/
|
|
1868
|
+
isTrustedDevice() {
|
|
1869
|
+
return (0, import_rxjs2.from)(this.client.isTrustedDevice());
|
|
1870
|
+
}
|
|
1871
|
+
// ============================================================================
|
|
1872
|
+
// Audit History
|
|
1873
|
+
// ============================================================================
|
|
1874
|
+
/**
|
|
1875
|
+
* Get paginated audit history for the current user.
|
|
1876
|
+
*
|
|
1877
|
+
* @param params - Query parameters for filtering and pagination
|
|
1878
|
+
* @returns Observable of audit history response
|
|
1879
|
+
*
|
|
1880
|
+
* @example
|
|
1881
|
+
* ```typescript
|
|
1882
|
+
* this.auth.getAuditHistory({ page: 1, limit: 20, eventType: 'LOGIN_SUCCESS' }).subscribe(history => {
|
|
1883
|
+
* console.log('Audit history:', history);
|
|
1884
|
+
* });
|
|
1885
|
+
* ```
|
|
1886
|
+
*/
|
|
1887
|
+
getAuditHistory(params) {
|
|
1888
|
+
return (0, import_rxjs2.from)(this.client.getAuditHistory(params));
|
|
1671
1889
|
}
|
|
1672
1890
|
// ============================================================================
|
|
1673
1891
|
// Escape Hatch
|
|
@@ -1675,20 +1893,19 @@ var AuthService = class {
|
|
|
1675
1893
|
/**
|
|
1676
1894
|
* Expose underlying NAuthClient for advanced scenarios.
|
|
1677
1895
|
*
|
|
1678
|
-
*
|
|
1679
|
-
*
|
|
1680
|
-
*
|
|
1681
|
-
*
|
|
1682
|
-
*
|
|
1683
|
-
* - Device trust (trustDevice)
|
|
1896
|
+
* @deprecated All core functionality is now exposed directly on AuthService as Observables.
|
|
1897
|
+
* Use the direct methods on AuthService instead (e.g., `auth.changePassword()` instead of `auth.getClient().changePassword()`).
|
|
1898
|
+
* This method is kept for backward compatibility only and may be removed in a future version.
|
|
1899
|
+
*
|
|
1900
|
+
* @returns The underlying NAuthClient instance
|
|
1684
1901
|
*
|
|
1685
1902
|
* @example
|
|
1686
1903
|
* ```typescript
|
|
1687
|
-
* //
|
|
1904
|
+
* // Deprecated - use direct methods instead
|
|
1688
1905
|
* const status = await this.auth.getClient().getMfaStatus();
|
|
1689
1906
|
*
|
|
1690
|
-
* //
|
|
1691
|
-
*
|
|
1907
|
+
* // Preferred - use Observable-based methods
|
|
1908
|
+
* this.auth.getMfaStatus().subscribe(status => ...);
|
|
1692
1909
|
* ```
|
|
1693
1910
|
*/
|
|
1694
1911
|
getClient() {
|
|
@@ -1767,12 +1984,11 @@ var authInterceptor = /* @__PURE__ */ __name((req, next) => {
|
|
|
1767
1984
|
const refreshPath = endpoints.refresh ?? "/refresh";
|
|
1768
1985
|
const loginPath = endpoints.login ?? "/login";
|
|
1769
1986
|
const signupPath = endpoints.signup ?? "/signup";
|
|
1770
|
-
const
|
|
1771
|
-
const socialCallbackPath = endpoints.socialCallback ?? "/social/callback";
|
|
1987
|
+
const socialExchangePath = endpoints.socialExchange ?? "/social/exchange";
|
|
1772
1988
|
const refreshUrl = `${baseUrl}${refreshPath}`;
|
|
1773
1989
|
const isAuthApiRequest = req.url.includes(baseUrl);
|
|
1774
1990
|
const isRefreshEndpoint = req.url.includes(refreshPath);
|
|
1775
|
-
const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(
|
|
1991
|
+
const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
|
|
1776
1992
|
let authReq = req;
|
|
1777
1993
|
if (tokenDelivery === "cookies") {
|
|
1778
1994
|
authReq = authReq.clone({ withCredentials: true });
|
|
@@ -1800,7 +2016,7 @@ var authInterceptor = /* @__PURE__ */ __name((req, next) => {
|
|
|
1800
2016
|
if (config.debug) {
|
|
1801
2017
|
console.warn("[nauth-interceptor] Starting refresh...");
|
|
1802
2018
|
}
|
|
1803
|
-
const refresh$ = tokenDelivery === "cookies" ? http.post(refreshUrl, {}, { withCredentials: true }) : (0, import_rxjs3.from)(authService.
|
|
2019
|
+
const refresh$ = tokenDelivery === "cookies" ? http.post(refreshUrl, {}, { withCredentials: true }) : (0, import_rxjs3.from)(authService.refreshTokensPromise());
|
|
1804
2020
|
return refresh$.pipe(
|
|
1805
2021
|
(0, import_rxjs3.switchMap)((response) => {
|
|
1806
2022
|
if (config.debug) {
|
|
@@ -1907,10 +2123,10 @@ var _AuthGuard = class _AuthGuard {
|
|
|
1907
2123
|
__name(_AuthGuard, "AuthGuard");
|
|
1908
2124
|
var AuthGuard = _AuthGuard;
|
|
1909
2125
|
|
|
1910
|
-
// src/angular/
|
|
2126
|
+
// src/angular/social-redirect-callback.guard.ts
|
|
1911
2127
|
var import_core6 = require("@angular/core");
|
|
1912
2128
|
var import_common2 = require("@angular/common");
|
|
1913
|
-
var
|
|
2129
|
+
var socialRedirectCallbackGuard = /* @__PURE__ */ __name(async () => {
|
|
1914
2130
|
const auth = (0, import_core6.inject)(AuthService);
|
|
1915
2131
|
const config = (0, import_core6.inject)(NAUTH_CLIENT_CONFIG);
|
|
1916
2132
|
const platformId = (0, import_core6.inject)(import_core6.PLATFORM_ID);
|
|
@@ -1918,38 +2134,37 @@ var oauthCallbackGuard = /* @__PURE__ */ __name(async () => {
|
|
|
1918
2134
|
if (!isBrowser) {
|
|
1919
2135
|
return false;
|
|
1920
2136
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
window.location.replace(homeUrl);
|
|
1926
|
-
return false;
|
|
1927
|
-
}
|
|
1928
|
-
if (response.challengeName) {
|
|
1929
|
-
const challengeBase = config.redirects?.challengeBase || "/auth/challenge";
|
|
1930
|
-
const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, "-");
|
|
1931
|
-
const challengePath = `${challengeBase}/${challengeRoute}`;
|
|
1932
|
-
if (config.debug) {
|
|
1933
|
-
console.warn("[oauth-callback-guard] Redirecting to challenge:", challengePath);
|
|
1934
|
-
}
|
|
1935
|
-
window.location.replace(challengePath);
|
|
1936
|
-
} else {
|
|
1937
|
-
const successUrl = config.redirects?.success || "/";
|
|
1938
|
-
if (config.debug) {
|
|
1939
|
-
console.warn("[oauth-callback-guard] Redirecting to success URL:", successUrl);
|
|
1940
|
-
}
|
|
1941
|
-
window.location.replace(successUrl);
|
|
1942
|
-
}
|
|
1943
|
-
} catch (error) {
|
|
1944
|
-
console.error("[oauth-callback-guard] OAuth callback failed:", error);
|
|
2137
|
+
const params = new URLSearchParams(window.location.search);
|
|
2138
|
+
const error = params.get("error");
|
|
2139
|
+
const exchangeToken = params.get("exchangeToken");
|
|
2140
|
+
if (error) {
|
|
1945
2141
|
const errorUrl = config.redirects?.oauthError || "/login";
|
|
1946
|
-
if (config.debug) {
|
|
1947
|
-
console.warn("[oauth-callback-guard] Redirecting to error URL:", errorUrl);
|
|
1948
|
-
}
|
|
1949
2142
|
window.location.replace(errorUrl);
|
|
2143
|
+
return false;
|
|
2144
|
+
}
|
|
2145
|
+
if (!exchangeToken) {
|
|
2146
|
+
try {
|
|
2147
|
+
await auth.getProfilePromise();
|
|
2148
|
+
} catch {
|
|
2149
|
+
const errorUrl = config.redirects?.oauthError || "/login";
|
|
2150
|
+
window.location.replace(errorUrl);
|
|
2151
|
+
return false;
|
|
2152
|
+
}
|
|
2153
|
+
const successUrl2 = config.redirects?.success || "/";
|
|
2154
|
+
window.location.replace(successUrl2);
|
|
2155
|
+
return false;
|
|
2156
|
+
}
|
|
2157
|
+
const response = await auth.exchangeSocialRedirectPromise(exchangeToken);
|
|
2158
|
+
if (response.challengeName) {
|
|
2159
|
+
const challengeBase = config.redirects?.challengeBase || "/auth/challenge";
|
|
2160
|
+
const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, "-");
|
|
2161
|
+
window.location.replace(`${challengeBase}/${challengeRoute}`);
|
|
2162
|
+
return false;
|
|
1950
2163
|
}
|
|
2164
|
+
const successUrl = config.redirects?.success || "/";
|
|
2165
|
+
window.location.replace(successUrl);
|
|
1951
2166
|
return false;
|
|
1952
|
-
}, "
|
|
2167
|
+
}, "socialRedirectCallbackGuard");
|
|
1953
2168
|
|
|
1954
2169
|
// src/angular/auth.module.ts
|
|
1955
2170
|
var import_core7 = require("@angular/core");
|
|
@@ -1984,6 +2199,6 @@ NAuthModule = __decorateClass([
|
|
|
1984
2199
|
NAuthModule,
|
|
1985
2200
|
authGuard,
|
|
1986
2201
|
authInterceptor,
|
|
1987
|
-
|
|
2202
|
+
socialRedirectCallbackGuard
|
|
1988
2203
|
});
|
|
1989
2204
|
//# sourceMappingURL=index.cjs.map
|