{"_rev":"17-c7dec67d56d160f02869da69767d0e9d","time":{"created":"2025-12-22T19:10:46.332Z","modified":"2025-12-22T19:10:46.977Z","0.1.0":"2025-12-04T02:56:45.001Z","0.1.1":"2025-12-04T04:08:38.368Z","0.2.0":"2025-12-04T05:04:55.258Z","0.3.0":"2025-12-04T17:25:44.994Z","0.3.1":"2025-12-04T17:26:07.127Z","0.3.2":"2025-12-04T22:08:50.161Z","0.3.3":"2025-12-04T23:10:10.567Z","0.3.4":"2025-12-04T23:45:41.221Z","0.3.5":"2025-12-05T01:51:47.216Z","0.3.6":"2025-12-05T02:03:26.491Z","0.3.7":"2025-12-05T02:08:31.226Z","0.3.8":"2025-12-05T02:10:04.659Z","0.4.0":"2025-12-05T03:12:18.633Z","0.4.1":"2025-12-05T03:28:31.969Z","0.5.0":"2025-12-22T19:10:46.619Z"},"_id":"@artatol-acp/auth-js","name":"@artatol-acp/auth-js","dist-tags":{"latest":"0.5.0"},"versions":{"0.5.0":{"name":"@artatol-acp/auth-js","version":"0.5.0","description":"Vanilla JavaScript/TypeScript SDK for ACP Auth","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"keywords":["auth","authentication","jwt","2fa","artatol","acp"],"author":{"name":"Artatol"},"license":"MIT","devDependencies":{"typescript":"^5.6.3"},"scripts":{"build":"tsc","typecheck":"tsc --noEmit"},"_id":"@artatol-acp/auth-js@0.5.0","_integrity":"sha512-pwCxIWOwjPbdi9AlI2IwIU/zvZYV1wYnhaiSWD9Glv0EDcjEtit+qUSRnSsD7tvjBRbvHSU+OS8mwtl2/+BfQg==","_resolved":"/private/var/folders/9x/wfkj1l0j56z0lywbzrkgrvs80000gn/T/44990eb51fb046682be5f7f632827c0b/artatol-acp-auth-js-0.5.0.tgz","_from":"file:artatol-acp-auth-js-0.5.0.tgz","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-pwCxIWOwjPbdi9AlI2IwIU/zvZYV1wYnhaiSWD9Glv0EDcjEtit+qUSRnSsD7tvjBRbvHSU+OS8mwtl2/+BfQg==","shasum":"2286593611c6baa22ecda67a58fa90d1d9e17017","tarball":"https://registry.npmjs.org/@artatol-acp/auth-js/-/auth-js-0.5.0.tgz","fileCount":14,"unpackedSize":46022,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCLQElvKB3JUpnsbSQaZOJSRmUe9gu2+pVjw4NVgPACJAIgEIFlCuQPtLaiPrNMvW1osON6tkqbX1q3t0VLrAsPDN0="}]},"_npmUser":{"name":"charouzek-artatol","email":"martin.charouzek@artatol.com"},"directories":{},"maintainers":[{"name":"charouzek-artatol","email":"martin.charouzek@artatol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/auth-js_0.5.0_1766430646471_0.8998084251504821"},"_hasShrinkwrap":false}},"maintainers":[{"name":"charouzek-artatol","email":"martin.charouzek@artatol.com"}],"description":"Vanilla JavaScript/TypeScript SDK for ACP Auth","keywords":["auth","authentication","jwt","2fa","artatol","acp"],"author":{"name":"Artatol"},"license":"MIT","readme":"# @artatol-acp/auth-js\n\nJavaScript SDK for Artatol Cloud Platform Authentication.\n\n## Changelog\n\n### v0.4.0\n\n**Breaking Changes:**\n- `apiKey` is now optional in `ACPAuthClientOptions`\n\n**Improvements:**\n- **Better error messages**: `baseUrl` validation now throws a clear error message instead of cryptic `Cannot read properties of undefined`\n- **Improved ACPAuthError**: Error message is now always properly extracted from API response\n  - New helper methods: `isAuthError()`, `isValidationError()`, `isNetworkError()`\n  - Added `code` property for error codes\n- **Better network error handling**: Network errors are now wrapped in `ACPAuthError` with clear messages\n- **New `FetchFunction` type**: Custom fetch functions are now typed more flexibly for compatibility with Bun and other runtimes\n\n## Installation\n\n```bash\nnpm install @artatol-acp/auth-js\n# or\npnpm add @artatol-acp/auth-js\n# or\nyarn add @artatol-acp/auth-js\n```\n\n## Prerequisites\n\nBefore using this SDK, you need to obtain from the ACP AUTH service:\n\n1. **API Key** (required) - Contact your system administrator for an API key for your application\n2. **Base URL** (required) - The auth service URL (e.g., `https://sso.artatol.net`)\n\nThis SDK handles all authentication operations via API calls and does not require JWT verification on the client side.\n\n## Features\n\n- **Automatic Token Refresh**: Automatically refreshes access tokens before they expire\n- **Email Verification**: Built-in email verification flow\n- **Two-Factor Authentication**: Support for TOTP-based 2FA\n- **Password Reset**: Secure password reset flow\n- **Account Management**: Complete user account lifecycle management\n\n## Usage\n\n```typescript\nimport { ACPAuthClient } from '@artatol-acp/auth-js';\n\nconst client = new ACPAuthClient({\n  baseUrl: 'https://sso.artatol.net',\n  apiKey: 'your-api-key-here',\n  // Optional: Configure automatic token refresh (enabled by default)\n  autoRefresh: true,\n  refreshThresholdSeconds: 60 // Refresh token 60 seconds before expiration\n});\n\n// Register\nconst user = await client.register({\n  email: 'user@example.com',\n  password: 'securepassword123'\n});\n// User will receive verification email\n\n// Login\nconst loginResult = await client.login({\n  email: 'user@example.com',\n  password: 'securepassword123'\n});\n\nif ('requiresTwoFactor' in loginResult) {\n  // 2FA required\n  const { accessToken, user } = await client.verify2FALogin({\n    tempToken: loginResult.tempToken,\n    code: '123456'\n  });\n} else {\n  // Login successful\n  const { accessToken, user } = loginResult;\n}\n\n// Refresh token\nconst { accessToken } = await client.refresh();\n\n// Setup 2FA\nconst { secret, qrCodeUrl, recoveryCodes } = await client.setup2FA(\n  { password: 'current-password' },\n  accessToken\n);\n\n// Verify 2FA\nawait client.verify2FA({ code: '123456' }, accessToken);\n\n// Disable 2FA\nawait client.disable2FA(\n  { password: 'current-password', code: '123456' },\n  accessToken\n);\n\n// Forgot password\nawait client.forgotPassword({ email: 'user@example.com' });\n\n// Reset password\nawait client.resetPassword({\n  token: 'reset-token-from-email',\n  newPassword: 'newSecurePassword123'\n});\n\n// Delete account\nawait client.deleteAccount(\n  { password: 'current-password', confirmation: 'DELETE' },\n  accessToken\n);\n\n// Verify email\nawait client.verifyEmail({ token: 'token-from-email' });\n\n// Resend verification email\nawait client.resendVerificationEmail({ email: 'user@example.com' });\n\n// Logout\nawait client.logout();\n```\n\n## Password Requirements\n\nPasswords must meet the following requirements:\n- Minimum 10 characters\n- At least one lowercase letter (a-z)\n- At least one uppercase letter (A-Z)\n- At least one number (0-9)\n\n```typescript\nfunction validatePassword(password: string): string[] {\n  const errors: string[] = [];\n\n  if (password.length < 10) {\n    errors.push('Password must be at least 10 characters');\n  }\n  if (!/[a-z]/.test(password)) {\n    errors.push('Password must contain at least one lowercase letter');\n  }\n  if (!/[A-Z]/.test(password)) {\n    errors.push('Password must contain at least one uppercase letter');\n  }\n  if (!/[0-9]/.test(password)) {\n    errors.push('Password must contain at least one number');\n  }\n\n  return errors;\n}\n```\n\n## Email Verification\n\nAfter registration, users must verify their email address before they can log in. The auth service automatically sends a verification email upon registration.\n\n### Verification Flow\n\n1. User registers → receives verification email\n2. User clicks link in email → email is verified\n3. User can now log in\n\n### Example Usage\n\n```typescript\nimport { ACPAuthClient } from '@artatol-acp/auth-js';\n\nconst client = new ACPAuthClient({\n  baseUrl: 'https://sso.artatol.net',\n  apiKey: 'your-api-key-here'\n});\n\n// Register - sends verification email automatically\nawait client.register({\n  email: 'user@example.com',\n  password: 'SecurePass123'\n});\n\n// Verify email using token from email\ntry {\n  await client.verifyEmail({ token: 'token-from-email-link' });\n  console.log('Email verified successfully');\n} catch (error) {\n  console.error('Verification failed:', error);\n}\n\n// Resend verification email if needed\nawait client.resendVerificationEmail({ email: 'user@example.com' });\n// Always succeeds to prevent email enumeration\n\n// Login - will fail if email not verified\ntry {\n  const result = await client.login({\n    email: 'user@example.com',\n    password: 'SecurePass123'\n  });\n} catch (error) {\n  if (error.message?.includes('Email not verified')) {\n    console.error('Please verify your email before logging in');\n  }\n}\n```\n\n## API Reference\n\n### Constructor\n\n```typescript\nnew ACPAuthClient(options: ACPAuthClientOptions)\n```\n\nOptions:\n- `baseUrl` (string, required): Base URL of the ACP AUTH service\n- `apiKey` (string, required): API key for authenticating your application\n- `fetch` (function, optional): Custom fetch implementation\n- `autoRefresh` (boolean, optional, default: true): Enable automatic token refresh\n- `refreshThresholdSeconds` (number, optional, default: 60): Number of seconds before token expiration to trigger auto-refresh\n\n### Methods\n\nAll methods return a Promise.\n\n#### `register(data: RegisterRequest): Promise<User>`\nRegister a new user. Automatically sends a verification email.\n\n#### `verifyEmail(data: VerifyEmailRequest): Promise<{ message: string }>`\nVerify user's email address using the token from the verification email.\n\n#### `resendVerificationEmail(data: ResendVerificationEmailRequest): Promise<{ message: string }>`\nResend verification email to the user.\n\n#### `login(data: LoginRequest): Promise<LoginResult>`\nLogin a user. Returns either login response with tokens or 2FA requirement.\n\n#### `verify2FALogin(data: Verify2FALoginRequest): Promise<LoginResponse>`\nComplete 2FA login flow.\n\n#### `logout(): Promise<{ message: string }>`\nLogout the current user.\n\n#### `refresh(): Promise<RefreshResponse>`\nRefresh the access token using the refresh token cookie.\n\n#### `me(accessToken?: string): Promise<User>`\nGet current user information. Uses the internally stored access token if not provided. Returns full user data including 2FA status.\n\n```typescript\ntype User = {\n  id: string;\n  email: string;\n  twoFactorEnabled: boolean;\n};\n```\n\n#### `setup2FA(data: Setup2FARequest, accessToken: string): Promise<Setup2FAResponse>`\nSetup 2FA for the authenticated user.\n\n#### `verify2FA(data: Verify2FARequest, accessToken: string): Promise<{ message: string }>`\nVerify and enable 2FA.\n\n#### `disable2FA(data: Disable2FARequest, accessToken: string): Promise<{ message: string }>`\nDisable 2FA for the authenticated user.\n\n#### `forgotPassword(data: ForgotPasswordRequest): Promise<{ message: string }>`\nRequest a password reset.\n\n#### `resetPassword(data: ResetPasswordRequest): Promise<{ message: string }>`\nReset password using the token from email.\n\n#### `deleteAccount(data: DeleteAccountRequest, accessToken: string): Promise<{ message: string }>`\nDelete the authenticated user's account.\n\n#### `health(): Promise<{ status: string; timestamp: string }>`\nCheck API health status.\n\n## Automatic Token Refresh\n\nThe SDK provides **lazy auto-refresh** - it checks and refreshes tokens before each API request if they're close to expiration.\n\n### How It Works (Lazy Mode)\n\n1. When you call `login()` or `verify2FALogin()`, the SDK automatically stores the access token internally\n2. **Before each API request**, the SDK checks if the token is close to expiration\n3. If the token will expire within `refreshThresholdSeconds` (default: 60 seconds), it automatically refreshes\n4. The refresh happens in the background, transparent to your application\n5. All subsequent requests use the new token\n\n**Note:** This is \"lazy\" refresh - it only refreshes when you make an API call. For **proactive** refresh with intervals, use the framework-specific SDKs (Next.js or Nuxt) which implement background refresh timers.\n\n### Configuration\n\n```typescript\nconst client = new ACPAuthClient({\n  baseUrl: 'https://sso.artatol.net',\n  apiKey: 'your-api-key',\n  autoRefresh: true, // Enable auto-refresh (default: true)\n  refreshThresholdSeconds: 60 // Refresh 60s before expiration (default: 60)\n});\n\n// After login, the token is automatically managed\nconst result = await client.login({ email: '...', password: '...' });\n\n// All subsequent calls automatically use and refresh the token\nconst user = await client.me(); // No need to pass accessToken\nawait client.setup2FA({ password: '...' }); // Token automatically refreshed if needed\n```\n\n### Manual Token Management\n\nYou can also manually manage tokens if needed:\n\n```typescript\n// Set token manually\nclient.setAccessToken('your-token', 300); // 300 seconds expiry\n\n// Get current token\nconst token = client.getAccessToken();\n\n// Clear token\nclient.setAccessToken(null);\n```\n\n### Disabling Auto-Refresh\n\nIf you prefer to handle token refresh manually:\n\n```typescript\nconst client = new ACPAuthClient({\n  baseUrl: 'https://sso.artatol.net',\n  apiKey: 'your-api-key',\n  autoRefresh: false // Disable auto-refresh\n});\n\n// Manually refresh when needed\nconst { accessToken } = await client.refresh();\nclient.setAccessToken(accessToken, 300);\n```\n\n## Error Handling\n\n```typescript\nimport { ACPAuthError } from '@artatol-acp/auth-js';\n\ntry {\n  await client.login({ email: 'user@example.com', password: 'wrong' });\n} catch (error) {\n  if (error instanceof ACPAuthError) {\n    console.error('Auth error:', error.message);\n    console.error('Status code:', error.statusCode);\n  }\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}