@classic-homes/auth 0.1.0

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.
@@ -0,0 +1,631 @@
1
+ import { L as LoginCredentials, a as LoginResponse, R as RegisterData, b as RegisterResponse, U as User, j as ProfileUpdateData, k as ChangePasswordData, S as Session, c as ApiKey, C as CreateApiKeyRequest, d as CreateApiKeyResponse, e as MFAStatus, M as MFASetupResponse, f as MFAChallengeData, D as Device, g as UserPreferences, h as LinkedAccount, i as SecurityEvent, P as Pagination } from '../types-exFUQyBX.js';
2
+ export { A as AuthState, l as ResetPasswordData } from '../types-exFUQyBX.js';
3
+
4
+ /**
5
+ * Auth Configuration
6
+ *
7
+ * Manages global configuration for the auth package.
8
+ * Must be initialized via initAuth() before using auth services.
9
+ */
10
+ interface SSOConfig {
11
+ /** Whether SSO is enabled */
12
+ enabled: boolean;
13
+ /** SSO provider name (e.g., 'authentik', 'okta') */
14
+ provider: string;
15
+ /** Override the default authorize URL (defaults to /auth/sso/authorize) */
16
+ authorizeUrl?: string;
17
+ }
18
+ interface StorageAdapter {
19
+ getItem(key: string): string | null;
20
+ setItem(key: string, value: string): void;
21
+ removeItem(key: string): void;
22
+ }
23
+ interface AuthConfig {
24
+ /** Base URL for the API (e.g., 'https://api.example.com/v1') */
25
+ baseUrl: string;
26
+ /** Custom fetch implementation (useful for SSR or testing) */
27
+ fetch?: typeof fetch;
28
+ /** Storage adapter for token persistence (defaults to localStorage in browser) */
29
+ storage?: StorageAdapter;
30
+ /** Storage key prefix for auth data */
31
+ storageKey?: string;
32
+ /** Callback when auth errors occur (e.g., for logging or analytics) */
33
+ onAuthError?: (error: Error) => void;
34
+ /** Callback when tokens are refreshed */
35
+ onTokenRefresh?: (tokens: {
36
+ accessToken: string;
37
+ refreshToken: string;
38
+ }) => void;
39
+ /** Callback when user is logged out (e.g., for redirect) */
40
+ onLogout?: () => void;
41
+ /** SSO configuration */
42
+ sso?: SSOConfig;
43
+ }
44
+ /**
45
+ * Initialize the auth package with configuration.
46
+ * Must be called before using any auth services.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { initAuth } from '@classic-homes/auth';
51
+ *
52
+ * initAuth({
53
+ * baseUrl: import.meta.env.PUBLIC_API_URL,
54
+ * sso: {
55
+ * enabled: true,
56
+ * provider: 'authentik',
57
+ * },
58
+ * });
59
+ * ```
60
+ */
61
+ declare function initAuth(options: AuthConfig): void;
62
+ /**
63
+ * Get the current auth configuration.
64
+ * Throws if initAuth() has not been called.
65
+ */
66
+ declare function getConfig(): AuthConfig;
67
+ /**
68
+ * Check if auth has been initialized.
69
+ */
70
+ declare function isInitialized(): boolean;
71
+ /**
72
+ * Reset the auth configuration (useful for testing).
73
+ */
74
+ declare function resetConfig(): void;
75
+ /**
76
+ * Get the default storage adapter.
77
+ * Returns localStorage in browser, or a no-op adapter in SSR.
78
+ */
79
+ declare function getDefaultStorage(): StorageAdapter;
80
+ /**
81
+ * Get the storage adapter from config or use default.
82
+ */
83
+ declare function getStorage(): StorageAdapter;
84
+ /**
85
+ * Get the fetch implementation from config or use global fetch.
86
+ */
87
+ declare function getFetch(): typeof fetch;
88
+
89
+ /**
90
+ * HTTP Client
91
+ *
92
+ * A configurable HTTP client for making API requests.
93
+ * Handles authentication headers, token refresh, and error handling.
94
+ */
95
+ interface ApiRequestOptions extends Omit<RequestInit, 'body'> {
96
+ /** Whether to include auth headers */
97
+ authenticated?: boolean;
98
+ /** Custom fetch implementation for this request */
99
+ customFetch?: typeof fetch;
100
+ /** Request body (will be JSON stringified) */
101
+ body?: unknown;
102
+ }
103
+ interface ApiResponse<T = unknown> {
104
+ data?: T;
105
+ meta?: {
106
+ status: string;
107
+ message?: string;
108
+ };
109
+ error?: {
110
+ message: string;
111
+ code?: string;
112
+ };
113
+ }
114
+ /**
115
+ * Get the current access token from storage.
116
+ */
117
+ declare function getAccessToken(): string | null;
118
+ /**
119
+ * Get the current refresh token from storage.
120
+ */
121
+ declare function getRefreshToken(): string | null;
122
+ /**
123
+ * Get the session token from storage.
124
+ */
125
+ declare function getSessionToken(): string | null;
126
+ /**
127
+ * Update stored tokens.
128
+ */
129
+ declare function updateStoredTokens(accessToken: string, refreshToken: string): void;
130
+ /**
131
+ * Clear stored auth data.
132
+ */
133
+ declare function clearStoredAuth(): void;
134
+ /**
135
+ * Helper to extract data from CHAPI response wrapper.
136
+ */
137
+ declare function extractData<T>(response: {
138
+ data?: {
139
+ data?: T;
140
+ } | T;
141
+ } | T): T;
142
+ /**
143
+ * Make an API request.
144
+ */
145
+ declare function apiRequest<T = unknown>(endpoint: string, options?: ApiRequestOptions): Promise<ApiResponse<T>>;
146
+ /**
147
+ * Convenience methods for common HTTP methods.
148
+ */
149
+ declare const api: {
150
+ get: <T = unknown>(endpoint: string, authenticated?: boolean, customFetch?: typeof fetch) => Promise<ApiResponse<T>>;
151
+ post: <T = unknown>(endpoint: string, body: unknown, authenticated?: boolean, customFetch?: typeof fetch) => Promise<ApiResponse<T>>;
152
+ put: <T = unknown>(endpoint: string, body: unknown, authenticated?: boolean, customFetch?: typeof fetch) => Promise<ApiResponse<T>>;
153
+ patch: <T = unknown>(endpoint: string, body: unknown, authenticated?: boolean, customFetch?: typeof fetch) => Promise<ApiResponse<T>>;
154
+ delete: <T = unknown>(endpoint: string, authenticated?: boolean, customFetch?: typeof fetch, body?: unknown) => Promise<ApiResponse<T>>;
155
+ };
156
+
157
+ /**
158
+ * Auth API
159
+ *
160
+ * API client methods for authentication endpoints.
161
+ */
162
+
163
+ declare const authApi: {
164
+ /**
165
+ * Login with username and password.
166
+ */
167
+ login(credentials: LoginCredentials): Promise<LoginResponse>;
168
+ /**
169
+ * Logout the current user.
170
+ */
171
+ logout(): Promise<void>;
172
+ /**
173
+ * Register a new user.
174
+ */
175
+ register(data: RegisterData): Promise<RegisterResponse>;
176
+ /**
177
+ * Request a password reset email.
178
+ */
179
+ forgotPassword(email: string): Promise<void>;
180
+ /**
181
+ * Reset password with a token.
182
+ */
183
+ resetPassword(token: string, newPassword: string): Promise<void>;
184
+ /**
185
+ * Refresh the access token.
186
+ */
187
+ refreshToken(refreshToken: string): Promise<{
188
+ accessToken: string;
189
+ refreshToken: string;
190
+ }>;
191
+ /**
192
+ * Initiate SSO login by redirecting to the SSO provider.
193
+ */
194
+ initiateSSOLogin(): void;
195
+ /**
196
+ * Get the current user's profile.
197
+ */
198
+ getProfile(customFetch?: typeof fetch): Promise<User>;
199
+ /**
200
+ * Update the current user's profile.
201
+ */
202
+ updateProfile(data: ProfileUpdateData): Promise<User>;
203
+ /**
204
+ * Change the current user's password.
205
+ */
206
+ changePassword(data: ChangePasswordData): Promise<void>;
207
+ /**
208
+ * Resend email verification.
209
+ */
210
+ resendVerification(): Promise<void>;
211
+ /**
212
+ * Verify email with a token.
213
+ */
214
+ verifyEmail(token: string): Promise<{
215
+ message: string;
216
+ user?: User;
217
+ }>;
218
+ /**
219
+ * Get all active sessions.
220
+ */
221
+ getSessions(customFetch?: typeof fetch): Promise<{
222
+ sessions: Session[];
223
+ total: number;
224
+ }>;
225
+ /**
226
+ * Revoke a specific session.
227
+ */
228
+ revokeSession(sessionId: string): Promise<void>;
229
+ /**
230
+ * Revoke all sessions except the current one.
231
+ */
232
+ revokeAllSessions(): Promise<void>;
233
+ /**
234
+ * Get all API keys.
235
+ */
236
+ getApiKeys(customFetch?: typeof fetch): Promise<{
237
+ apiKeys: ApiKey[];
238
+ }>;
239
+ /**
240
+ * Create a new API key.
241
+ */
242
+ createApiKey(data: CreateApiKeyRequest): Promise<CreateApiKeyResponse>;
243
+ /**
244
+ * Revoke an API key.
245
+ */
246
+ revokeApiKey(keyId: string): Promise<void>;
247
+ /**
248
+ * Update an API key's name.
249
+ */
250
+ updateApiKey(keyId: string, data: {
251
+ name: string;
252
+ }): Promise<void>;
253
+ /**
254
+ * Get MFA status for the current user.
255
+ */
256
+ getMFAStatus(): Promise<MFAStatus>;
257
+ /**
258
+ * Setup MFA (get QR code and backup codes).
259
+ */
260
+ setupMFA(): Promise<MFASetupResponse>;
261
+ /**
262
+ * Verify MFA setup with a code.
263
+ */
264
+ verifyMFASetup(code: string): Promise<void>;
265
+ /**
266
+ * Disable MFA.
267
+ */
268
+ disableMFA(password: string): Promise<void>;
269
+ /**
270
+ * Regenerate MFA backup codes.
271
+ */
272
+ regenerateBackupCodes(password: string): Promise<{
273
+ backupCodes: string[];
274
+ }>;
275
+ /**
276
+ * Verify MFA challenge during login.
277
+ */
278
+ verifyMFAChallenge(data: MFAChallengeData): Promise<LoginResponse>;
279
+ /**
280
+ * Get all devices.
281
+ */
282
+ getDevices(customFetch?: typeof fetch): Promise<{
283
+ devices: Device[];
284
+ }>;
285
+ /**
286
+ * Trust a device.
287
+ */
288
+ trustDevice(deviceId: string): Promise<void>;
289
+ /**
290
+ * Revoke device trust.
291
+ */
292
+ revokeDevice(deviceId: string): Promise<void>;
293
+ /**
294
+ * Remove a device completely.
295
+ */
296
+ removeDevice(deviceId: string): Promise<void>;
297
+ /**
298
+ * Approve a device with a token.
299
+ */
300
+ approveDevice(token: string): Promise<{
301
+ message: string;
302
+ device?: Device;
303
+ }>;
304
+ /**
305
+ * Block a device with a token.
306
+ */
307
+ blockDevice(token: string): Promise<{
308
+ message: string;
309
+ device?: Device;
310
+ }>;
311
+ /**
312
+ * Get user preferences.
313
+ */
314
+ getPreferences(customFetch?: typeof fetch): Promise<UserPreferences>;
315
+ /**
316
+ * Update user preferences.
317
+ */
318
+ updatePreferences(data: Partial<UserPreferences>): Promise<void>;
319
+ /**
320
+ * Get SSO linked accounts.
321
+ */
322
+ getSSOAccounts(customFetch?: typeof fetch): Promise<LinkedAccount[]>;
323
+ /**
324
+ * Unlink an SSO account.
325
+ */
326
+ unlinkSSOAccount(provider: string, password?: string): Promise<void>;
327
+ /**
328
+ * Link an SSO account (redirects to SSO provider).
329
+ */
330
+ linkSSOAccount(provider?: string): Promise<void>;
331
+ /**
332
+ * Get security event history.
333
+ */
334
+ getSecurityEvents(params?: {
335
+ page?: number;
336
+ limit?: number;
337
+ type?: string;
338
+ }, customFetch?: typeof fetch): Promise<{
339
+ events: SecurityEvent[];
340
+ pagination: Pagination;
341
+ }>;
342
+ };
343
+
344
+ /**
345
+ * Auth Service
346
+ *
347
+ * Business logic layer for authentication operations.
348
+ * Wraps authApi calls and provides a clean interface for components.
349
+ */
350
+
351
+ /**
352
+ * AuthService
353
+ *
354
+ * Provides a clean interface for authentication operations.
355
+ * Can be instantiated for testing or used via the singleton export.
356
+ */
357
+ declare class AuthService {
358
+ /**
359
+ * Login with username and password.
360
+ */
361
+ login(credentials: LoginCredentials): Promise<LoginResponse>;
362
+ /**
363
+ * Logout the current user.
364
+ */
365
+ logout(): Promise<void>;
366
+ /**
367
+ * Register a new user.
368
+ */
369
+ register(data: RegisterData): Promise<RegisterResponse>;
370
+ /**
371
+ * Request a password reset email.
372
+ */
373
+ forgotPassword(email: string): Promise<void>;
374
+ /**
375
+ * Reset password with a token.
376
+ */
377
+ resetPassword(token: string, newPassword: string): Promise<void>;
378
+ /**
379
+ * Change the current user's password.
380
+ */
381
+ changePassword(currentPassword: string, newPassword: string): Promise<void>;
382
+ /**
383
+ * Refresh the access token.
384
+ */
385
+ refreshToken(refreshToken: string): Promise<{
386
+ accessToken: string;
387
+ refreshToken: string;
388
+ }>;
389
+ /**
390
+ * Initiate SSO login (redirects to SSO provider).
391
+ */
392
+ initiateSSOLogin(): void;
393
+ /**
394
+ * Get the current user's profile.
395
+ */
396
+ getProfile(customFetch?: typeof fetch): Promise<User>;
397
+ /**
398
+ * Update the current user's profile.
399
+ */
400
+ updateProfile(data: ProfileUpdateData): Promise<User>;
401
+ /**
402
+ * Resend email verification.
403
+ */
404
+ resendVerification(): Promise<void>;
405
+ /**
406
+ * Verify email with a token.
407
+ */
408
+ verifyEmail(token: string): Promise<{
409
+ message: string;
410
+ user?: User;
411
+ }>;
412
+ /**
413
+ * Get all active sessions.
414
+ */
415
+ getSessions(customFetch?: typeof fetch): Promise<{
416
+ sessions: Session[];
417
+ total: number;
418
+ }>;
419
+ /**
420
+ * Revoke a specific session.
421
+ */
422
+ revokeSession(sessionId: string): Promise<void>;
423
+ /**
424
+ * Revoke all sessions except the current one.
425
+ */
426
+ revokeAllSessions(): Promise<void>;
427
+ /**
428
+ * Get all API keys.
429
+ */
430
+ getApiKeys(customFetch?: typeof fetch): Promise<{
431
+ apiKeys: ApiKey[];
432
+ }>;
433
+ /**
434
+ * Create a new API key.
435
+ */
436
+ createApiKey(data: CreateApiKeyRequest): Promise<CreateApiKeyResponse>;
437
+ /**
438
+ * Revoke an API key.
439
+ */
440
+ revokeApiKey(keyId: string): Promise<void>;
441
+ /**
442
+ * Update an API key's name.
443
+ */
444
+ updateApiKey(keyId: string, name: string): Promise<void>;
445
+ /**
446
+ * Get MFA status for the current user.
447
+ */
448
+ getMFAStatus(): Promise<MFAStatus>;
449
+ /**
450
+ * Setup MFA (get QR code and backup codes).
451
+ */
452
+ setupMFA(): Promise<MFASetupResponse>;
453
+ /**
454
+ * Verify MFA setup with a code.
455
+ */
456
+ verifyMFASetup(code: string): Promise<void>;
457
+ /**
458
+ * Disable MFA.
459
+ */
460
+ disableMFA(password: string): Promise<void>;
461
+ /**
462
+ * Regenerate MFA backup codes.
463
+ */
464
+ regenerateBackupCodes(password: string): Promise<{
465
+ backupCodes: string[];
466
+ }>;
467
+ /**
468
+ * Verify MFA challenge during login.
469
+ */
470
+ verifyMFAChallenge(data: MFAChallengeData): Promise<LoginResponse>;
471
+ /**
472
+ * Get all devices.
473
+ */
474
+ getDevices(customFetch?: typeof fetch): Promise<{
475
+ devices: Device[];
476
+ }>;
477
+ /**
478
+ * Trust a device.
479
+ */
480
+ trustDevice(deviceId: string): Promise<void>;
481
+ /**
482
+ * Revoke device trust.
483
+ */
484
+ revokeDevice(deviceId: string): Promise<void>;
485
+ /**
486
+ * Remove a device completely.
487
+ */
488
+ removeDevice(deviceId: string): Promise<void>;
489
+ /**
490
+ * Approve a device with a token.
491
+ */
492
+ approveDevice(token: string): Promise<{
493
+ message: string;
494
+ device?: Device;
495
+ }>;
496
+ /**
497
+ * Block a device with a token.
498
+ */
499
+ blockDevice(token: string): Promise<{
500
+ message: string;
501
+ device?: Device;
502
+ }>;
503
+ /**
504
+ * Get user preferences.
505
+ */
506
+ getPreferences(customFetch?: typeof fetch): Promise<UserPreferences>;
507
+ /**
508
+ * Update user preferences.
509
+ */
510
+ updatePreferences(data: Partial<UserPreferences>): Promise<void>;
511
+ /**
512
+ * Get SSO linked accounts.
513
+ */
514
+ getLinkedAccounts(customFetch?: typeof fetch): Promise<LinkedAccount[]>;
515
+ /**
516
+ * Link an SSO account (redirects to SSO provider).
517
+ */
518
+ linkAccount(provider?: string): Promise<void>;
519
+ /**
520
+ * Unlink an SSO account.
521
+ */
522
+ unlinkAccount(provider: string, password?: string): Promise<void>;
523
+ /**
524
+ * Get security event history.
525
+ */
526
+ getSecurityEvents(params?: {
527
+ page?: number;
528
+ limit?: number;
529
+ type?: string;
530
+ }, customFetch?: typeof fetch): Promise<{
531
+ events: SecurityEvent[];
532
+ pagination: Pagination;
533
+ }>;
534
+ }
535
+ /** Singleton instance of AuthService */
536
+ declare const authService: AuthService;
537
+
538
+ /**
539
+ * JWT Utilities
540
+ *
541
+ * Simple JWT decoder utilities for extracting payload data.
542
+ * Note: These functions do NOT verify signatures - they only extract payloads.
543
+ */
544
+ interface JWTPayload {
545
+ /** Subject (usually user ID) */
546
+ sub: string;
547
+ email?: string;
548
+ username?: string;
549
+ roles?: string[];
550
+ permissions?: string[];
551
+ /** Expiration time (Unix timestamp in seconds) */
552
+ exp?: number;
553
+ /** Issued at time (Unix timestamp in seconds) */
554
+ iat?: number;
555
+ /** Additional claims */
556
+ [key: string]: unknown;
557
+ }
558
+ /**
559
+ * Decode a JWT token and extract its payload.
560
+ *
561
+ * @param token - The JWT token string
562
+ * @returns The decoded payload, or null if decoding fails
563
+ *
564
+ * @example
565
+ * ```typescript
566
+ * const payload = decodeJWT(accessToken);
567
+ * if (payload) {
568
+ * console.log('User ID:', payload.sub);
569
+ * console.log('Expires:', new Date(payload.exp! * 1000));
570
+ * }
571
+ * ```
572
+ */
573
+ declare function decodeJWT(token: string): JWTPayload | null;
574
+ /**
575
+ * Check if a JWT token is expired.
576
+ *
577
+ * @param token - The JWT token string
578
+ * @returns true if the token is expired or invalid, false otherwise
579
+ *
580
+ * @example
581
+ * ```typescript
582
+ * if (isTokenExpired(accessToken)) {
583
+ * // Token needs refresh
584
+ * }
585
+ * ```
586
+ */
587
+ declare function isTokenExpired(token: string): boolean;
588
+ /**
589
+ * Get the remaining time until a JWT token expires.
590
+ *
591
+ * @param token - The JWT token string
592
+ * @returns Remaining time in milliseconds, or 0 if expired/invalid
593
+ *
594
+ * @example
595
+ * ```typescript
596
+ * const remaining = getTokenRemainingTime(accessToken);
597
+ * console.log(`Token expires in ${remaining / 1000} seconds`);
598
+ * ```
599
+ */
600
+ declare function getTokenRemainingTime(token: string): number;
601
+ /**
602
+ * Get the expiration date of a JWT token.
603
+ *
604
+ * @param token - The JWT token string
605
+ * @returns The expiration Date, or null if no expiration or invalid token
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * const expiry = getTokenExpiration(accessToken);
610
+ * if (expiry) {
611
+ * console.log(`Token expires at ${expiry.toISOString()}`);
612
+ * }
613
+ * ```
614
+ */
615
+ declare function getTokenExpiration(token: string): Date | null;
616
+ /**
617
+ * Extract specific claims from a JWT token.
618
+ *
619
+ * @param token - The JWT token string
620
+ * @param claims - Array of claim names to extract
621
+ * @returns Object with requested claims, or null if token is invalid
622
+ *
623
+ * @example
624
+ * ```typescript
625
+ * const claims = extractClaims(token, ['sub', 'roles', 'permissions']);
626
+ * // { sub: '123', roles: ['admin'], permissions: ['read', 'write'] }
627
+ * ```
628
+ */
629
+ declare function extractClaims<T extends string>(token: string, claims: T[]): Pick<JWTPayload, T> | null;
630
+
631
+ export { ApiKey, type ApiRequestOptions, type ApiResponse, type AuthConfig, AuthService, ChangePasswordData, CreateApiKeyRequest, CreateApiKeyResponse, Device, type JWTPayload, LinkedAccount, LoginCredentials, LoginResponse, MFAChallengeData, MFASetupResponse, MFAStatus, Pagination, ProfileUpdateData, RegisterData, RegisterResponse, type SSOConfig, SecurityEvent, Session, type StorageAdapter, User, UserPreferences, api, apiRequest, authApi, authService, clearStoredAuth, decodeJWT, extractClaims, extractData, getAccessToken, getConfig, getDefaultStorage, getFetch, getRefreshToken, getSessionToken, getStorage, getTokenExpiration, getTokenRemainingTime, initAuth, isInitialized, isTokenExpired, resetConfig, updateStoredTokens };