npm package: @shyam-148/auth-client
Description: Framework-agnostic auth client core
Latest version: 1.0.1

# Auth Client

A framework-agnostic authentication client for TypeScript/JavaScript applications. Provides a robust, type-safe API for handling user authentication with support for email/password login, MFA, token refresh, and session management.

## Features

- 🔐 **Multiple Authentication Strategies** - Email/Password with extensible strategy pattern
- 🔄 **Automatic Token Refresh** - Seamless token renewal with request queuing
- 📱 **MFA Support** - Built-in support for multi-factor authentication flows
- 💾 **Persistent Sessions** - Automatic session restoration from storage
- 📡 **Reactive State** - Subscribe to authentication state changes
- 🛡️ **Type-Safe** - Full TypeScript support with comprehensive types
- 🎯 **Framework Agnostic** - Works with React, Vue, Angular, or vanilla JS

## Installation

```bash
npm install auth-client
# or
pnpm add auth-client
# or
yarn add auth-client
```

## Quick Start

### Basic Usage

```typescript
import { AuthManager, EmailPasswordStrategy } from 'auth-client';

// Create the auth manager
const auth = new AuthManager({
  baseUrl: 'https://api.example.com',
  applicationSlug: 'my-app',
});

// Create the email/password strategy
const emailStrategy = new EmailPasswordStrategy('my-app');

// Login
try {
  await auth.login(emailStrategy, {
    email: 'user@example.com',
    password: 'password123'
  });
  
  console.log('Logged in!', auth.getUser());
} catch (error) {
  console.error('Login failed:', error);
}

// Check authentication status
if (auth.isAuthenticated()) {
  console.log('User:', auth.getUser());
}

// Logout
await auth.logout();
```

### Using the Factory Function

```typescript
import { createAuthClient } from 'auth-client';

const { manager, emailPasswordStrategy } = createAuthClient({
  baseUrl: 'https://api.example.com',
  applicationSlug: 'my-app',
  debug: true, // Enable debug logging
});

// Login using the pre-configured strategy
await manager.login(emailPasswordStrategy, {
  email: 'user@example.com',
  password: 'password123'
});
```

### Subscribing to State Changes

```typescript
const unsubscribe = auth.subscribe((snapshot, event) => {
  console.log('Auth event:', event);
  console.log('Status:', snapshot.status);
  console.log('User:', snapshot.user);
});

// Later, unsubscribe when no longer needed
unsubscribe();
```

### Handling MFA

```typescript
import { 
  createAuthClient, 
  isMfaChallenge, 
  MfaRequiredError 
} from 'auth-client';

const { manager, emailPasswordStrategy } = createAuthClient({
  baseUrl: 'https://api.example.com',
  applicationSlug: 'my-app',
});

try {
  // Use loginWithMfaSupport for MFA-aware flow
  const result = await manager.loginWithMfaSupport(emailPasswordStrategy, {
    email: 'user@example.com',
    password: 'password123'
  });
  
  if (isMfaChallenge(result)) {
    // MFA required - prompt user for code
    console.log('MFA required, method:', result.mfaMethod);
    
    // Later, verify the MFA code
    await manager.verifyMfa({
      challengeId: result.challengeId,
      sessionId: result.sessionId,
      code: '123456' // User-entered code
    });
  } else {
    // Login successful without MFA
    console.log('Logged in!', result.user);
  }
} catch (error) {
  if (error instanceof MfaRequiredError) {
    // Handle MFA requirement
  }
}
```

## Configuration

### AuthClientConfig

```typescript
interface AuthClientConfig {
  /** Base URL for the auth API server */
  baseUrl: string;
  
  /** Application slug for multi-tenant support */
  applicationSlug: string;
  
  /** Optional storage configuration */
  storage?: {
    key: string; // Storage key prefix
  };
  
  /** Optional endpoint overrides */
  endpoints?: Partial<EndpointConfig>;
  
  /** Optional default device info */
  defaultDevice?: DeviceInfo;
  
  /** Request timeout in milliseconds (default: 10000) */
  timeout?: number;
  
  /** Enable debug logging */
  debug?: boolean;
}
```

### Default Endpoints

```typescript
const DEFAULT_ENDPOINTS = {
  login: '/auth/login',
  register: '/auth/register',
  logout: '/auth/logout',
  logoutAll: '/auth/logout/all',
  logoutOthers: '/auth/logout/others',
  refresh: '/auth/refresh',
  mfaVerify: '/auth/mfa/verify',
  verifyEmail: '/auth/verify-email',
  resendVerification: '/auth/resend-verification',
  me: '/auth/me'
};
```

## API Reference

### AuthManager

The main class for managing authentication.

#### Methods

| Method | Description |
|--------|-------------|
| `login(strategy, payload)` | Login using an authentication strategy |
| `loginWithMfaSupport(strategy, payload)` | Login with MFA handling |
| `verifyMfa(payload)` | Verify MFA code |
| `logout()` | Logout current session |
| `logoutAll()` | Logout from all sessions |
| `logoutOthers()` | Logout from other sessions |
| `refreshToken()` | Manually refresh the access token |
| `getUser()` | Get current user |
| `getSession()` | Get current session |
| `getAccessToken()` | Get current access token |
| `isAuthenticated()` | Check if user is authenticated |
| `subscribe(listener)` | Subscribe to state changes |

### EmailPasswordStrategy

Strategy for email/password authentication.

```typescript
const strategy = new EmailPasswordStrategy(
  'my-app',        // applicationSlug
  defaultDevice?   // optional device info
);

await auth.login(strategy, {
  email: 'user@example.com',
  password: 'password123',
  device?: { /* optional device override */ }
});
```

### Error Handling

All authentication errors extend `AuthError`:

```typescript
import { 
  AuthError,
  AuthErrorCode,
  InvalidCredentialsError,
  MfaRequiredError,
  SessionExpiredError,
  NetworkError,
  RateLimitError
} from 'auth-client';

try {
  await auth.login(strategy, credentials);
} catch (error) {
  if (error instanceof InvalidCredentialsError) {
    // Handle invalid credentials
  } else if (error instanceof MfaRequiredError) {
    // Handle MFA requirement
  } else if (error instanceof RateLimitError) {
    // Handle rate limiting
    console.log('Retry after:', error.retryAfter);
  } else if (error instanceof AuthError) {
    // Handle other auth errors
    console.log('Error code:', error.code);
    console.log('Is retryable:', error.isRetryable());
  }
}
```

### Error Codes

| Code | Description |
|------|-------------|
| `AUTH_1001` | Invalid credentials |
| `AUTH_1002` | Account locked |
| `AUTH_1003` | Account disabled |
| `AUTH_1004` | Email not verified |
| `AUTH_1009` | Session expired |
| `MFA_2001` | MFA required |
| `MFA_2002` | Invalid MFA code |
| `REG_3001` | Email already exists |
| `REG_3002` | Weak password |
| `RATE_7001` | Rate limit exceeded |

## TypeScript

The package is fully typed. Key types are exported:

```typescript
import type {
  User,
  Session,
  AuthTokens,
  AuthSnapshot,
  AuthEventType,
  LoginResult,
  AuthenticatedResult,
  MfaChallengeResult,
  DeviceInfo,
  AuthClientConfig,
} from 'auth-client';
```

## License

MIT