@artatol-acp/auth-js
v0.5.0
Published
Vanilla JavaScript/TypeScript SDK for ACP Auth
Maintainers
Readme
@artatol-acp/auth-js
JavaScript SDK for Artatol Cloud Platform Authentication.
Changelog
v0.4.0
Breaking Changes:
apiKeyis now optional inACPAuthClientOptions
Improvements:
- Better error messages:
baseUrlvalidation now throws a clear error message instead of crypticCannot read properties of undefined - Improved ACPAuthError: Error message is now always properly extracted from API response
- New helper methods:
isAuthError(),isValidationError(),isNetworkError() - Added
codeproperty for error codes
- New helper methods:
- Better network error handling: Network errors are now wrapped in
ACPAuthErrorwith clear messages - New
FetchFunctiontype: Custom fetch functions are now typed more flexibly for compatibility with Bun and other runtimes
Installation
npm install @artatol-acp/auth-js
# or
pnpm add @artatol-acp/auth-js
# or
yarn add @artatol-acp/auth-jsPrerequisites
Before using this SDK, you need to obtain from the ACP AUTH service:
- API Key (required) - Contact your system administrator for an API key for your application
- Base URL (required) - The auth service URL (e.g.,
https://sso.artatol.net)
This SDK handles all authentication operations via API calls and does not require JWT verification on the client side.
Features
- Automatic Token Refresh: Automatically refreshes access tokens before they expire
- Email Verification: Built-in email verification flow
- Two-Factor Authentication: Support for TOTP-based 2FA
- Password Reset: Secure password reset flow
- Account Management: Complete user account lifecycle management
Usage
import { ACPAuthClient } from '@artatol-acp/auth-js';
const client = new ACPAuthClient({
baseUrl: 'https://sso.artatol.net',
apiKey: 'your-api-key-here',
// Optional: Configure automatic token refresh (enabled by default)
autoRefresh: true,
refreshThresholdSeconds: 60 // Refresh token 60 seconds before expiration
});
// Register
const user = await client.register({
email: '[email protected]',
password: 'securepassword123'
});
// User will receive verification email
// Login
const loginResult = await client.login({
email: '[email protected]',
password: 'securepassword123'
});
if ('requiresTwoFactor' in loginResult) {
// 2FA required
const { accessToken, user } = await client.verify2FALogin({
tempToken: loginResult.tempToken,
code: '123456'
});
} else {
// Login successful
const { accessToken, user } = loginResult;
}
// Refresh token
const { accessToken } = await client.refresh();
// Setup 2FA
const { secret, qrCodeUrl, recoveryCodes } = await client.setup2FA(
{ password: 'current-password' },
accessToken
);
// Verify 2FA
await client.verify2FA({ code: '123456' }, accessToken);
// Disable 2FA
await client.disable2FA(
{ password: 'current-password', code: '123456' },
accessToken
);
// Forgot password
await client.forgotPassword({ email: '[email protected]' });
// Reset password
await client.resetPassword({
token: 'reset-token-from-email',
newPassword: 'newSecurePassword123'
});
// Delete account
await client.deleteAccount(
{ password: 'current-password', confirmation: 'DELETE' },
accessToken
);
// Verify email
await client.verifyEmail({ token: 'token-from-email' });
// Resend verification email
await client.resendVerificationEmail({ email: '[email protected]' });
// Logout
await client.logout();Password Requirements
Passwords must meet the following requirements:
- Minimum 10 characters
- At least one lowercase letter (a-z)
- At least one uppercase letter (A-Z)
- At least one number (0-9)
function validatePassword(password: string): string[] {
const errors: string[] = [];
if (password.length < 10) {
errors.push('Password must be at least 10 characters');
}
if (!/[a-z]/.test(password)) {
errors.push('Password must contain at least one lowercase letter');
}
if (!/[A-Z]/.test(password)) {
errors.push('Password must contain at least one uppercase letter');
}
if (!/[0-9]/.test(password)) {
errors.push('Password must contain at least one number');
}
return errors;
}Email Verification
After registration, users must verify their email address before they can log in. The auth service automatically sends a verification email upon registration.
Verification Flow
- User registers → receives verification email
- User clicks link in email → email is verified
- User can now log in
Example Usage
import { ACPAuthClient } from '@artatol-acp/auth-js';
const client = new ACPAuthClient({
baseUrl: 'https://sso.artatol.net',
apiKey: 'your-api-key-here'
});
// Register - sends verification email automatically
await client.register({
email: '[email protected]',
password: 'SecurePass123'
});
// Verify email using token from email
try {
await client.verifyEmail({ token: 'token-from-email-link' });
console.log('Email verified successfully');
} catch (error) {
console.error('Verification failed:', error);
}
// Resend verification email if needed
await client.resendVerificationEmail({ email: '[email protected]' });
// Always succeeds to prevent email enumeration
// Login - will fail if email not verified
try {
const result = await client.login({
email: '[email protected]',
password: 'SecurePass123'
});
} catch (error) {
if (error.message?.includes('Email not verified')) {
console.error('Please verify your email before logging in');
}
}API Reference
Constructor
new ACPAuthClient(options: ACPAuthClientOptions)Options:
baseUrl(string, required): Base URL of the ACP AUTH serviceapiKey(string, required): API key for authenticating your applicationfetch(function, optional): Custom fetch implementationautoRefresh(boolean, optional, default: true): Enable automatic token refreshrefreshThresholdSeconds(number, optional, default: 60): Number of seconds before token expiration to trigger auto-refresh
Methods
All methods return a Promise.
register(data: RegisterRequest): Promise<User>
Register a new user. Automatically sends a verification email.
verifyEmail(data: VerifyEmailRequest): Promise<{ message: string }>
Verify user's email address using the token from the verification email.
resendVerificationEmail(data: ResendVerificationEmailRequest): Promise<{ message: string }>
Resend verification email to the user.
login(data: LoginRequest): Promise<LoginResult>
Login a user. Returns either login response with tokens or 2FA requirement.
verify2FALogin(data: Verify2FALoginRequest): Promise<LoginResponse>
Complete 2FA login flow.
logout(): Promise<{ message: string }>
Logout the current user.
refresh(): Promise<RefreshResponse>
Refresh the access token using the refresh token cookie.
me(accessToken?: string): Promise<User>
Get current user information. Uses the internally stored access token if not provided. Returns full user data including 2FA status.
type User = {
id: string;
email: string;
twoFactorEnabled: boolean;
};setup2FA(data: Setup2FARequest, accessToken: string): Promise<Setup2FAResponse>
Setup 2FA for the authenticated user.
verify2FA(data: Verify2FARequest, accessToken: string): Promise<{ message: string }>
Verify and enable 2FA.
disable2FA(data: Disable2FARequest, accessToken: string): Promise<{ message: string }>
Disable 2FA for the authenticated user.
forgotPassword(data: ForgotPasswordRequest): Promise<{ message: string }>
Request a password reset.
resetPassword(data: ResetPasswordRequest): Promise<{ message: string }>
Reset password using the token from email.
deleteAccount(data: DeleteAccountRequest, accessToken: string): Promise<{ message: string }>
Delete the authenticated user's account.
health(): Promise<{ status: string; timestamp: string }>
Check API health status.
Automatic Token Refresh
The SDK provides lazy auto-refresh - it checks and refreshes tokens before each API request if they're close to expiration.
How It Works (Lazy Mode)
- When you call
login()orverify2FALogin(), the SDK automatically stores the access token internally - Before each API request, the SDK checks if the token is close to expiration
- If the token will expire within
refreshThresholdSeconds(default: 60 seconds), it automatically refreshes - The refresh happens in the background, transparent to your application
- All subsequent requests use the new token
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.
Configuration
const client = new ACPAuthClient({
baseUrl: 'https://sso.artatol.net',
apiKey: 'your-api-key',
autoRefresh: true, // Enable auto-refresh (default: true)
refreshThresholdSeconds: 60 // Refresh 60s before expiration (default: 60)
});
// After login, the token is automatically managed
const result = await client.login({ email: '...', password: '...' });
// All subsequent calls automatically use and refresh the token
const user = await client.me(); // No need to pass accessToken
await client.setup2FA({ password: '...' }); // Token automatically refreshed if neededManual Token Management
You can also manually manage tokens if needed:
// Set token manually
client.setAccessToken('your-token', 300); // 300 seconds expiry
// Get current token
const token = client.getAccessToken();
// Clear token
client.setAccessToken(null);Disabling Auto-Refresh
If you prefer to handle token refresh manually:
const client = new ACPAuthClient({
baseUrl: 'https://sso.artatol.net',
apiKey: 'your-api-key',
autoRefresh: false // Disable auto-refresh
});
// Manually refresh when needed
const { accessToken } = await client.refresh();
client.setAccessToken(accessToken, 300);Error Handling
import { ACPAuthError } from '@artatol-acp/auth-js';
try {
await client.login({ email: '[email protected]', password: 'wrong' });
} catch (error) {
if (error instanceof ACPAuthError) {
console.error('Auth error:', error.message);
console.error('Status code:', error.statusCode);
}
}License
MIT
