say-auth 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,45 @@
1
+ # Changelog
2
+
3
+ ## [1.1.0] - 2024-01-XX
4
+
5
+ ### Added
6
+ - New `useAuthContext` hook for better React 19 compatibility
7
+ - Added `LoginForm` component with built-in validation
8
+ - Added `MFAVerification` component for 2FA flows
9
+ - Added `SessionWarning` component for session expiry notifications
10
+ - Added `setupAuthInterceptors` for automatic token refresh
11
+ - Added environment validation utilities
12
+ - Added error tracking integration support
13
+ - Added security headers utility
14
+ - Added comprehensive TypeScript types
15
+
16
+ ### Changed
17
+ - Improved React 16.8+ through 19 compatibility
18
+ - Enhanced token storage with versioning and migration support
19
+ - Better error messages and debugging information
20
+ - Improved performance with memoized context values
21
+
22
+ ### Fixed
23
+ - Fixed `createContext` error in React 19
24
+ - Fixed token refresh race conditions
25
+ - Fixed MFA verification timing issues
26
+ - Fixed localStorage SSR issues
27
+
28
+ ## [1.0.0] - 2024-01-XX
29
+
30
+ ### Added
31
+ - Initial release of say-auth
32
+ - JWT authentication with refresh tokens
33
+ - MFA/2FA support with TOTP
34
+ - Role-Based Access Control (RBAC)
35
+ - Auto token refresh mechanism
36
+ - Rate limiting for login attempts
37
+ - Audit logging for security events
38
+ - Session management across devices
39
+ - Token blacklisting for secure logout
40
+ - Device fingerprinting for trusted devices
41
+ - Secure encrypted token storage
42
+ - React hooks: `useAuth`, `useProtectedRoute`
43
+ - Components: `AuthProvider`, `ProtectedRoute`, `MFASetup`
44
+ - TypeScript support with full type definitions
45
+ - Next.js 13+ App Router support
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AxiosInstance } from 'axios';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import React$1 from 'react';
3
+ import * as React$1 from 'react';
4
+ import React__default from 'react';
4
5
 
5
6
  interface User {
6
7
  id: string;
@@ -35,6 +36,11 @@ interface AuthState {
35
36
  isLoading: boolean;
36
37
  error: string | null;
37
38
  }
39
+ interface MFASetup$1 {
40
+ secret: string;
41
+ qrCode: string;
42
+ backupCodes: string[];
43
+ }
38
44
  interface MFAVerify {
39
45
  userId: string;
40
46
  code: string;
@@ -87,6 +93,9 @@ declare class AuthService {
87
93
  getAxiosInstance(): AxiosInstance;
88
94
  getUser(): User | null;
89
95
  getState(): AuthState;
96
+ setupMFA(): Promise<MFASetup$1>;
97
+ disableMFA(code: string): Promise<void>;
98
+ updateUser(userData: Partial<User>): Promise<User>;
90
99
  }
91
100
 
92
101
  declare class SecureTokenStorage {
@@ -244,18 +253,82 @@ declare function useProtectedRoute(redirectTo?: string, requiredRole?: string |
244
253
  isLoading: boolean;
245
254
  };
246
255
 
256
+ interface AuthContextValue extends AuthState {
257
+ login: (credentials: LoginCredentials) => Promise<{
258
+ requiresMFA: boolean;
259
+ user?: User;
260
+ }>;
261
+ register: (data: RegisterData) => Promise<User>;
262
+ logout: () => Promise<void>;
263
+ logoutAllDevices: () => Promise<void>;
264
+ refreshSession: () => Promise<void>;
265
+ changePassword: (currentPassword: string, newPassword: string) => Promise<void>;
266
+ hasRole: (role: string | string[]) => boolean;
267
+ getAxiosInstance: () => any;
268
+ getUser: () => User | null;
269
+ verifyMFA: (code: string, trustDevice?: boolean) => Promise<User>;
270
+ setupMFA: () => Promise<MFASetup$1>;
271
+ disableMFA: (code: string) => Promise<void>;
272
+ updateUser: (userData: Partial<User>) => Promise<void>;
273
+ clearError: () => void;
274
+ isTokenExpired: () => boolean;
275
+ getAccessToken: () => string | null;
276
+ healthCheck: () => Promise<boolean>;
277
+ refreshTokens: () => Promise<void>;
278
+ getRemainingSessionTime: () => number;
279
+ extendSession: () => Promise<void>;
280
+ }
247
281
  interface AuthProviderProps {
248
- children: React$1.ReactNode;
282
+ children: React__default.ReactNode;
249
283
  apiUrl?: string;
284
+ onError?: (error: string) => void;
285
+ onSessionExpired?: () => void;
286
+ onLogin?: (user: User) => void;
287
+ onLogout?: () => void;
288
+ autoRefresh?: boolean;
289
+ refreshThreshold?: number;
250
290
  }
251
- declare function AuthProvider({ children, apiUrl }: AuthProviderProps): react_jsx_runtime.JSX.Element;
291
+ declare function AuthProvider({ children, apiUrl, onError, onSessionExpired, onLogin, onLogout, autoRefresh, refreshThreshold }: AuthProviderProps): react_jsx_runtime.JSX.Element;
292
+ declare function useAuthContext(): AuthContextValue;
293
+ declare function withAuth<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P & {
294
+ auth?: AuthContextValue;
295
+ }>;
296
+ interface RoleBasedProps {
297
+ children: React__default.ReactNode;
298
+ roles: string | string[];
299
+ fallback?: React__default.ReactNode;
300
+ }
301
+ declare function RoleBased({ children, roles, fallback }: RoleBasedProps): react_jsx_runtime.JSX.Element;
302
+ interface MFARequiredProps {
303
+ children: React__default.ReactNode;
304
+ redirectTo?: string;
305
+ }
306
+ declare function MFARequired({ children, redirectTo }: MFARequiredProps): react_jsx_runtime.JSX.Element | null;
307
+ declare function AuthStatus(): react_jsx_runtime.JSX.Element;
308
+ declare function SessionTimer(): react_jsx_runtime.JSX.Element | null;
309
+ declare function AuthDebug(): react_jsx_runtime.JSX.Element | null;
310
+ declare function SessionMonitor(): null;
311
+ interface SessionExpiryWarningProps {
312
+ warningMinutes?: number[];
313
+ onExtend?: () => void;
314
+ }
315
+ declare function SessionExpiryWarning({ warningMinutes, onExtend }: SessionExpiryWarningProps): react_jsx_runtime.JSX.Element | null;
252
316
 
253
317
  interface ProtectedRouteProps {
254
318
  children: React.ReactNode;
255
319
  requiredRole?: string | string[];
256
320
  fallback?: React.ReactNode;
321
+ redirectTo?: string;
322
+ }
323
+ declare function ProtectedRoute({ children, requiredRole, fallback, redirectTo }: ProtectedRouteProps): string | number | true | Iterable<React$1.ReactNode> | react_jsx_runtime.JSX.Element | null;
324
+
325
+ interface LoginFormProps {
326
+ onSubmit: (email: string, password: string) => Promise<void>;
327
+ isLoading?: boolean;
328
+ error?: string;
329
+ className?: string;
257
330
  }
258
- declare function ProtectedRoute({ children, requiredRole, fallback }: ProtectedRouteProps): react_jsx_runtime.JSX.Element | null;
331
+ declare function LoginForm({ onSubmit, isLoading, error, className }: LoginFormProps): react_jsx_runtime.JSX.Element;
259
332
 
260
333
  interface MFASetupProps {
261
334
  userId: string;
@@ -280,6 +353,8 @@ declare function setupAuthInterceptors(axiosInstance: AxiosInstance, baseURL: st
280
353
  declare function cn(...classes: (string | undefined | false)[]): string;
281
354
  declare function getErrorMessage(error: unknown): string;
282
355
  declare function isValidEmail(email: string): boolean;
356
+ declare function formatDate(date: Date): string;
357
+ declare function generateRandomString(length: number): string;
283
358
 
284
359
  declare const AUTH_CONFIG: {
285
360
  tokenRefreshThreshold: number;
@@ -309,4 +384,22 @@ declare const API_ENDPOINTS: {
309
384
  audit: string;
310
385
  };
311
386
 
312
- export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthProvider, AuthService, type AuthState, type AuthTokens, DeviceFingerprint, type LoginCredentials, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, STORAGE_KEYS, SessionManager, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, cn, getErrorMessage, isValidEmail, setupAuthInterceptors, useAuth, useProtectedRoute };
387
+ declare function validateEnvironment(): void;
388
+
389
+ interface ErrorTracker {
390
+ captureException(error: Error, context?: Record<string, any>): void;
391
+ captureMessage(message: string, context?: Record<string, any>): void;
392
+ }
393
+ declare let errorTracker: ErrorTracker;
394
+ declare function initErrorTracker(tracker: ErrorTracker): void;
395
+
396
+ declare const securityHeaders: {
397
+ 'X-Frame-Options': string;
398
+ 'X-Content-Type-Options': string;
399
+ 'X-XSS-Protection': string;
400
+ 'Referrer-Policy': string;
401
+ 'Permissions-Policy': string;
402
+ };
403
+ declare function applySecurityHeaders(response: Response): Response;
404
+
405
+ export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthDebug, AuthProvider, AuthService, type AuthState, AuthStatus, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFARequired, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, RoleBased, STORAGE_KEYS, SessionExpiryWarning, SessionManager, SessionMonitor, SessionTimer, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment, withAuth };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AxiosInstance } from 'axios';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import React$1 from 'react';
3
+ import * as React$1 from 'react';
4
+ import React__default from 'react';
4
5
 
5
6
  interface User {
6
7
  id: string;
@@ -35,6 +36,11 @@ interface AuthState {
35
36
  isLoading: boolean;
36
37
  error: string | null;
37
38
  }
39
+ interface MFASetup$1 {
40
+ secret: string;
41
+ qrCode: string;
42
+ backupCodes: string[];
43
+ }
38
44
  interface MFAVerify {
39
45
  userId: string;
40
46
  code: string;
@@ -87,6 +93,9 @@ declare class AuthService {
87
93
  getAxiosInstance(): AxiosInstance;
88
94
  getUser(): User | null;
89
95
  getState(): AuthState;
96
+ setupMFA(): Promise<MFASetup$1>;
97
+ disableMFA(code: string): Promise<void>;
98
+ updateUser(userData: Partial<User>): Promise<User>;
90
99
  }
91
100
 
92
101
  declare class SecureTokenStorage {
@@ -244,18 +253,82 @@ declare function useProtectedRoute(redirectTo?: string, requiredRole?: string |
244
253
  isLoading: boolean;
245
254
  };
246
255
 
256
+ interface AuthContextValue extends AuthState {
257
+ login: (credentials: LoginCredentials) => Promise<{
258
+ requiresMFA: boolean;
259
+ user?: User;
260
+ }>;
261
+ register: (data: RegisterData) => Promise<User>;
262
+ logout: () => Promise<void>;
263
+ logoutAllDevices: () => Promise<void>;
264
+ refreshSession: () => Promise<void>;
265
+ changePassword: (currentPassword: string, newPassword: string) => Promise<void>;
266
+ hasRole: (role: string | string[]) => boolean;
267
+ getAxiosInstance: () => any;
268
+ getUser: () => User | null;
269
+ verifyMFA: (code: string, trustDevice?: boolean) => Promise<User>;
270
+ setupMFA: () => Promise<MFASetup$1>;
271
+ disableMFA: (code: string) => Promise<void>;
272
+ updateUser: (userData: Partial<User>) => Promise<void>;
273
+ clearError: () => void;
274
+ isTokenExpired: () => boolean;
275
+ getAccessToken: () => string | null;
276
+ healthCheck: () => Promise<boolean>;
277
+ refreshTokens: () => Promise<void>;
278
+ getRemainingSessionTime: () => number;
279
+ extendSession: () => Promise<void>;
280
+ }
247
281
  interface AuthProviderProps {
248
- children: React$1.ReactNode;
282
+ children: React__default.ReactNode;
249
283
  apiUrl?: string;
284
+ onError?: (error: string) => void;
285
+ onSessionExpired?: () => void;
286
+ onLogin?: (user: User) => void;
287
+ onLogout?: () => void;
288
+ autoRefresh?: boolean;
289
+ refreshThreshold?: number;
250
290
  }
251
- declare function AuthProvider({ children, apiUrl }: AuthProviderProps): react_jsx_runtime.JSX.Element;
291
+ declare function AuthProvider({ children, apiUrl, onError, onSessionExpired, onLogin, onLogout, autoRefresh, refreshThreshold }: AuthProviderProps): react_jsx_runtime.JSX.Element;
292
+ declare function useAuthContext(): AuthContextValue;
293
+ declare function withAuth<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P & {
294
+ auth?: AuthContextValue;
295
+ }>;
296
+ interface RoleBasedProps {
297
+ children: React__default.ReactNode;
298
+ roles: string | string[];
299
+ fallback?: React__default.ReactNode;
300
+ }
301
+ declare function RoleBased({ children, roles, fallback }: RoleBasedProps): react_jsx_runtime.JSX.Element;
302
+ interface MFARequiredProps {
303
+ children: React__default.ReactNode;
304
+ redirectTo?: string;
305
+ }
306
+ declare function MFARequired({ children, redirectTo }: MFARequiredProps): react_jsx_runtime.JSX.Element | null;
307
+ declare function AuthStatus(): react_jsx_runtime.JSX.Element;
308
+ declare function SessionTimer(): react_jsx_runtime.JSX.Element | null;
309
+ declare function AuthDebug(): react_jsx_runtime.JSX.Element | null;
310
+ declare function SessionMonitor(): null;
311
+ interface SessionExpiryWarningProps {
312
+ warningMinutes?: number[];
313
+ onExtend?: () => void;
314
+ }
315
+ declare function SessionExpiryWarning({ warningMinutes, onExtend }: SessionExpiryWarningProps): react_jsx_runtime.JSX.Element | null;
252
316
 
253
317
  interface ProtectedRouteProps {
254
318
  children: React.ReactNode;
255
319
  requiredRole?: string | string[];
256
320
  fallback?: React.ReactNode;
321
+ redirectTo?: string;
322
+ }
323
+ declare function ProtectedRoute({ children, requiredRole, fallback, redirectTo }: ProtectedRouteProps): string | number | true | Iterable<React$1.ReactNode> | react_jsx_runtime.JSX.Element | null;
324
+
325
+ interface LoginFormProps {
326
+ onSubmit: (email: string, password: string) => Promise<void>;
327
+ isLoading?: boolean;
328
+ error?: string;
329
+ className?: string;
257
330
  }
258
- declare function ProtectedRoute({ children, requiredRole, fallback }: ProtectedRouteProps): react_jsx_runtime.JSX.Element | null;
331
+ declare function LoginForm({ onSubmit, isLoading, error, className }: LoginFormProps): react_jsx_runtime.JSX.Element;
259
332
 
260
333
  interface MFASetupProps {
261
334
  userId: string;
@@ -280,6 +353,8 @@ declare function setupAuthInterceptors(axiosInstance: AxiosInstance, baseURL: st
280
353
  declare function cn(...classes: (string | undefined | false)[]): string;
281
354
  declare function getErrorMessage(error: unknown): string;
282
355
  declare function isValidEmail(email: string): boolean;
356
+ declare function formatDate(date: Date): string;
357
+ declare function generateRandomString(length: number): string;
283
358
 
284
359
  declare const AUTH_CONFIG: {
285
360
  tokenRefreshThreshold: number;
@@ -309,4 +384,22 @@ declare const API_ENDPOINTS: {
309
384
  audit: string;
310
385
  };
311
386
 
312
- export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthProvider, AuthService, type AuthState, type AuthTokens, DeviceFingerprint, type LoginCredentials, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, STORAGE_KEYS, SessionManager, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, cn, getErrorMessage, isValidEmail, setupAuthInterceptors, useAuth, useProtectedRoute };
387
+ declare function validateEnvironment(): void;
388
+
389
+ interface ErrorTracker {
390
+ captureException(error: Error, context?: Record<string, any>): void;
391
+ captureMessage(message: string, context?: Record<string, any>): void;
392
+ }
393
+ declare let errorTracker: ErrorTracker;
394
+ declare function initErrorTracker(tracker: ErrorTracker): void;
395
+
396
+ declare const securityHeaders: {
397
+ 'X-Frame-Options': string;
398
+ 'X-Content-Type-Options': string;
399
+ 'X-XSS-Protection': string;
400
+ 'Referrer-Policy': string;
401
+ 'Permissions-Policy': string;
402
+ };
403
+ declare function applySecurityHeaders(response: Response): Response;
404
+
405
+ export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthDebug, AuthProvider, AuthService, type AuthState, AuthStatus, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFARequired, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, RoleBased, STORAGE_KEYS, SessionExpiryWarning, SessionManager, SessionMonitor, SessionTimer, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment, withAuth };