@nauth-toolkit/client 0.1.50 → 0.1.53

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.
@@ -1,2402 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
- var __export = (target, all) => {
11
- for (var name in all)
12
- __defProp(target, name, { get: all[name], enumerable: true });
13
- };
14
- var __copyProps = (to, from2, except, desc) => {
15
- if (from2 && typeof from2 === "object" || typeof from2 === "function") {
16
- for (let key of __getOwnPropNames(from2))
17
- if (!__hasOwnProp.call(to, key) && key !== except)
18
- __defProp(to, key, { get: () => from2[key], enumerable: !(desc = __getOwnPropDesc(from2, key)) || desc.enumerable });
19
- }
20
- return to;
21
- };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
- // If the importer is in node compatibility mode or this is not an ESM
24
- // file that has been converted to a CommonJS file using a Babel-
25
- // compatible transform (i.e. "__esModule" has not been set), then set
26
- // "default" to the CommonJS "module.exports" for node compatibility.
27
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
- mod
29
- ));
30
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
32
-
33
- // tmp/ngc/angular/angular/index.js
34
- var index_exports = {};
35
- __export(index_exports, {
36
- AngularHttpAdapter: () => AngularHttpAdapter,
37
- AuthGuard: () => AuthGuard,
38
- AuthInterceptor: () => AuthInterceptor,
39
- AuthService: () => AuthService,
40
- NAUTH_CLIENT_CONFIG: () => NAUTH_CLIENT_CONFIG,
41
- NAuthModule: () => NAuthModule,
42
- authGuard: () => authGuard,
43
- authInterceptor: () => authInterceptor,
44
- socialRedirectCallbackGuard: () => socialRedirectCallbackGuard
45
- });
46
- module.exports = __toCommonJS(index_exports);
47
-
48
- // tmp/ngc/angular/angular/tokens.js
49
- var import_core = require("@angular/core");
50
- var NAUTH_CLIENT_CONFIG = new import_core.InjectionToken("NAUTH_CLIENT_CONFIG");
51
-
52
- // tmp/ngc/angular/angular/auth.service.js
53
- var import_core3 = require("@angular/core");
54
- var import_rxjs2 = require("rxjs");
55
- var import_operators = require("rxjs/operators");
56
-
57
- // tmp/ngc/angular/angular/http-adapter.js
58
- var import_core2 = require("@angular/core");
59
- var import_http = require("@angular/common/http");
60
- var import_rxjs = require("rxjs");
61
-
62
- // tmp/ngc/angular/core/errors.js
63
- var _NAuthClientError = class _NAuthClientError extends Error {
64
- /**
65
- * Create a new client error.
66
- *
67
- * @param code - Error code from NAuthErrorCode enum
68
- * @param message - Human-readable error message
69
- * @param options - Optional metadata including details, statusCode, timestamp, and network error flag
70
- */
71
- constructor(code, message, options) {
72
- super(message);
73
- __publicField(this, "code");
74
- __publicField(this, "details");
75
- __publicField(this, "statusCode");
76
- __publicField(this, "timestamp");
77
- __publicField(this, "isNetworkError");
78
- this.code = code;
79
- this.details = options?.details;
80
- this.statusCode = options?.statusCode;
81
- this.timestamp = options?.timestamp || (/* @__PURE__ */ new Date()).toISOString();
82
- this.isNetworkError = options?.isNetworkError ?? false;
83
- this.name = "NAuthClientError";
84
- Object.setPrototypeOf(this, _NAuthClientError.prototype);
85
- }
86
- /**
87
- * Check if error matches a specific error code.
88
- *
89
- * @param code - Error code to check against
90
- * @returns True if the error code matches
91
- *
92
- * @example
93
- * ```typescript
94
- * if (error.isCode(NAuthErrorCode.RATE_LIMIT_SMS)) {
95
- * // Handle SMS rate limit
96
- * }
97
- * ```
98
- */
99
- isCode(code) {
100
- return this.code === code;
101
- }
102
- /**
103
- * Get error details/metadata.
104
- *
105
- * @returns Error details object or undefined
106
- *
107
- * @example
108
- * ```typescript
109
- * const details = error.getDetails();
110
- * if (details?.retryAfter) {
111
- * console.log(`Retry after ${details.retryAfter} seconds`);
112
- * }
113
- * ```
114
- */
115
- getDetails() {
116
- return this.details;
117
- }
118
- /**
119
- * Get the error code.
120
- *
121
- * @returns The error code enum value
122
- */
123
- getCode() {
124
- return this.code;
125
- }
126
- /**
127
- * Serialize error to JSON object.
128
- *
129
- * @returns Plain object representation
130
- *
131
- * @example
132
- * ```typescript
133
- * const errorJson = error.toJSON();
134
- * // { code: 'AUTH_INVALID_CREDENTIALS', message: '...', timestamp: '...', details: {...} }
135
- * ```
136
- */
137
- toJSON() {
138
- return {
139
- code: this.code,
140
- message: this.message,
141
- timestamp: this.timestamp,
142
- details: this.details,
143
- statusCode: this.statusCode
144
- };
145
- }
146
- };
147
- __name(_NAuthClientError, "NAuthClientError");
148
- var NAuthClientError = _NAuthClientError;
149
-
150
- // tmp/ngc/angular/types/error.types.js
151
- var NAuthErrorCode;
152
- (function(NAuthErrorCode2) {
153
- NAuthErrorCode2["AUTH_INVALID_CREDENTIALS"] = "AUTH_INVALID_CREDENTIALS";
154
- NAuthErrorCode2["AUTH_ACCOUNT_LOCKED"] = "AUTH_ACCOUNT_LOCKED";
155
- NAuthErrorCode2["AUTH_ACCOUNT_INACTIVE"] = "AUTH_ACCOUNT_INACTIVE";
156
- NAuthErrorCode2["AUTH_TOKEN_EXPIRED"] = "AUTH_TOKEN_EXPIRED";
157
- NAuthErrorCode2["AUTH_TOKEN_INVALID"] = "AUTH_TOKEN_INVALID";
158
- NAuthErrorCode2["AUTH_BEARER_NOT_ALLOWED"] = "AUTH_BEARER_NOT_ALLOWED";
159
- NAuthErrorCode2["AUTH_COOKIES_NOT_ALLOWED"] = "AUTH_COOKIES_NOT_ALLOWED";
160
- NAuthErrorCode2["AUTH_CSRF_TOKEN_INVALID"] = "AUTH_CSRF_TOKEN_INVALID";
161
- NAuthErrorCode2["AUTH_CSRF_TOKEN_MISSING"] = "AUTH_CSRF_TOKEN_MISSING";
162
- NAuthErrorCode2["AUTH_TOKEN_REUSE_DETECTED"] = "AUTH_TOKEN_REUSE_DETECTED";
163
- NAuthErrorCode2["AUTH_SESSION_NOT_FOUND"] = "AUTH_SESSION_NOT_FOUND";
164
- NAuthErrorCode2["AUTH_SESSION_EXPIRED"] = "AUTH_SESSION_EXPIRED";
165
- NAuthErrorCode2["SIGNUP_DISABLED"] = "SIGNUP_DISABLED";
166
- NAuthErrorCode2["SIGNUP_EMAIL_EXISTS"] = "SIGNUP_EMAIL_EXISTS";
167
- NAuthErrorCode2["SIGNUP_USERNAME_EXISTS"] = "SIGNUP_USERNAME_EXISTS";
168
- NAuthErrorCode2["SIGNUP_PHONE_EXISTS"] = "SIGNUP_PHONE_EXISTS";
169
- NAuthErrorCode2["SIGNUP_WEAK_PASSWORD"] = "SIGNUP_WEAK_PASSWORD";
170
- NAuthErrorCode2["SIGNUP_PHONE_REQUIRED"] = "SIGNUP_PHONE_REQUIRED";
171
- NAuthErrorCode2["SIGNUP_NOT_ALLOWED"] = "SIGNUP_NOT_ALLOWED";
172
- NAuthErrorCode2["VERIFY_CODE_INVALID"] = "VERIFY_CODE_INVALID";
173
- NAuthErrorCode2["VERIFY_CODE_EXPIRED"] = "VERIFY_CODE_EXPIRED";
174
- NAuthErrorCode2["VERIFY_TOO_MANY_ATTEMPTS"] = "VERIFY_TOO_MANY_ATTEMPTS";
175
- NAuthErrorCode2["VERIFY_ALREADY_VERIFIED"] = "VERIFY_ALREADY_VERIFIED";
176
- NAuthErrorCode2["MFA_SETUP_REQUIRED"] = "MFA_SETUP_REQUIRED";
177
- NAuthErrorCode2["RATE_LIMIT_SMS"] = "RATE_LIMIT_SMS";
178
- NAuthErrorCode2["RATE_LIMIT_EMAIL"] = "RATE_LIMIT_EMAIL";
179
- NAuthErrorCode2["RATE_LIMIT_LOGIN"] = "RATE_LIMIT_LOGIN";
180
- NAuthErrorCode2["RATE_LIMIT_RESEND"] = "RATE_LIMIT_RESEND";
181
- NAuthErrorCode2["SOCIAL_TOKEN_INVALID"] = "SOCIAL_TOKEN_INVALID";
182
- NAuthErrorCode2["SOCIAL_ACCOUNT_LINKED"] = "SOCIAL_ACCOUNT_LINKED";
183
- NAuthErrorCode2["SOCIAL_CONFIG_MISSING"] = "SOCIAL_CONFIG_MISSING";
184
- NAuthErrorCode2["SOCIAL_EMAIL_REQUIRED"] = "SOCIAL_EMAIL_REQUIRED";
185
- NAuthErrorCode2["SOCIAL_ACCOUNT_NOT_FOUND"] = "SOCIAL_ACCOUNT_NOT_FOUND";
186
- NAuthErrorCode2["CHALLENGE_EXPIRED"] = "CHALLENGE_EXPIRED";
187
- NAuthErrorCode2["CHALLENGE_INVALID"] = "CHALLENGE_INVALID";
188
- NAuthErrorCode2["CHALLENGE_TYPE_MISMATCH"] = "CHALLENGE_TYPE_MISMATCH";
189
- NAuthErrorCode2["CHALLENGE_MAX_ATTEMPTS"] = "CHALLENGE_MAX_ATTEMPTS";
190
- NAuthErrorCode2["CHALLENGE_ALREADY_COMPLETED"] = "CHALLENGE_ALREADY_COMPLETED";
191
- NAuthErrorCode2["VALIDATION_FAILED"] = "VALIDATION_FAILED";
192
- NAuthErrorCode2["VALIDATION_INVALID_PHONE"] = "VALIDATION_INVALID_PHONE";
193
- NAuthErrorCode2["VALIDATION_INVALID_EMAIL"] = "VALIDATION_INVALID_EMAIL";
194
- NAuthErrorCode2["VALIDATION_INVALID_PASSWORD"] = "VALIDATION_INVALID_PASSWORD";
195
- NAuthErrorCode2["PASSWORD_INCORRECT"] = "PASSWORD_INCORRECT";
196
- NAuthErrorCode2["PASSWORD_REUSED"] = "PASSWORD_REUSED";
197
- NAuthErrorCode2["PASSWORD_CHANGE_NOT_ALLOWED"] = "PASSWORD_CHANGE_NOT_ALLOWED";
198
- NAuthErrorCode2["WEAK_PASSWORD"] = "SIGNUP_WEAK_PASSWORD";
199
- NAuthErrorCode2["PASSWORD_RESET_CODE_INVALID"] = "PASSWORD_RESET_CODE_INVALID";
200
- NAuthErrorCode2["PASSWORD_RESET_CODE_EXPIRED"] = "PASSWORD_RESET_CODE_EXPIRED";
201
- NAuthErrorCode2["PASSWORD_RESET_MAX_ATTEMPTS"] = "PASSWORD_RESET_MAX_ATTEMPTS";
202
- NAuthErrorCode2["RATE_LIMIT_PASSWORD_RESET"] = "RATE_LIMIT_PASSWORD_RESET";
203
- NAuthErrorCode2["SIGNIN_BLOCKED_HIGH_RISK"] = "SIGNIN_BLOCKED_HIGH_RISK";
204
- NAuthErrorCode2["RESOURCE_NOT_FOUND"] = "RESOURCE_NOT_FOUND";
205
- NAuthErrorCode2["FORBIDDEN"] = "FORBIDDEN";
206
- NAuthErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
207
- NAuthErrorCode2["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
208
- })(NAuthErrorCode || (NAuthErrorCode = {}));
209
-
210
- // tmp/ngc/angular/angular/http-adapter.js
211
- var i0 = __toESM(require("@angular/core"));
212
- var _AngularHttpAdapter = class _AngularHttpAdapter {
213
- constructor() {
214
- __publicField(this, "http", (0, import_core2.inject)(import_http.HttpClient));
215
- }
216
- /**
217
- * Execute HTTP request using Angular's HttpClient.
218
- *
219
- * @param config - Request configuration
220
- * @returns Response with parsed data
221
- * @throws NAuthClientError if request fails
222
- */
223
- async request(config) {
224
- try {
225
- const data = await (0, import_rxjs.firstValueFrom)(this.http.request(config.method, config.url, {
226
- body: config.body,
227
- headers: config.headers,
228
- withCredentials: config.credentials === "include",
229
- observe: "body"
230
- // Only return body data
231
- }));
232
- return {
233
- data,
234
- status: 200,
235
- // HttpClient only returns data on success
236
- headers: {}
237
- // Can extract from observe: 'response' if needed
238
- };
239
- } catch (error) {
240
- if (error instanceof import_http.HttpErrorResponse) {
241
- const errorData = error.error || {};
242
- const code = typeof errorData["code"] === "string" ? errorData.code : NAuthErrorCode.INTERNAL_ERROR;
243
- const message = typeof errorData["message"] === "string" ? errorData.message : error.message || `Request failed with status ${error.status}`;
244
- const timestamp = typeof errorData["timestamp"] === "string" ? errorData.timestamp : void 0;
245
- const details = errorData["details"];
246
- throw new NAuthClientError(code, message, {
247
- statusCode: error.status,
248
- timestamp,
249
- details,
250
- isNetworkError: error.status === 0
251
- // Network error (no response from server)
252
- });
253
- }
254
- throw error;
255
- }
256
- }
257
- };
258
- __name(_AngularHttpAdapter, "AngularHttpAdapter");
259
- __publicField(_AngularHttpAdapter, "\u0275fac", i0.\u0275\u0275ngDeclareFactory({ minVersion: "12.0.0", version: "21.0.5", ngImport: i0, type: _AngularHttpAdapter, deps: [], target: i0.\u0275\u0275FactoryTarget.Injectable }));
260
- __publicField(_AngularHttpAdapter, "\u0275prov", i0.\u0275\u0275ngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.5", ngImport: i0, type: _AngularHttpAdapter, providedIn: "root" }));
261
- var AngularHttpAdapter = _AngularHttpAdapter;
262
- i0.\u0275\u0275ngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.5", ngImport: i0, type: AngularHttpAdapter, decorators: [{
263
- type: import_core2.Injectable,
264
- args: [{ providedIn: "root" }]
265
- }] });
266
-
267
- // tmp/ngc/angular/core/config.js
268
- var defaultEndpoints = {
269
- login: "/login",
270
- signup: "/signup",
271
- logout: "/logout",
272
- logoutAll: "/logout/all",
273
- refresh: "/refresh",
274
- respondChallenge: "/respond-challenge",
275
- resendCode: "/challenge/resend",
276
- getSetupData: "/challenge/setup-data",
277
- getChallengeData: "/challenge/challenge-data",
278
- profile: "/profile",
279
- changePassword: "/change-password",
280
- requestPasswordChange: "/request-password-change",
281
- forgotPassword: "/forgot-password",
282
- confirmForgotPassword: "/forgot-password/confirm",
283
- mfaStatus: "/mfa/status",
284
- mfaDevices: "/mfa/devices",
285
- mfaSetupData: "/mfa/setup-data",
286
- mfaVerifySetup: "/mfa/verify-setup",
287
- mfaRemove: "/mfa/method",
288
- mfaPreferred: "/mfa/preferred-method",
289
- mfaBackupCodes: "/mfa/backup-codes/generate",
290
- mfaExemption: "/mfa/exemption",
291
- socialLinked: "/social/linked",
292
- socialLink: "/social/link",
293
- socialUnlink: "/social/unlink",
294
- socialVerify: "/social/:provider/verify",
295
- socialRedirectStart: "/social/:provider/redirect",
296
- socialExchange: "/social/exchange",
297
- trustDevice: "/trust-device",
298
- isTrustedDevice: "/is-trusted-device",
299
- auditHistory: "/audit/history",
300
- updateProfile: "/profile"
301
- };
302
- var resolveConfig = /* @__PURE__ */ __name((config, defaultAdapter) => {
303
- const resolvedEndpoints = {
304
- ...defaultEndpoints,
305
- ...config.endpoints ?? {}
306
- };
307
- return {
308
- ...config,
309
- csrf: {
310
- cookieName: config.csrf?.cookieName ?? "nauth_csrf_token",
311
- headerName: config.csrf?.headerName ?? "x-csrf-token"
312
- },
313
- deviceTrust: {
314
- headerName: config.deviceTrust?.headerName ?? "X-Device-Token",
315
- storageKey: config.deviceTrust?.storageKey ?? "nauth_device_token"
316
- },
317
- headers: config.headers ?? {},
318
- timeout: config.timeout ?? 3e4,
319
- endpoints: resolvedEndpoints,
320
- storage: config.storage,
321
- httpAdapter: config.httpAdapter ?? defaultAdapter
322
- };
323
- }, "resolveConfig");
324
-
325
- // tmp/ngc/angular/core/refresh.js
326
- var ACCESS_TOKEN_KEY = "nauth_access_token";
327
- var REFRESH_TOKEN_KEY = "nauth_refresh_token";
328
- var ACCESS_EXPIRES_AT_KEY = "nauth_access_token_expires_at";
329
- var REFRESH_EXPIRES_AT_KEY = "nauth_refresh_token_expires_at";
330
- var USER_KEY = "nauth_user";
331
- var CHALLENGE_KEY = "nauth_challenge_session";
332
- var _TokenManager = class _TokenManager {
333
- /**
334
- * @param storage - storage adapter
335
- */
336
- constructor(storage) {
337
- __publicField(this, "storage");
338
- __publicField(this, "refreshPromise", null);
339
- __publicField(this, "isBrowser", typeof window !== "undefined");
340
- this.storage = storage;
341
- }
342
- /**
343
- * Load tokens from storage.
344
- */
345
- async getTokens() {
346
- const [accessToken, refreshToken, accessExpRaw, refreshExpRaw] = await Promise.all([
347
- this.storage.getItem(ACCESS_TOKEN_KEY),
348
- this.storage.getItem(REFRESH_TOKEN_KEY),
349
- this.storage.getItem(ACCESS_EXPIRES_AT_KEY),
350
- this.storage.getItem(REFRESH_EXPIRES_AT_KEY)
351
- ]);
352
- return {
353
- accessToken,
354
- refreshToken,
355
- accessTokenExpiresAt: accessExpRaw ? Number(accessExpRaw) : null,
356
- refreshTokenExpiresAt: refreshExpRaw ? Number(refreshExpRaw) : null
357
- };
358
- }
359
- /**
360
- * Persist tokens.
361
- *
362
- * @param tokens - new token pair
363
- */
364
- async setTokens(tokens) {
365
- await Promise.all([
366
- this.storage.setItem(ACCESS_TOKEN_KEY, tokens.accessToken),
367
- this.storage.setItem(REFRESH_TOKEN_KEY, tokens.refreshToken),
368
- this.storage.setItem(ACCESS_EXPIRES_AT_KEY, tokens.accessTokenExpiresAt.toString()),
369
- this.storage.setItem(REFRESH_EXPIRES_AT_KEY, tokens.refreshTokenExpiresAt.toString())
370
- ]);
371
- this.broadcastStorage();
372
- }
373
- /**
374
- * Clear tokens and related auth state.
375
- */
376
- async clearTokens() {
377
- await Promise.all([
378
- this.storage.removeItem(ACCESS_TOKEN_KEY),
379
- this.storage.removeItem(REFRESH_TOKEN_KEY),
380
- this.storage.removeItem(ACCESS_EXPIRES_AT_KEY),
381
- this.storage.removeItem(REFRESH_EXPIRES_AT_KEY),
382
- this.storage.removeItem(USER_KEY),
383
- this.storage.removeItem(CHALLENGE_KEY)
384
- ]);
385
- this.broadcastStorage();
386
- }
387
- /**
388
- * Ensure only one refresh in flight.
389
- *
390
- * @param refreshFn - function performing refresh request
391
- */
392
- async refreshOnce(refreshFn) {
393
- if (!this.refreshPromise) {
394
- this.refreshPromise = refreshFn().then(async (tokens) => {
395
- await this.setTokens(tokens);
396
- return tokens;
397
- }).catch((error) => {
398
- throw error;
399
- }).finally(() => {
400
- this.refreshPromise = null;
401
- });
402
- }
403
- return this.refreshPromise;
404
- }
405
- /**
406
- * Validate that a refresh token exists before attempting refresh.
407
- */
408
- async assertHasRefreshToken() {
409
- const state = await this.getTokens();
410
- if (!state.refreshToken) {
411
- throw new NAuthClientError(NAuthErrorCode.AUTH_SESSION_NOT_FOUND, "No refresh token available");
412
- }
413
- }
414
- /**
415
- * Broadcast a no-op write to trigger storage listeners in other tabs.
416
- */
417
- broadcastStorage() {
418
- if (!this.isBrowser)
419
- return;
420
- try {
421
- window.localStorage.setItem("nauth_sync", Date.now().toString());
422
- } catch {
423
- }
424
- }
425
- };
426
- __name(_TokenManager, "TokenManager");
427
- var TokenManager = _TokenManager;
428
-
429
- // tmp/ngc/angular/storage/browser.js
430
- var _BrowserStorage = class _BrowserStorage {
431
- /**
432
- * Create a browser storage adapter.
433
- *
434
- * @param storage - Storage implementation (localStorage by default)
435
- */
436
- constructor(storage = window.localStorage) {
437
- __publicField(this, "storage");
438
- this.storage = storage;
439
- }
440
- async getItem(key) {
441
- return this.storage.getItem(key);
442
- }
443
- async setItem(key, value) {
444
- this.storage.setItem(key, value);
445
- }
446
- async removeItem(key) {
447
- this.storage.removeItem(key);
448
- }
449
- async clear() {
450
- this.storage.clear();
451
- }
452
- };
453
- __name(_BrowserStorage, "BrowserStorage");
454
- var BrowserStorage = _BrowserStorage;
455
-
456
- // tmp/ngc/angular/storage/memory.js
457
- var _InMemoryStorage = class _InMemoryStorage {
458
- constructor() {
459
- __publicField(this, "store", /* @__PURE__ */ new Map());
460
- }
461
- async getItem(key) {
462
- return this.store.has(key) ? this.store.get(key) : null;
463
- }
464
- async setItem(key, value) {
465
- this.store.set(key, value);
466
- }
467
- async removeItem(key) {
468
- this.store.delete(key);
469
- }
470
- async clear() {
471
- this.store.clear();
472
- }
473
- };
474
- __name(_InMemoryStorage, "InMemoryStorage");
475
- var InMemoryStorage = _InMemoryStorage;
476
-
477
- // tmp/ngc/angular/core/events.js
478
- var _EventEmitter = class _EventEmitter {
479
- constructor() {
480
- __publicField(this, "listeners", /* @__PURE__ */ new Map());
481
- }
482
- /**
483
- * Subscribe to an authentication event
484
- *
485
- * @param event - Event type or '*' for all events
486
- * @param listener - Callback function
487
- * @returns Unsubscribe function
488
- *
489
- * @example
490
- * ```typescript
491
- * const unsubscribe = emitter.on('auth:success', (event) => {
492
- * console.log('User logged in:', event.data);
493
- * });
494
- *
495
- * // Later
496
- * unsubscribe();
497
- * ```
498
- */
499
- on(event, listener) {
500
- if (!this.listeners.has(event)) {
501
- this.listeners.set(event, /* @__PURE__ */ new Set());
502
- }
503
- this.listeners.get(event).add(listener);
504
- return () => this.off(event, listener);
505
- }
506
- /**
507
- * Unsubscribe from an authentication event
508
- *
509
- * @param event - Event type or '*'
510
- * @param listener - Callback function to remove
511
- */
512
- off(event, listener) {
513
- this.listeners.get(event)?.delete(listener);
514
- }
515
- /**
516
- * Emit an authentication event
517
- *
518
- * Notifies all listeners for the specific event type and wildcard listeners.
519
- *
520
- * @param event - Event to emit
521
- * @internal
522
- */
523
- emit(event) {
524
- const specificListeners = this.listeners.get(event.type);
525
- const wildcardListeners = this.listeners.get("*");
526
- specificListeners?.forEach((listener) => {
527
- try {
528
- listener(event);
529
- } catch (error) {
530
- console.error(`Error in ${event.type} event listener:`, error);
531
- }
532
- });
533
- wildcardListeners?.forEach((listener) => {
534
- try {
535
- listener(event);
536
- } catch (error) {
537
- console.error(`Error in wildcard event listener:`, error);
538
- }
539
- });
540
- }
541
- /**
542
- * Remove all listeners
543
- *
544
- * @internal
545
- */
546
- clear() {
547
- this.listeners.clear();
548
- }
549
- };
550
- __name(_EventEmitter, "EventEmitter");
551
- var EventEmitter = _EventEmitter;
552
-
553
- // tmp/ngc/angular/adapters/fetch-adapter.js
554
- var _FetchAdapter = class _FetchAdapter {
555
- /**
556
- * Execute HTTP request using native fetch.
557
- *
558
- * @param config - Request configuration
559
- * @returns Response with parsed data
560
- * @throws NAuthClientError if request fails
561
- */
562
- async request(config) {
563
- const fetchOptions = {
564
- method: config.method,
565
- headers: config.headers,
566
- signal: config.signal,
567
- credentials: config.credentials
568
- };
569
- if (config.body !== void 0) {
570
- fetchOptions.body = JSON.stringify(config.body);
571
- }
572
- let response;
573
- try {
574
- response = await fetch(config.url, fetchOptions);
575
- } catch (error) {
576
- throw new NAuthClientError(NAuthErrorCode.INTERNAL_ERROR, "Network request failed", {
577
- isNetworkError: true,
578
- details: { url: config.url, message: error.message }
579
- });
580
- }
581
- const status = response.status;
582
- let data = null;
583
- const text = await response.text();
584
- if (text) {
585
- try {
586
- data = JSON.parse(text);
587
- } catch {
588
- data = text;
589
- }
590
- }
591
- const headers = {};
592
- response.headers.forEach((value, key) => {
593
- headers[key] = value;
594
- });
595
- if (!response.ok) {
596
- const errorData = typeof data === "object" && data !== null ? data : {};
597
- const code = typeof errorData["code"] === "string" ? errorData["code"] : NAuthErrorCode.INTERNAL_ERROR;
598
- const message = typeof errorData["message"] === "string" ? errorData["message"] : `Request failed with status ${status}`;
599
- const timestamp = typeof errorData["timestamp"] === "string" ? errorData["timestamp"] : void 0;
600
- const details = errorData["details"];
601
- throw new NAuthClientError(code, message, {
602
- statusCode: status,
603
- timestamp,
604
- details
605
- });
606
- }
607
- return { data, status, headers };
608
- }
609
- };
610
- __name(_FetchAdapter, "FetchAdapter");
611
- var FetchAdapter = _FetchAdapter;
612
-
613
- // tmp/ngc/angular/types/auth.types.js
614
- var AuthChallenge;
615
- (function(AuthChallenge2) {
616
- AuthChallenge2["VERIFY_EMAIL"] = "VERIFY_EMAIL";
617
- AuthChallenge2["VERIFY_PHONE"] = "VERIFY_PHONE";
618
- AuthChallenge2["MFA_REQUIRED"] = "MFA_REQUIRED";
619
- AuthChallenge2["MFA_SETUP_REQUIRED"] = "MFA_SETUP_REQUIRED";
620
- AuthChallenge2["FORCE_CHANGE_PASSWORD"] = "FORCE_CHANGE_PASSWORD";
621
- })(AuthChallenge || (AuthChallenge = {}));
622
-
623
- // tmp/ngc/angular/core/client.js
624
- var USER_KEY2 = "nauth_user";
625
- var CHALLENGE_KEY2 = "nauth_challenge_session";
626
- var hasWindow = /* @__PURE__ */ __name(() => typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined", "hasWindow");
627
- var defaultStorage = /* @__PURE__ */ __name(() => {
628
- if (hasWindow() && typeof window.localStorage !== "undefined") {
629
- return new BrowserStorage();
630
- }
631
- return new InMemoryStorage();
632
- }, "defaultStorage");
633
- var _NAuthClient = class _NAuthClient {
634
- /**
635
- * Create a new client instance.
636
- *
637
- * @param userConfig - Client configuration
638
- */
639
- constructor(userConfig) {
640
- __publicField(this, "config");
641
- __publicField(this, "tokenManager");
642
- __publicField(this, "eventEmitter");
643
- __publicField(this, "currentUser", null);
644
- /**
645
- * Handle cross-tab storage updates.
646
- */
647
- __publicField(this, "handleStorageEvent", /* @__PURE__ */ __name((event) => {
648
- if (event.key === "nauth_sync") {
649
- this.config.storage.getItem(USER_KEY2).then((value) => value ? JSON.parse(value) : null).then((user) => {
650
- this.currentUser = user;
651
- this.config.onAuthStateChange?.(user);
652
- }).catch(() => {
653
- });
654
- }
655
- }, "handleStorageEvent"));
656
- const storage = userConfig.storage ?? defaultStorage();
657
- const defaultAdapter = userConfig.httpAdapter ?? new FetchAdapter();
658
- this.config = resolveConfig({ ...userConfig, storage }, defaultAdapter);
659
- this.tokenManager = new TokenManager(storage);
660
- this.eventEmitter = new EventEmitter();
661
- if (hasWindow()) {
662
- window.addEventListener("storage", this.handleStorageEvent);
663
- }
664
- }
665
- /**
666
- * Clean up resources.
667
- */
668
- dispose() {
669
- if (hasWindow()) {
670
- window.removeEventListener("storage", this.handleStorageEvent);
671
- }
672
- }
673
- /**
674
- * Login with identifier and password.
675
- */
676
- async login(identifier, password) {
677
- const loginEvent = { type: "auth:login", data: { identifier }, timestamp: Date.now() };
678
- this.eventEmitter.emit(loginEvent);
679
- try {
680
- const body = { identifier, password };
681
- const response = await this.post(this.config.endpoints.login, body);
682
- await this.handleAuthResponse(response);
683
- if (response.challengeName) {
684
- const challengeEvent = { type: "auth:challenge", data: response, timestamp: Date.now() };
685
- this.eventEmitter.emit(challengeEvent);
686
- } else {
687
- const successEvent = { type: "auth:success", data: response, timestamp: Date.now() };
688
- this.eventEmitter.emit(successEvent);
689
- }
690
- return response;
691
- } catch (error) {
692
- const authError = error instanceof NAuthClientError ? error : new NAuthClientError(NAuthErrorCode.AUTH_INVALID_CREDENTIALS, error.message || "Login failed");
693
- const errorEvent = { type: "auth:error", data: authError, timestamp: Date.now() };
694
- this.eventEmitter.emit(errorEvent);
695
- throw authError;
696
- }
697
- }
698
- /**
699
- * Signup with credentials.
700
- */
701
- async signup(payload) {
702
- this.eventEmitter.emit({ type: "auth:signup", data: { email: payload.email }, timestamp: Date.now() });
703
- try {
704
- const response = await this.post(this.config.endpoints.signup, payload);
705
- await this.handleAuthResponse(response);
706
- if (response.challengeName) {
707
- this.eventEmitter.emit({ type: "auth:challenge", data: response, timestamp: Date.now() });
708
- } else {
709
- this.eventEmitter.emit({ type: "auth:success", data: response, timestamp: Date.now() });
710
- }
711
- return response;
712
- } catch (error) {
713
- const authError = error instanceof NAuthClientError ? error : new NAuthClientError(NAuthErrorCode.AUTH_INVALID_CREDENTIALS, error.message || "Signup failed");
714
- this.eventEmitter.emit({ type: "auth:error", data: authError, timestamp: Date.now() });
715
- throw authError;
716
- }
717
- }
718
- /**
719
- * Refresh tokens manually.
720
- */
721
- async refreshTokens() {
722
- const tokenDelivery = this.getTokenDeliveryMode();
723
- if (tokenDelivery === "json") {
724
- await this.tokenManager.assertHasRefreshToken();
725
- }
726
- const body = tokenDelivery === "json" ? { refreshToken: (await this.tokenManager.getTokens()).refreshToken } : { refreshToken: "" };
727
- const refreshFn = /* @__PURE__ */ __name(async () => {
728
- return this.post(this.config.endpoints.refresh, body, false);
729
- }, "refreshFn");
730
- const tokens = await this.tokenManager.refreshOnce(refreshFn);
731
- this.config.onTokenRefresh?.();
732
- this.eventEmitter.emit({ type: "auth:refresh", data: { success: true }, timestamp: Date.now() });
733
- return tokens;
734
- }
735
- /**
736
- * Logout current session.
737
- *
738
- * Uses GET request to avoid CSRF token issues.
739
- *
740
- * @param forgetDevice - If true, also untrust the device (require MFA on next login)
741
- */
742
- async logout(forgetDevice) {
743
- const queryParams = forgetDevice ? "?forgetMe=true" : "";
744
- try {
745
- await this.get(this.config.endpoints.logout + queryParams, true);
746
- } catch (error) {
747
- console.warn("[nauth] Logout request failed (session may already be invalid):", error);
748
- } finally {
749
- await this.clearAuthState(forgetDevice);
750
- this.eventEmitter.emit({
751
- type: "auth:logout",
752
- data: { forgetDevice: !!forgetDevice, global: false },
753
- timestamp: Date.now()
754
- });
755
- }
756
- }
757
- /**
758
- * Logout all sessions.
759
- *
760
- * Revokes all active sessions for the current user across all devices.
761
- * Optionally revokes all trusted devices if forgetDevices is true.
762
- *
763
- * @param forgetDevices - If true, also revokes all trusted devices (default: false)
764
- * @returns Number of sessions revoked
765
- */
766
- async logoutAll(forgetDevices) {
767
- try {
768
- const payload = {
769
- forgetDevices: forgetDevices ?? false
770
- };
771
- const result = await this.post(this.config.endpoints.logoutAll, payload, true);
772
- await this.clearAuthState(forgetDevices);
773
- this.eventEmitter.emit({
774
- type: "auth:logout",
775
- data: { forgetDevice: !!forgetDevices, global: true },
776
- timestamp: Date.now()
777
- });
778
- return { revokedCount: result.revokedCount };
779
- } catch (error) {
780
- await this.clearAuthState(forgetDevices);
781
- this.eventEmitter.emit({
782
- type: "auth:logout",
783
- data: { forgetDevice: !!forgetDevices, global: true },
784
- timestamp: Date.now()
785
- });
786
- throw error;
787
- }
788
- }
789
- /**
790
- * Respond to a challenge.
791
- *
792
- * Validates challenge response data before sending to backend.
793
- * Provides helpful error messages for common validation issues.
794
- *
795
- * @param response - Challenge response data
796
- * @returns Auth response from backend
797
- * @throws {NAuthClientError} If validation fails
798
- */
799
- async respondToChallenge(response) {
800
- if (response.type === AuthChallenge.MFA_SETUP_REQUIRED && response.method === "totp") {
801
- const setupData = response.setupData;
802
- if (!setupData || typeof setupData !== "object") {
803
- throw new NAuthClientError(NAuthErrorCode.VALIDATION_FAILED, "TOTP setup requires setupData with both secret and code", { details: { field: "setupData" } });
804
- }
805
- const secret = setupData["secret"];
806
- const code = setupData["code"];
807
- if (!secret || typeof secret !== "string") {
808
- throw new NAuthClientError(NAuthErrorCode.VALIDATION_FAILED, "TOTP setup requires secret in setupData. Make sure to include the secret from getSetupData() response.", { details: { field: "secret" } });
809
- }
810
- if (!code || typeof code !== "string") {
811
- throw new NAuthClientError(NAuthErrorCode.VALIDATION_FAILED, "TOTP setup requires code in setupData. Please enter the verification code from your authenticator app.", { details: { field: "code" } });
812
- }
813
- }
814
- try {
815
- const result = await this.post(this.config.endpoints.respondChallenge, response);
816
- await this.handleAuthResponse(result);
817
- if (result.challengeName) {
818
- const challengeEvent = { type: "auth:challenge", data: result, timestamp: Date.now() };
819
- this.eventEmitter.emit(challengeEvent);
820
- } else {
821
- const successEvent = { type: "auth:success", data: result, timestamp: Date.now() };
822
- this.eventEmitter.emit(successEvent);
823
- }
824
- return result;
825
- } catch (error) {
826
- const authError = error instanceof NAuthClientError ? error : new NAuthClientError(NAuthErrorCode.CHALLENGE_INVALID, error.message || "Challenge response failed");
827
- const errorEvent = { type: "auth:error", data: authError, timestamp: Date.now() };
828
- this.eventEmitter.emit(errorEvent);
829
- throw authError;
830
- }
831
- }
832
- /**
833
- * Resend a challenge code.
834
- */
835
- async resendCode(session) {
836
- const payload = { session };
837
- return this.post(this.config.endpoints.resendCode, payload);
838
- }
839
- /**
840
- * Get setup data for MFA.
841
- *
842
- * Returns method-specific setup information:
843
- * - TOTP: { secret, qrCode, manualEntryKey }
844
- * - SMS: { maskedPhone }
845
- * - Email: { maskedEmail }
846
- * - Passkey: WebAuthn registration options
847
- *
848
- * @param session - Challenge session token
849
- * @param method - MFA method to set up
850
- * @returns Setup data wrapped in GetSetupDataResponse
851
- */
852
- async getSetupData(session, method) {
853
- const payload = { session, method };
854
- return this.post(this.config.endpoints.getSetupData, payload);
855
- }
856
- /**
857
- * Get challenge data (e.g., WebAuthn options).
858
- *
859
- * Returns challenge-specific data for verification flows.
860
- *
861
- * @param session - Challenge session token
862
- * @param method - Challenge method to get data for
863
- * @returns Challenge data wrapped in GetChallengeDataResponse
864
- */
865
- async getChallengeData(session, method) {
866
- const payload = { session, method };
867
- return this.post(this.config.endpoints.getChallengeData, payload);
868
- }
869
- /**
870
- * Get current user profile.
871
- */
872
- async getProfile() {
873
- const profile = await this.get(this.config.endpoints.profile, true);
874
- await this.setUser(profile);
875
- return profile;
876
- }
877
- /**
878
- * Update user profile.
879
- */
880
- async updateProfile(updates) {
881
- const updated = await this.put(this.config.endpoints.updateProfile, updates, true);
882
- await this.setUser(updated);
883
- return updated;
884
- }
885
- /**
886
- * Change user password.
887
- */
888
- async changePassword(oldPassword, newPassword) {
889
- const payload = { currentPassword: oldPassword, newPassword };
890
- await this.post(this.config.endpoints.changePassword, payload, true);
891
- }
892
- /**
893
- * Request a password reset code (forgot password).
894
- */
895
- async forgotPassword(identifier) {
896
- const payload = { identifier };
897
- return this.post(this.config.endpoints.forgotPassword, payload);
898
- }
899
- /**
900
- * Confirm a password reset code and set a new password.
901
- */
902
- async confirmForgotPassword(identifier, code, newPassword) {
903
- const payload = { identifier, code, newPassword };
904
- const result = await this.post(this.config.endpoints.confirmForgotPassword, payload);
905
- await this.clearAuthState(false);
906
- return result;
907
- }
908
- /**
909
- * Request password change (must change on next login).
910
- */
911
- async requestPasswordChange() {
912
- await this.post(this.config.endpoints.requestPasswordChange, {}, true);
913
- }
914
- /**
915
- * Get MFA status.
916
- */
917
- async getMfaStatus() {
918
- return this.get(this.config.endpoints.mfaStatus, true);
919
- }
920
- /**
921
- * Get MFA devices.
922
- */
923
- async getMfaDevices() {
924
- return this.get(this.config.endpoints.mfaDevices, true);
925
- }
926
- /**
927
- * Setup MFA device (authenticated user).
928
- */
929
- async setupMfaDevice(method) {
930
- return this.post(this.config.endpoints.mfaSetupData, { method }, true);
931
- }
932
- /**
933
- * Verify MFA setup (authenticated user).
934
- */
935
- async verifyMfaSetup(method, setupData, deviceName) {
936
- return this.post(this.config.endpoints.mfaVerifySetup, { method, setupData, deviceName }, true);
937
- }
938
- /**
939
- * Remove MFA method.
940
- */
941
- async removeMfaDevice(method) {
942
- const path = `${this.config.endpoints.mfaRemove}/${method}`;
943
- return this.delete(path, true);
944
- }
945
- /**
946
- * Set preferred MFA method.
947
- *
948
- * @param method - Device method to set as preferred ('totp', 'sms', 'email', or 'passkey'). Cannot be 'backup'.
949
- * @returns Success message
950
- */
951
- async setPreferredMfaMethod(method) {
952
- return this.post(this.config.endpoints.mfaPreferred, { method }, true);
953
- }
954
- /**
955
- * Generate backup codes.
956
- */
957
- async generateBackupCodes() {
958
- const result = await this.post(this.config.endpoints.mfaBackupCodes, {}, true);
959
- return result.codes;
960
- }
961
- /**
962
- * Set MFA exemption (admin/test scenarios).
963
- */
964
- async setMfaExemption(exempt, reason) {
965
- await this.post(this.config.endpoints.mfaExemption, { exempt, reason }, true);
966
- }
967
- // ============================================================================
968
- // Event System
969
- // ============================================================================
970
- /**
971
- * Subscribe to authentication events.
972
- *
973
- * Emits events throughout the auth lifecycle for custom logic, analytics, or UI updates.
974
- *
975
- * @param event - Event type to listen for, or '*' for all events
976
- * @param listener - Callback function to handle the event
977
- * @returns Unsubscribe function
978
- *
979
- * @example
980
- * ```typescript
981
- * // Listen to successful authentication
982
- * const unsubscribe = client.on('auth:success', (event) => {
983
- * console.log('User logged in:', event.data.user);
984
- * analytics.track('login_success');
985
- * });
986
- *
987
- * // Listen to all events
988
- * client.on('*', (event) => {
989
- * console.log('Auth event:', event.type, event.data);
990
- * });
991
- *
992
- * // Unsubscribe when done
993
- * unsubscribe();
994
- * ```
995
- */
996
- on(event, listener) {
997
- return this.eventEmitter.on(event, listener);
998
- }
999
- /**
1000
- * Unsubscribe from authentication events.
1001
- *
1002
- * @param event - Event type
1003
- * @param listener - Callback function to remove
1004
- */
1005
- off(event, listener) {
1006
- this.eventEmitter.off(event, listener);
1007
- }
1008
- // ============================================================================
1009
- // Social Authentication
1010
- // ============================================================================
1011
- /**
1012
- * Start redirect-first social OAuth flow (web).
1013
- *
1014
- * This performs a browser navigation to:
1015
- * `GET {baseUrl}/social/:provider/redirect?returnTo=...&appState=...`
1016
- *
1017
- * The backend:
1018
- * - generates and stores CSRF state (cluster-safe)
1019
- * - redirects the user to the provider
1020
- * - completes OAuth on callback and sets cookies (or issues an exchange token)
1021
- * - redirects back to `returnTo` with `appState` (and `exchangeToken` for json/hybrid)
1022
- *
1023
- * @param provider - OAuth provider ('google', 'apple', 'facebook')
1024
- * @param options - Optional redirect options
1025
- *
1026
- * @example
1027
- * ```typescript
1028
- * await client.loginWithSocial('google', { returnTo: '/auth/callback', appState: '12345' });
1029
- * ```
1030
- */
1031
- async loginWithSocial(provider, options) {
1032
- this.eventEmitter.emit({ type: "oauth:started", data: { provider }, timestamp: Date.now() });
1033
- if (hasWindow()) {
1034
- const startPath = this.config.endpoints.socialRedirectStart.replace(":provider", provider);
1035
- const base = this.config.baseUrl.replace(/\/$/, "");
1036
- const startUrl = new URL(`${base}${startPath}`);
1037
- const returnTo = options?.returnTo ?? this.config.redirects?.success ?? "/";
1038
- startUrl.searchParams.set("returnTo", returnTo);
1039
- if (options?.action === "link") {
1040
- startUrl.searchParams.set("action", "link");
1041
- }
1042
- if (typeof options?.appState === "string" && options.appState.trim() !== "") {
1043
- startUrl.searchParams.set("appState", options.appState);
1044
- }
1045
- window.location.href = startUrl.toString();
1046
- }
1047
- }
1048
- /**
1049
- * Exchange an `exchangeToken` (from redirect callback URL) into an AuthResponse.
1050
- *
1051
- * Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back
1052
- * with `exchangeToken` instead of setting cookies.
1053
- *
1054
- * @param exchangeToken - One-time exchange token from the callback URL
1055
- * @returns AuthResponse
1056
- */
1057
- async exchangeSocialRedirect(exchangeToken) {
1058
- const token = exchangeToken?.trim();
1059
- if (!token) {
1060
- throw new NAuthClientError(NAuthErrorCode.CHALLENGE_INVALID, "Missing exchangeToken");
1061
- }
1062
- const result = await this.post(this.config.endpoints.socialExchange, { exchangeToken: token });
1063
- await this.handleAuthResponse(result);
1064
- return result;
1065
- }
1066
- /**
1067
- * Verify native social token (mobile).
1068
- */
1069
- async verifyNativeSocial(request) {
1070
- try {
1071
- const path = this.config.endpoints.socialVerify.replace(":provider", request.provider);
1072
- const result = await this.post(path, request);
1073
- await this.handleAuthResponse(result);
1074
- if (result.challengeName) {
1075
- const challengeEvent = { type: "auth:challenge", data: result, timestamp: Date.now() };
1076
- this.eventEmitter.emit(challengeEvent);
1077
- } else {
1078
- const successEvent = { type: "auth:success", data: result, timestamp: Date.now() };
1079
- this.eventEmitter.emit(successEvent);
1080
- }
1081
- return result;
1082
- } catch (error) {
1083
- const authError = error instanceof NAuthClientError ? error : new NAuthClientError(NAuthErrorCode.SOCIAL_TOKEN_INVALID, error.message || "Social verification failed");
1084
- const errorEvent = { type: "auth:error", data: authError, timestamp: Date.now() };
1085
- this.eventEmitter.emit(errorEvent);
1086
- throw authError;
1087
- }
1088
- }
1089
- /**
1090
- * Get linked accounts.
1091
- */
1092
- async getLinkedAccounts() {
1093
- return this.get(this.config.endpoints.socialLinked, true);
1094
- }
1095
- /**
1096
- * Link social account.
1097
- */
1098
- async linkSocialAccount(provider, code, state) {
1099
- return this.post(this.config.endpoints.socialLink, { provider, code, state }, true);
1100
- }
1101
- /**
1102
- * Unlink social account.
1103
- */
1104
- async unlinkSocialAccount(provider) {
1105
- return this.post(this.config.endpoints.socialUnlink, { provider }, true);
1106
- }
1107
- /**
1108
- * Trust current device.
1109
- */
1110
- async trustDevice() {
1111
- const result = await this.post(this.config.endpoints.trustDevice, {}, true);
1112
- await this.setDeviceToken(result.deviceToken);
1113
- return result;
1114
- }
1115
- /**
1116
- * Check if the current device is trusted.
1117
- *
1118
- * Returns whether the current device is trusted based on the device token
1119
- * (from cookie in cookies mode, or header in JSON mode).
1120
- *
1121
- * This performs a server-side validation of the device token and checks:
1122
- * - Device token exists and is valid
1123
- * - Device token matches a trusted device record in the database
1124
- * - Trust has not expired
1125
- *
1126
- * @returns Object with trusted status
1127
- *
1128
- * @example
1129
- * ```typescript
1130
- * const result = await client.isTrustedDevice();
1131
- * if (result.trusted) {
1132
- * console.log('This device is trusted');
1133
- * }
1134
- * ```
1135
- */
1136
- async isTrustedDevice() {
1137
- return this.get(this.config.endpoints.isTrustedDevice, true);
1138
- }
1139
- /**
1140
- * Get paginated audit history for the current user.
1141
- *
1142
- * Returns authentication and security events with full audit details including:
1143
- * - Event type (login, logout, MFA, etc.)
1144
- * - Event status (success, failure, suspicious)
1145
- * - Device information, location, risk factors
1146
- *
1147
- * @param params - Query parameters for filtering and pagination
1148
- * @returns Paginated audit history response
1149
- *
1150
- * @example
1151
- * ```typescript
1152
- * const history = await client.getAuditHistory({
1153
- * page: 1,
1154
- * limit: 20,
1155
- * eventType: 'LOGIN_SUCCESS'
1156
- * });
1157
- * ```
1158
- */
1159
- async getAuditHistory(params) {
1160
- const entries = Object.entries(params ?? {}).map(([k, v]) => [k, String(v)]);
1161
- const query = entries.length > 0 ? `?${new URLSearchParams(entries).toString()}` : "";
1162
- const path = `${this.config.endpoints.auditHistory}${query}`;
1163
- return this.get(path, true);
1164
- }
1165
- /**
1166
- * Initialize client by hydrating state from storage.
1167
- * Call this on app startup to restore auth state.
1168
- */
1169
- async initialize() {
1170
- const userJson = await this.config.storage.getItem(USER_KEY2);
1171
- if (userJson) {
1172
- try {
1173
- this.currentUser = JSON.parse(userJson);
1174
- this.config.onAuthStateChange?.(this.currentUser);
1175
- } catch {
1176
- await this.config.storage.removeItem(USER_KEY2);
1177
- }
1178
- }
1179
- }
1180
- /**
1181
- * Determine if user is authenticated (async - checks tokens).
1182
- */
1183
- async isAuthenticated() {
1184
- const tokens = await this.tokenManager.getTokens();
1185
- return Boolean(tokens.accessToken);
1186
- }
1187
- /**
1188
- * Determine if user is authenticated (sync - checks cached user).
1189
- * Use this for guards and sync checks. Use `isAuthenticated()` for definitive check.
1190
- */
1191
- isAuthenticatedSync() {
1192
- return this.currentUser !== null;
1193
- }
1194
- /**
1195
- * Get current access token (may be null).
1196
- */
1197
- async getAccessToken() {
1198
- const tokens = await this.tokenManager.getTokens();
1199
- return tokens.accessToken ?? null;
1200
- }
1201
- /**
1202
- * Get current user (cached, sync).
1203
- */
1204
- getCurrentUser() {
1205
- return this.currentUser;
1206
- }
1207
- /**
1208
- * Get stored challenge session (for resuming challenge flows).
1209
- */
1210
- async getStoredChallenge() {
1211
- const raw = await this.config.storage.getItem(CHALLENGE_KEY2);
1212
- if (!raw)
1213
- return null;
1214
- try {
1215
- return JSON.parse(raw);
1216
- } catch {
1217
- return null;
1218
- }
1219
- }
1220
- /**
1221
- * Clear stored challenge session.
1222
- */
1223
- async clearStoredChallenge() {
1224
- await this.config.storage.removeItem(CHALLENGE_KEY2);
1225
- }
1226
- /**
1227
- * Internal: handle auth response (tokens or challenge).
1228
- *
1229
- * In cookies mode: Tokens are set as httpOnly cookies by backend, not stored in client storage.
1230
- * In JSON mode: Tokens are stored in tokenManager for Authorization header.
1231
- */
1232
- async handleAuthResponse(response) {
1233
- if (response.challengeName) {
1234
- await this.persistChallenge(response);
1235
- return;
1236
- }
1237
- if (this.config.tokenDelivery === "json" && response.accessToken && response.refreshToken) {
1238
- await this.tokenManager.setTokens({
1239
- accessToken: response.accessToken,
1240
- refreshToken: response.refreshToken,
1241
- accessTokenExpiresAt: response.accessTokenExpiresAt ?? 0,
1242
- refreshTokenExpiresAt: response.refreshTokenExpiresAt ?? 0
1243
- });
1244
- }
1245
- if (this.config.tokenDelivery === "json" && response.deviceToken) {
1246
- await this.setDeviceToken(response.deviceToken);
1247
- }
1248
- if (response.user) {
1249
- const user = response.user;
1250
- user.sessionAuthMethod = response.authMethod ?? null;
1251
- await this.setUser(user);
1252
- }
1253
- await this.clearChallenge();
1254
- }
1255
- /**
1256
- * Persist challenge state.
1257
- */
1258
- async persistChallenge(challenge) {
1259
- await this.config.storage.setItem(CHALLENGE_KEY2, JSON.stringify(challenge));
1260
- }
1261
- /**
1262
- * Clear challenge state.
1263
- */
1264
- async clearChallenge() {
1265
- await this.config.storage.removeItem(CHALLENGE_KEY2);
1266
- }
1267
- /**
1268
- * Persist user.
1269
- */
1270
- async setUser(user) {
1271
- this.currentUser = user;
1272
- await this.config.storage.setItem(USER_KEY2, JSON.stringify(user));
1273
- this.config.onAuthStateChange?.(user);
1274
- }
1275
- /**
1276
- * Clear all auth state.
1277
- *
1278
- * @param forgetDevice - If true, also clear device token (for JSON mode)
1279
- */
1280
- async clearAuthState(forgetDevice) {
1281
- this.currentUser = null;
1282
- await this.tokenManager.clearTokens();
1283
- await this.config.storage.removeItem(USER_KEY2);
1284
- if (forgetDevice && this.config.tokenDelivery === "json") {
1285
- await this.config.storage.removeItem(this.config.deviceTrust.storageKey);
1286
- }
1287
- this.config.onAuthStateChange?.(null);
1288
- }
1289
- /**
1290
- * Persist device token (json mode mobile).
1291
- */
1292
- async setDeviceToken(token) {
1293
- await this.config.storage.setItem(this.config.deviceTrust.storageKey, token);
1294
- }
1295
- /**
1296
- * Determine token delivery mode for this environment.
1297
- */
1298
- getTokenDeliveryMode() {
1299
- return this.config.tokenDelivery;
1300
- }
1301
- /**
1302
- * Build request URL by combining baseUrl with path.
1303
- * @private
1304
- */
1305
- buildUrl(path) {
1306
- return `${this.config.baseUrl}${path}`;
1307
- }
1308
- /**
1309
- * Build request headers for authentication.
1310
- * @private
1311
- */
1312
- async buildHeaders(auth) {
1313
- const headers = {
1314
- "Content-Type": "application/json",
1315
- ...this.config.headers
1316
- };
1317
- if (auth && this.config.tokenDelivery === "json") {
1318
- const accessToken = (await this.tokenManager.getTokens()).accessToken;
1319
- if (accessToken) {
1320
- headers["Authorization"] = `Bearer ${accessToken}`;
1321
- }
1322
- }
1323
- if (this.config.tokenDelivery === "json") {
1324
- try {
1325
- const deviceToken = await this.config.storage.getItem(this.config.deviceTrust.storageKey);
1326
- if (deviceToken) {
1327
- headers[this.config.deviceTrust.headerName] = deviceToken;
1328
- }
1329
- } catch {
1330
- }
1331
- }
1332
- if (this.config.tokenDelivery === "cookies" && hasWindow()) {
1333
- const csrfToken = this.getCsrfToken();
1334
- if (csrfToken) {
1335
- headers[this.config.csrf.headerName] = csrfToken;
1336
- }
1337
- }
1338
- return headers;
1339
- }
1340
- /**
1341
- * Get CSRF token from cookie (browser only).
1342
- * @private
1343
- */
1344
- getCsrfToken() {
1345
- if (!hasWindow() || typeof document === "undefined")
1346
- return null;
1347
- const match = document.cookie.match(new RegExp(`(^| )${this.config.csrf.cookieName}=([^;]+)`));
1348
- return match ? decodeURIComponent(match[2]) : null;
1349
- }
1350
- /**
1351
- * Execute GET request.
1352
- * Note: 401 refresh is handled by framework interceptors (Angular) or manually.
1353
- */
1354
- async get(path, auth = false) {
1355
- const url = this.buildUrl(path);
1356
- const headers = await this.buildHeaders(auth);
1357
- const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1358
- const response = await this.config.httpAdapter.request({
1359
- method: "GET",
1360
- url,
1361
- headers,
1362
- credentials
1363
- });
1364
- return response.data;
1365
- }
1366
- /**
1367
- * Execute POST request.
1368
- * Note: 401 refresh is handled by framework interceptors (Angular) or manually.
1369
- */
1370
- async post(path, body, auth = false) {
1371
- const url = this.buildUrl(path);
1372
- const headers = await this.buildHeaders(auth);
1373
- const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1374
- const response = await this.config.httpAdapter.request({
1375
- method: "POST",
1376
- url,
1377
- headers,
1378
- body,
1379
- credentials
1380
- });
1381
- return response.data;
1382
- }
1383
- /**
1384
- * Execute PUT request.
1385
- * Note: 401 refresh is handled by framework interceptors (Angular) or manually.
1386
- */
1387
- async put(path, body, auth = false) {
1388
- const url = this.buildUrl(path);
1389
- const headers = await this.buildHeaders(auth);
1390
- const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1391
- const response = await this.config.httpAdapter.request({
1392
- method: "PUT",
1393
- url,
1394
- headers,
1395
- body,
1396
- credentials
1397
- });
1398
- return response.data;
1399
- }
1400
- /**
1401
- * Execute DELETE request.
1402
- * Note: 401 refresh is handled by framework interceptors (Angular) or manually.
1403
- */
1404
- async delete(path, auth = false) {
1405
- const url = this.buildUrl(path);
1406
- const headers = await this.buildHeaders(auth);
1407
- const credentials = this.config.tokenDelivery === "cookies" ? "include" : "omit";
1408
- const response = await this.config.httpAdapter.request({
1409
- method: "DELETE",
1410
- url,
1411
- headers,
1412
- credentials
1413
- });
1414
- return response.data;
1415
- }
1416
- };
1417
- __name(_NAuthClient, "NAuthClient");
1418
- var NAuthClient = _NAuthClient;
1419
-
1420
- // tmp/ngc/angular/angular/auth.service.js
1421
- var i02 = __toESM(require("@angular/core"));
1422
- var _AuthService = class _AuthService {
1423
- /**
1424
- * @param config - Injected client configuration
1425
- *
1426
- * Note: AngularHttpAdapter is automatically injected via Angular DI.
1427
- * This ensures all requests go through Angular's HttpClient and interceptors.
1428
- */
1429
- constructor(config) {
1430
- __publicField(this, "client");
1431
- __publicField(this, "config");
1432
- __publicField(this, "currentUserSubject", new import_rxjs2.BehaviorSubject(null));
1433
- __publicField(this, "isAuthenticatedSubject", new import_rxjs2.BehaviorSubject(false));
1434
- __publicField(this, "challengeSubject", new import_rxjs2.BehaviorSubject(null));
1435
- __publicField(this, "authEventsSubject", new import_rxjs2.Subject());
1436
- __publicField(this, "initialized", false);
1437
- if (!config) {
1438
- throw new Error("NAUTH_CLIENT_CONFIG is required to initialize AuthService");
1439
- }
1440
- this.config = config;
1441
- const httpAdapter = config.httpAdapter ?? (0, import_core3.inject)(AngularHttpAdapter);
1442
- this.client = new NAuthClient({
1443
- ...config,
1444
- httpAdapter,
1445
- // Automatically use Angular's HttpClient
1446
- onAuthStateChange: /* @__PURE__ */ __name((user) => {
1447
- this.currentUserSubject.next(user);
1448
- this.isAuthenticatedSubject.next(Boolean(user));
1449
- config.onAuthStateChange?.(user);
1450
- }, "onAuthStateChange")
1451
- });
1452
- this.client.on("*", (event) => {
1453
- this.authEventsSubject.next(event);
1454
- });
1455
- this.initialize();
1456
- }
1457
- // ============================================================================
1458
- // Reactive State Observables
1459
- // ============================================================================
1460
- /**
1461
- * Current user observable.
1462
- */
1463
- get currentUser$() {
1464
- return this.currentUserSubject.asObservable();
1465
- }
1466
- /**
1467
- * Authenticated state observable.
1468
- */
1469
- get isAuthenticated$() {
1470
- return this.isAuthenticatedSubject.asObservable();
1471
- }
1472
- /**
1473
- * Current challenge observable (for reactive challenge navigation).
1474
- */
1475
- get challenge$() {
1476
- return this.challengeSubject.asObservable();
1477
- }
1478
- /**
1479
- * Authentication events stream.
1480
- * Emits all auth lifecycle events for custom logic, analytics, or UI updates.
1481
- */
1482
- get authEvents$() {
1483
- return this.authEventsSubject.asObservable();
1484
- }
1485
- /**
1486
- * Successful authentication events stream.
1487
- * Emits when user successfully authenticates (login, signup, social auth).
1488
- */
1489
- get authSuccess$() {
1490
- return this.authEventsSubject.pipe((0, import_operators.filter)((e) => e.type === "auth:success"));
1491
- }
1492
- /**
1493
- * Authentication error events stream.
1494
- * Emits when authentication fails (login error, OAuth error, etc.).
1495
- */
1496
- get authError$() {
1497
- return this.authEventsSubject.pipe((0, import_operators.filter)((e) => e.type === "auth:error" || e.type === "oauth:error"));
1498
- }
1499
- // ============================================================================
1500
- // Sync State Accessors (for guards, templates)
1501
- // ============================================================================
1502
- /**
1503
- * Check if authenticated (sync, uses cached state).
1504
- */
1505
- isAuthenticated() {
1506
- return this.client.isAuthenticatedSync();
1507
- }
1508
- /**
1509
- * Get current user (sync, uses cached state).
1510
- */
1511
- getCurrentUser() {
1512
- return this.client.getCurrentUser();
1513
- }
1514
- /**
1515
- * Get current challenge (sync).
1516
- */
1517
- getCurrentChallenge() {
1518
- return this.challengeSubject.value;
1519
- }
1520
- // ============================================================================
1521
- // Core Auth Methods
1522
- // ============================================================================
1523
- /**
1524
- * Login with identifier and password.
1525
- *
1526
- * @param identifier - User email or username
1527
- * @param password - User password
1528
- * @returns Promise with auth response or challenge
1529
- *
1530
- * @example
1531
- * ```typescript
1532
- * const response = await this.auth.login('user@example.com', 'password');
1533
- * if (response.challengeName) {
1534
- * // Handle challenge
1535
- * } else {
1536
- * // Login successful
1537
- * }
1538
- * ```
1539
- */
1540
- async login(identifier, password) {
1541
- const res = await this.client.login(identifier, password);
1542
- return this.updateChallengeState(res);
1543
- }
1544
- /**
1545
- * Signup with credentials.
1546
- *
1547
- * @param payload - Signup request payload
1548
- * @returns Promise with auth response or challenge
1549
- *
1550
- * @example
1551
- * ```typescript
1552
- * const response = await this.auth.signup({
1553
- * email: 'new@example.com',
1554
- * password: 'SecurePass123!',
1555
- * firstName: 'John',
1556
- * });
1557
- * ```
1558
- */
1559
- async signup(payload) {
1560
- const res = await this.client.signup(payload);
1561
- return this.updateChallengeState(res);
1562
- }
1563
- /**
1564
- * Logout current session.
1565
- *
1566
- * @param forgetDevice - If true, removes device trust
1567
- *
1568
- * @example
1569
- * ```typescript
1570
- * await this.auth.logout();
1571
- * ```
1572
- */
1573
- async logout(forgetDevice) {
1574
- await this.client.logout(forgetDevice);
1575
- this.challengeSubject.next(null);
1576
- this.currentUserSubject.next(null);
1577
- this.isAuthenticatedSubject.next(false);
1578
- if (this.config.tokenDelivery === "cookies" && typeof document !== "undefined") {
1579
- const csrfCookieName = this.config.csrf?.cookieName ?? "nauth_csrf_token";
1580
- try {
1581
- const url = new URL(this.config.baseUrl);
1582
- document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${url.hostname}`;
1583
- document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
1584
- } catch {
1585
- document.cookie = `${csrfCookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
1586
- }
1587
- }
1588
- }
1589
- /**
1590
- * Logout all sessions.
1591
- *
1592
- * Revokes all active sessions for the current user across all devices.
1593
- * Optionally revokes all trusted devices if forgetDevices is true.
1594
- *
1595
- * @param forgetDevices - If true, also revokes all trusted devices (default: false)
1596
- * @returns Promise with number of sessions revoked
1597
- *
1598
- * @example
1599
- * ```typescript
1600
- * const result = await this.auth.logoutAll();
1601
- * console.log(`Revoked ${result.revokedCount} sessions`);
1602
- * ```
1603
- */
1604
- async logoutAll(forgetDevices) {
1605
- const res = await this.client.logoutAll(forgetDevices);
1606
- this.challengeSubject.next(null);
1607
- this.currentUserSubject.next(null);
1608
- this.isAuthenticatedSubject.next(false);
1609
- return res;
1610
- }
1611
- /**
1612
- * Refresh tokens.
1613
- *
1614
- * @returns Promise with new tokens
1615
- *
1616
- * @example
1617
- * ```typescript
1618
- * const tokens = await this.auth.refresh();
1619
- * ```
1620
- */
1621
- async refresh() {
1622
- return this.client.refreshTokens();
1623
- }
1624
- // ============================================================================
1625
- // Account Recovery (Forgot Password)
1626
- // ============================================================================
1627
- /**
1628
- * Request a password reset code (forgot password).
1629
- *
1630
- * @param identifier - User email, username, or phone
1631
- * @returns Promise with password reset response
1632
- *
1633
- * @example
1634
- * ```typescript
1635
- * await this.auth.forgotPassword('user@example.com');
1636
- * ```
1637
- */
1638
- async forgotPassword(identifier) {
1639
- return this.client.forgotPassword(identifier);
1640
- }
1641
- /**
1642
- * Confirm a password reset code and set a new password.
1643
- *
1644
- * @param identifier - User email, username, or phone
1645
- * @param code - One-time reset code
1646
- * @param newPassword - New password
1647
- * @returns Promise with confirmation response
1648
- *
1649
- * @example
1650
- * ```typescript
1651
- * await this.auth.confirmForgotPassword('user@example.com', '123456', 'NewPass123!');
1652
- * ```
1653
- */
1654
- async confirmForgotPassword(identifier, code, newPassword) {
1655
- return this.client.confirmForgotPassword(identifier, code, newPassword);
1656
- }
1657
- /**
1658
- * Change user password (requires current password).
1659
- *
1660
- * @param oldPassword - Current password
1661
- * @param newPassword - New password (must meet requirements)
1662
- * @returns Promise that resolves when password is changed
1663
- *
1664
- * @example
1665
- * ```typescript
1666
- * await this.auth.changePassword('oldPassword123', 'newSecurePassword456!');
1667
- * ```
1668
- */
1669
- async changePassword(oldPassword, newPassword) {
1670
- return this.client.changePassword(oldPassword, newPassword);
1671
- }
1672
- /**
1673
- * Request password change (must change on next login).
1674
- *
1675
- * @returns Promise that resolves when request is sent
1676
- *
1677
- * @example
1678
- * ```typescript
1679
- * await this.auth.requestPasswordChange();
1680
- * ```
1681
- */
1682
- async requestPasswordChange() {
1683
- return this.client.requestPasswordChange();
1684
- }
1685
- // ============================================================================
1686
- // Profile Management
1687
- // ============================================================================
1688
- /**
1689
- * Get current user profile.
1690
- *
1691
- * @returns Promise of current user profile
1692
- *
1693
- * @example
1694
- * ```typescript
1695
- * const user = await this.auth.getProfile();
1696
- * console.log('User profile:', user);
1697
- * ```
1698
- */
1699
- async getProfile() {
1700
- const user = await this.client.getProfile();
1701
- this.currentUserSubject.next(user);
1702
- return user;
1703
- }
1704
- /**
1705
- * Update user profile.
1706
- *
1707
- * @param updates - Profile fields to update
1708
- * @returns Promise of updated user profile
1709
- *
1710
- * @example
1711
- * ```typescript
1712
- * const user = await this.auth.updateProfile({ firstName: 'John', lastName: 'Doe' });
1713
- * console.log('Profile updated:', user);
1714
- * ```
1715
- */
1716
- async updateProfile(updates) {
1717
- const user = await this.client.updateProfile(updates);
1718
- this.currentUserSubject.next(user);
1719
- return user;
1720
- }
1721
- // ============================================================================
1722
- // Challenge Flow Methods (Essential for any auth flow)
1723
- // ============================================================================
1724
- /**
1725
- * Respond to a challenge (VERIFY_EMAIL, VERIFY_PHONE, MFA_REQUIRED, etc.).
1726
- *
1727
- * @param response - Challenge response data
1728
- * @returns Promise with auth response or next challenge
1729
- *
1730
- * @example
1731
- * ```typescript
1732
- * const result = await this.auth.respondToChallenge({
1733
- * session: challengeSession,
1734
- * type: 'VERIFY_EMAIL',
1735
- * code: '123456',
1736
- * });
1737
- * ```
1738
- */
1739
- async respondToChallenge(response) {
1740
- const res = await this.client.respondToChallenge(response);
1741
- return this.updateChallengeState(res);
1742
- }
1743
- /**
1744
- * Resend challenge code.
1745
- *
1746
- * @param session - Challenge session token
1747
- * @returns Promise with destination information
1748
- *
1749
- * @example
1750
- * ```typescript
1751
- * const result = await this.auth.resendCode(session);
1752
- * console.log('Code sent to:', result.destination);
1753
- * ```
1754
- */
1755
- async resendCode(session) {
1756
- return this.client.resendCode(session);
1757
- }
1758
- /**
1759
- * Get MFA setup data (for MFA_SETUP_REQUIRED challenge).
1760
- *
1761
- * Returns method-specific setup information:
1762
- * - TOTP: { secret, qrCode, manualEntryKey }
1763
- * - SMS: { maskedPhone }
1764
- * - Email: { maskedEmail }
1765
- * - Passkey: WebAuthn registration options
1766
- *
1767
- * @param session - Challenge session token
1768
- * @param method - MFA method to set up
1769
- * @returns Promise of setup data response
1770
- *
1771
- * @example
1772
- * ```typescript
1773
- * const setupData = await this.auth.getSetupData(session, 'totp');
1774
- * console.log('QR Code:', setupData.setupData.qrCode);
1775
- * ```
1776
- */
1777
- async getSetupData(session, method) {
1778
- return this.client.getSetupData(session, method);
1779
- }
1780
- /**
1781
- * Get MFA challenge data (for MFA_REQUIRED challenge - e.g., passkey options).
1782
- *
1783
- * @param session - Challenge session token
1784
- * @param method - Challenge method
1785
- * @returns Promise of challenge data response
1786
- *
1787
- * @example
1788
- * ```typescript
1789
- * const challengeData = await this.auth.getChallengeData(session, 'passkey');
1790
- * ```
1791
- */
1792
- async getChallengeData(session, method) {
1793
- return this.client.getChallengeData(session, method);
1794
- }
1795
- /**
1796
- * Clear stored challenge (when navigating away from challenge flow).
1797
- *
1798
- * @returns Promise that resolves when challenge is cleared
1799
- *
1800
- * @example
1801
- * ```typescript
1802
- * await this.auth.clearChallenge();
1803
- * ```
1804
- */
1805
- async clearChallenge() {
1806
- await this.client.clearStoredChallenge();
1807
- this.challengeSubject.next(null);
1808
- }
1809
- // ============================================================================
1810
- // Social Authentication
1811
- // ============================================================================
1812
- /**
1813
- * Initiate social OAuth login flow.
1814
- * Redirects the browser to backend `/auth/social/:provider/redirect`.
1815
- *
1816
- * @param provider - Social provider ('google', 'apple', 'facebook')
1817
- * @param options - Optional redirect options
1818
- * @returns Promise that resolves when redirect starts
1819
- *
1820
- * @example
1821
- * ```typescript
1822
- * await this.auth.loginWithSocial('google', { returnTo: '/auth/callback' });
1823
- * ```
1824
- */
1825
- async loginWithSocial(provider, options) {
1826
- return this.client.loginWithSocial(provider, options);
1827
- }
1828
- /**
1829
- * Exchange an exchangeToken (from redirect callback URL) into an AuthResponse.
1830
- *
1831
- * Used for `tokenDelivery: 'json'` or hybrid flows where the backend redirects back
1832
- * with `exchangeToken` instead of setting cookies.
1833
- *
1834
- * @param exchangeToken - One-time exchange token from the callback URL
1835
- * @returns Promise of AuthResponse
1836
- *
1837
- * @example
1838
- * ```typescript
1839
- * const response = await this.auth.exchangeSocialRedirect(exchangeToken);
1840
- * ```
1841
- */
1842
- async exchangeSocialRedirect(exchangeToken) {
1843
- const res = await this.client.exchangeSocialRedirect(exchangeToken);
1844
- return this.updateChallengeState(res);
1845
- }
1846
- /**
1847
- * Verify native social token (mobile).
1848
- *
1849
- * @param request - Social verification request with provider and token
1850
- * @returns Promise of AuthResponse
1851
- *
1852
- * @example
1853
- * ```typescript
1854
- * const result = await this.auth.verifyNativeSocial({
1855
- * provider: 'google',
1856
- * idToken: nativeIdToken,
1857
- * });
1858
- * ```
1859
- */
1860
- async verifyNativeSocial(request) {
1861
- const res = await this.client.verifyNativeSocial(request);
1862
- return this.updateChallengeState(res);
1863
- }
1864
- /**
1865
- * Get linked social accounts.
1866
- *
1867
- * @returns Promise of linked accounts response
1868
- *
1869
- * @example
1870
- * ```typescript
1871
- * const accounts = await this.auth.getLinkedAccounts();
1872
- * console.log('Linked providers:', accounts.providers);
1873
- * ```
1874
- */
1875
- async getLinkedAccounts() {
1876
- return this.client.getLinkedAccounts();
1877
- }
1878
- /**
1879
- * Link social account.
1880
- *
1881
- * @param provider - Social provider to link
1882
- * @param code - OAuth authorization code
1883
- * @param state - OAuth state parameter
1884
- * @returns Promise with success message
1885
- *
1886
- * @example
1887
- * ```typescript
1888
- * await this.auth.linkSocialAccount('google', code, state);
1889
- * ```
1890
- */
1891
- async linkSocialAccount(provider, code, state) {
1892
- return this.client.linkSocialAccount(provider, code, state);
1893
- }
1894
- /**
1895
- * Unlink social account.
1896
- *
1897
- * @param provider - Social provider to unlink
1898
- * @returns Promise with success message
1899
- *
1900
- * @example
1901
- * ```typescript
1902
- * await this.auth.unlinkSocialAccount('google');
1903
- * ```
1904
- */
1905
- async unlinkSocialAccount(provider) {
1906
- return this.client.unlinkSocialAccount(provider);
1907
- }
1908
- // ============================================================================
1909
- // MFA Management
1910
- // ============================================================================
1911
- /**
1912
- * Get MFA status for the current user.
1913
- *
1914
- * @returns Promise of MFA status
1915
- *
1916
- * @example
1917
- * ```typescript
1918
- * const status = await this.auth.getMfaStatus();
1919
- * console.log('MFA enabled:', status.enabled);
1920
- * ```
1921
- */
1922
- async getMfaStatus() {
1923
- return this.client.getMfaStatus();
1924
- }
1925
- /**
1926
- * Get MFA devices for the current user.
1927
- *
1928
- * @returns Promise of MFA devices array
1929
- *
1930
- * @example
1931
- * ```typescript
1932
- * const devices = await this.auth.getMfaDevices();
1933
- * ```
1934
- */
1935
- async getMfaDevices() {
1936
- return this.client.getMfaDevices();
1937
- }
1938
- /**
1939
- * Setup MFA device (authenticated user).
1940
- *
1941
- * @param method - MFA method to set up
1942
- * @returns Promise of setup data
1943
- *
1944
- * @example
1945
- * ```typescript
1946
- * const setupData = await this.auth.setupMfaDevice('totp');
1947
- * ```
1948
- */
1949
- async setupMfaDevice(method) {
1950
- return this.client.setupMfaDevice(method);
1951
- }
1952
- /**
1953
- * Verify MFA setup (authenticated user).
1954
- *
1955
- * @param method - MFA method
1956
- * @param setupData - Setup data from setupMfaDevice
1957
- * @param deviceName - Optional device name
1958
- * @returns Promise with device ID
1959
- *
1960
- * @example
1961
- * ```typescript
1962
- * const result = await this.auth.verifyMfaSetup('totp', { code: '123456' }, 'My Phone');
1963
- * ```
1964
- */
1965
- async verifyMfaSetup(method, setupData, deviceName) {
1966
- return this.client.verifyMfaSetup(method, setupData, deviceName);
1967
- }
1968
- /**
1969
- * Remove MFA device.
1970
- *
1971
- * @param method - MFA method to remove
1972
- * @returns Promise with success message
1973
- *
1974
- * @example
1975
- * ```typescript
1976
- * await this.auth.removeMfaDevice('sms');
1977
- * ```
1978
- */
1979
- async removeMfaDevice(method) {
1980
- return this.client.removeMfaDevice(method);
1981
- }
1982
- /**
1983
- * Set preferred MFA method.
1984
- *
1985
- * @param method - Device method to set as preferred ('totp', 'sms', 'email', or 'passkey')
1986
- * @returns Promise with success message
1987
- *
1988
- * @example
1989
- * ```typescript
1990
- * await this.auth.setPreferredMfaMethod('totp');
1991
- * ```
1992
- */
1993
- async setPreferredMfaMethod(method) {
1994
- return this.client.setPreferredMfaMethod(method);
1995
- }
1996
- /**
1997
- * Generate backup codes.
1998
- *
1999
- * @returns Promise of backup codes array
2000
- *
2001
- * @example
2002
- * ```typescript
2003
- * const codes = await this.auth.generateBackupCodes();
2004
- * console.log('Backup codes:', codes);
2005
- * ```
2006
- */
2007
- async generateBackupCodes() {
2008
- return this.client.generateBackupCodes();
2009
- }
2010
- /**
2011
- * Set MFA exemption (admin/test scenarios).
2012
- *
2013
- * @param exempt - Whether to exempt user from MFA
2014
- * @param reason - Optional reason for exemption
2015
- * @returns Promise that resolves when exemption is set
2016
- *
2017
- * @example
2018
- * ```typescript
2019
- * await this.auth.setMfaExemption(true, 'Test account');
2020
- * ```
2021
- */
2022
- async setMfaExemption(exempt, reason) {
2023
- return this.client.setMfaExemption(exempt, reason);
2024
- }
2025
- // ============================================================================
2026
- // Device Trust
2027
- // ============================================================================
2028
- /**
2029
- * Trust current device.
2030
- *
2031
- * @returns Promise with device token
2032
- *
2033
- * @example
2034
- * ```typescript
2035
- * const result = await this.auth.trustDevice();
2036
- * console.log('Device trusted:', result.deviceToken);
2037
- * ```
2038
- */
2039
- async trustDevice() {
2040
- return this.client.trustDevice();
2041
- }
2042
- /**
2043
- * Check if the current device is trusted.
2044
- *
2045
- * @returns Promise with trusted status
2046
- *
2047
- * @example
2048
- * ```typescript
2049
- * const result = await this.auth.isTrustedDevice();
2050
- * if (result.trusted) {
2051
- * console.log('This device is trusted');
2052
- * }
2053
- * ```
2054
- */
2055
- async isTrustedDevice() {
2056
- return this.client.isTrustedDevice();
2057
- }
2058
- // ============================================================================
2059
- // Audit History
2060
- // ============================================================================
2061
- /**
2062
- * Get paginated audit history for the current user.
2063
- *
2064
- * @param params - Query parameters for filtering and pagination
2065
- * @returns Promise of audit history response
2066
- *
2067
- * @example
2068
- * ```typescript
2069
- * const history = await this.auth.getAuditHistory({
2070
- * page: 1,
2071
- * limit: 20,
2072
- * eventType: 'LOGIN_SUCCESS'
2073
- * });
2074
- * console.log('Audit history:', history);
2075
- * ```
2076
- */
2077
- async getAuditHistory(params) {
2078
- return this.client.getAuditHistory(params);
2079
- }
2080
- // ============================================================================
2081
- // Escape Hatch
2082
- // ============================================================================
2083
- /**
2084
- * Expose underlying NAuthClient for advanced scenarios.
2085
- *
2086
- * @deprecated All core functionality is now exposed directly on AuthService as Promises.
2087
- * Use the direct methods on AuthService instead (e.g., `auth.changePassword()` instead of `auth.getClient().changePassword()`).
2088
- * This method is kept for backward compatibility only and may be removed in a future version.
2089
- *
2090
- * @returns The underlying NAuthClient instance
2091
- *
2092
- * @example
2093
- * ```typescript
2094
- * // Deprecated - use direct methods instead
2095
- * const status = await this.auth.getClient().getMfaStatus();
2096
- *
2097
- * // Preferred - use direct methods
2098
- * const status = await this.auth.getMfaStatus();
2099
- * ```
2100
- */
2101
- getClient() {
2102
- return this.client;
2103
- }
2104
- // ============================================================================
2105
- // Internal Methods
2106
- // ============================================================================
2107
- /**
2108
- * Initialize by hydrating state from storage.
2109
- * Called automatically on construction.
2110
- */
2111
- async initialize() {
2112
- if (this.initialized)
2113
- return;
2114
- this.initialized = true;
2115
- await this.client.initialize();
2116
- const storedChallenge = await this.client.getStoredChallenge();
2117
- if (storedChallenge) {
2118
- this.challengeSubject.next(storedChallenge);
2119
- }
2120
- const user = this.client.getCurrentUser();
2121
- if (user) {
2122
- this.currentUserSubject.next(user);
2123
- this.isAuthenticatedSubject.next(true);
2124
- }
2125
- }
2126
- /**
2127
- * Update challenge state after auth response.
2128
- */
2129
- updateChallengeState(response) {
2130
- if (response.challengeName) {
2131
- this.challengeSubject.next(response);
2132
- } else {
2133
- this.challengeSubject.next(null);
2134
- }
2135
- return response;
2136
- }
2137
- };
2138
- __name(_AuthService, "AuthService");
2139
- __publicField(_AuthService, "\u0275fac", i02.\u0275\u0275ngDeclareFactory({ minVersion: "12.0.0", version: "21.0.5", ngImport: i02, type: _AuthService, deps: [{ token: NAUTH_CLIENT_CONFIG, optional: true }], target: i02.\u0275\u0275FactoryTarget.Injectable }));
2140
- __publicField(_AuthService, "\u0275prov", i02.\u0275\u0275ngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.5", ngImport: i02, type: _AuthService, providedIn: "root" }));
2141
- var AuthService = _AuthService;
2142
- i02.\u0275\u0275ngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.5", ngImport: i02, type: AuthService, decorators: [{
2143
- type: import_core3.Injectable,
2144
- args: [{
2145
- providedIn: "root"
2146
- }]
2147
- }], ctorParameters: /* @__PURE__ */ __name(() => [{ type: void 0, decorators: [{
2148
- type: import_core3.Optional
2149
- }, {
2150
- type: import_core3.Inject,
2151
- args: [NAUTH_CLIENT_CONFIG]
2152
- }] }], "ctorParameters") });
2153
-
2154
- // tmp/ngc/angular/angular/auth.interceptor.js
2155
- var import_core4 = require("@angular/core");
2156
- var import_common = require("@angular/common");
2157
- var import_http2 = require("@angular/common/http");
2158
- var import_router = require("@angular/router");
2159
- var import_rxjs3 = require("rxjs");
2160
- var isRefreshing = false;
2161
- var refreshTokenSubject = new import_rxjs3.BehaviorSubject(null);
2162
- var retriedRequests = /* @__PURE__ */ new WeakSet();
2163
- function getCsrfToken(cookieName) {
2164
- if (typeof document === "undefined")
2165
- return null;
2166
- const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
2167
- return match ? decodeURIComponent(match[2]) : null;
2168
- }
2169
- __name(getCsrfToken, "getCsrfToken");
2170
- var authInterceptor = /* @__PURE__ */ __name((req, next) => {
2171
- const config = (0, import_core4.inject)(NAUTH_CLIENT_CONFIG);
2172
- const http = (0, import_core4.inject)(import_http2.HttpClient);
2173
- const authService = (0, import_core4.inject)(AuthService);
2174
- const platformId = (0, import_core4.inject)(import_core4.PLATFORM_ID);
2175
- const router = (0, import_core4.inject)(import_router.Router);
2176
- const isBrowser = (0, import_common.isPlatformBrowser)(platformId);
2177
- if (!isBrowser) {
2178
- return next(req);
2179
- }
2180
- const tokenDelivery = config.tokenDelivery;
2181
- const baseUrl = config.baseUrl;
2182
- const endpoints = config.endpoints ?? {};
2183
- const refreshPath = endpoints.refresh ?? "/refresh";
2184
- const loginPath = endpoints.login ?? "/login";
2185
- const signupPath = endpoints.signup ?? "/signup";
2186
- const socialExchangePath = endpoints.socialExchange ?? "/social/exchange";
2187
- const refreshUrl = `${baseUrl}${refreshPath}`;
2188
- const isAuthApiRequest = req.url.includes(baseUrl);
2189
- const isRefreshEndpoint = req.url.includes(refreshPath);
2190
- const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
2191
- let authReq = req;
2192
- if (tokenDelivery === "cookies") {
2193
- authReq = authReq.clone({ withCredentials: true });
2194
- if (["POST", "PUT", "PATCH", "DELETE"].includes(req.method)) {
2195
- const csrfCookieName = config.csrf?.cookieName ?? "nauth_csrf_token";
2196
- const csrfHeaderName = config.csrf?.headerName ?? "x-csrf-token";
2197
- const csrfToken = getCsrfToken(csrfCookieName);
2198
- if (csrfToken) {
2199
- authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });
2200
- }
2201
- }
2202
- }
2203
- return next(authReq).pipe((0, import_rxjs3.catchError)((error) => {
2204
- const shouldHandle = error instanceof import_http2.HttpErrorResponse && error.status === 401 && isAuthApiRequest && !isRefreshEndpoint && !isPublicEndpoint && !retriedRequests.has(req);
2205
- if (!shouldHandle) {
2206
- return (0, import_rxjs3.throwError)(() => error);
2207
- }
2208
- if (config.debug) {
2209
- console.warn("[nauth-interceptor] 401 detected:", req.url);
2210
- }
2211
- if (!isRefreshing) {
2212
- isRefreshing = true;
2213
- refreshTokenSubject.next(null);
2214
- if (config.debug) {
2215
- console.warn("[nauth-interceptor] Starting refresh...");
2216
- }
2217
- const refresh$ = tokenDelivery === "cookies" ? http.post(refreshUrl, {}, { withCredentials: true }) : (0, import_rxjs3.from)(authService.refresh());
2218
- return refresh$.pipe((0, import_rxjs3.switchMap)((response) => {
2219
- if (config.debug) {
2220
- console.warn("[nauth-interceptor] Refresh successful");
2221
- }
2222
- isRefreshing = false;
2223
- const newToken = "accessToken" in response ? response.accessToken : "success";
2224
- refreshTokenSubject.next(newToken ?? "success");
2225
- const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken);
2226
- retriedRequests.add(retryReq);
2227
- if (config.debug) {
2228
- console.warn("[nauth-interceptor] Retrying:", req.url);
2229
- }
2230
- return next(retryReq);
2231
- }), (0, import_rxjs3.catchError)((err) => {
2232
- if (config.debug) {
2233
- console.error("[nauth-interceptor] Refresh failed:", err);
2234
- }
2235
- isRefreshing = false;
2236
- refreshTokenSubject.next(null);
2237
- if (config.redirects?.sessionExpired) {
2238
- router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
2239
- if (config.debug) {
2240
- console.error("[nauth-interceptor] Navigation failed:", navError);
2241
- }
2242
- });
2243
- }
2244
- return (0, import_rxjs3.throwError)(() => err);
2245
- }));
2246
- } else {
2247
- if (config.debug) {
2248
- console.warn("[nauth-interceptor] Waiting for refresh...");
2249
- }
2250
- return refreshTokenSubject.pipe((0, import_rxjs3.filter)((token) => token !== null), (0, import_rxjs3.take)(1), (0, import_rxjs3.switchMap)((token) => {
2251
- if (config.debug) {
2252
- console.warn("[nauth-interceptor] Refresh done, retrying:", req.url);
2253
- }
2254
- const retryReq = buildRetryRequest(authReq, tokenDelivery, token);
2255
- retriedRequests.add(retryReq);
2256
- return next(retryReq);
2257
- }));
2258
- }
2259
- }));
2260
- }, "authInterceptor");
2261
- function buildRetryRequest(originalReq, tokenDelivery, newToken) {
2262
- if (tokenDelivery === "json" && newToken && newToken !== "success") {
2263
- return originalReq.clone({
2264
- setHeaders: { Authorization: `Bearer ${newToken}` }
2265
- });
2266
- }
2267
- return originalReq.clone();
2268
- }
2269
- __name(buildRetryRequest, "buildRetryRequest");
2270
- var _AuthInterceptor = class _AuthInterceptor {
2271
- intercept(req, next) {
2272
- return authInterceptor(req, next);
2273
- }
2274
- };
2275
- __name(_AuthInterceptor, "AuthInterceptor");
2276
- var AuthInterceptor = _AuthInterceptor;
2277
-
2278
- // tmp/ngc/angular/angular/auth.guard.js
2279
- var import_core5 = require("@angular/core");
2280
- var import_router2 = require("@angular/router");
2281
- function authGuard(redirectTo = "/login") {
2282
- return () => {
2283
- const auth = (0, import_core5.inject)(AuthService);
2284
- const router = (0, import_core5.inject)(import_router2.Router);
2285
- if (auth.isAuthenticated()) {
2286
- return true;
2287
- }
2288
- return router.createUrlTree([redirectTo]);
2289
- };
2290
- }
2291
- __name(authGuard, "authGuard");
2292
- var _AuthGuard = class _AuthGuard {
2293
- /**
2294
- * @param auth - Authentication service
2295
- * @param router - Angular router
2296
- */
2297
- constructor(auth, router) {
2298
- __publicField(this, "auth");
2299
- __publicField(this, "router");
2300
- this.auth = auth;
2301
- this.router = router;
2302
- }
2303
- /**
2304
- * Check if route can be activated.
2305
- *
2306
- * @returns True if authenticated, otherwise redirects to login
2307
- */
2308
- canActivate() {
2309
- if (this.auth.isAuthenticated()) {
2310
- return true;
2311
- }
2312
- return this.router.createUrlTree(["/login"]);
2313
- }
2314
- };
2315
- __name(_AuthGuard, "AuthGuard");
2316
- var AuthGuard = _AuthGuard;
2317
-
2318
- // tmp/ngc/angular/angular/social-redirect-callback.guard.js
2319
- var import_core6 = require("@angular/core");
2320
- var import_common2 = require("@angular/common");
2321
- var socialRedirectCallbackGuard = /* @__PURE__ */ __name(async () => {
2322
- const auth = (0, import_core6.inject)(AuthService);
2323
- const config = (0, import_core6.inject)(NAUTH_CLIENT_CONFIG);
2324
- const platformId = (0, import_core6.inject)(import_core6.PLATFORM_ID);
2325
- const isBrowser = (0, import_common2.isPlatformBrowser)(platformId);
2326
- if (!isBrowser) {
2327
- return false;
2328
- }
2329
- const params = new URLSearchParams(window.location.search);
2330
- const error = params.get("error");
2331
- const exchangeToken = params.get("exchangeToken");
2332
- if (error) {
2333
- const errorUrl = config.redirects?.oauthError || "/login";
2334
- window.location.replace(errorUrl);
2335
- return false;
2336
- }
2337
- if (!exchangeToken) {
2338
- try {
2339
- await auth.getProfile();
2340
- } catch {
2341
- const errorUrl = config.redirects?.oauthError || "/login";
2342
- window.location.replace(errorUrl);
2343
- return false;
2344
- }
2345
- const successUrl2 = config.redirects?.success || "/";
2346
- window.location.replace(successUrl2);
2347
- return false;
2348
- }
2349
- const response = await auth.exchangeSocialRedirect(exchangeToken);
2350
- if (response.challengeName) {
2351
- const challengeBase = config.redirects?.challengeBase || "/auth/challenge";
2352
- const challengeRoute = response.challengeName.toLowerCase().replace(/_/g, "-");
2353
- window.location.replace(`${challengeBase}/${challengeRoute}`);
2354
- return false;
2355
- }
2356
- const successUrl = config.redirects?.success || "/";
2357
- window.location.replace(successUrl);
2358
- return false;
2359
- }, "socialRedirectCallbackGuard");
2360
-
2361
- // tmp/ngc/angular/angular/auth.module.js
2362
- var import_core7 = require("@angular/core");
2363
- var import_http3 = require("@angular/common/http");
2364
- var i03 = __toESM(require("@angular/core"));
2365
- var _NAuthModule = class _NAuthModule {
2366
- /**
2367
- * Configure the module with client settings.
2368
- *
2369
- * @param config - Client configuration
2370
- */
2371
- static forRoot(config) {
2372
- return {
2373
- ngModule: _NAuthModule,
2374
- providers: [
2375
- { provide: NAUTH_CLIENT_CONFIG, useValue: config },
2376
- { provide: import_http3.HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
2377
- ]
2378
- };
2379
- }
2380
- };
2381
- __name(_NAuthModule, "NAuthModule");
2382
- __publicField(_NAuthModule, "\u0275fac", i03.\u0275\u0275ngDeclareFactory({ minVersion: "12.0.0", version: "21.0.5", ngImport: i03, type: _NAuthModule, deps: [], target: i03.\u0275\u0275FactoryTarget.NgModule }));
2383
- __publicField(_NAuthModule, "\u0275mod", i03.\u0275\u0275ngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.5", ngImport: i03, type: _NAuthModule }));
2384
- __publicField(_NAuthModule, "\u0275inj", i03.\u0275\u0275ngDeclareInjector({ minVersion: "12.0.0", version: "21.0.5", ngImport: i03, type: _NAuthModule }));
2385
- var NAuthModule = _NAuthModule;
2386
- i03.\u0275\u0275ngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.5", ngImport: i03, type: NAuthModule, decorators: [{
2387
- type: import_core7.NgModule,
2388
- args: [{}]
2389
- }] });
2390
- // Annotate the CommonJS export names for ESM import in node:
2391
- 0 && (module.exports = {
2392
- AngularHttpAdapter,
2393
- AuthGuard,
2394
- AuthInterceptor,
2395
- AuthService,
2396
- NAUTH_CLIENT_CONFIG,
2397
- NAuthModule,
2398
- authGuard,
2399
- authInterceptor,
2400
- socialRedirectCallbackGuard
2401
- });
2402
- //# sourceMappingURL=index.cjs.map