@gsarthak783/accesskit-auth
v1.2.6
Published
JavaScript/TypeScript SDK for AccessKit Authentication System - Easy auth integration for any project
Maintainers
Readme
@gsarthak783/accesskit-auth
JavaScript/TypeScript SDK for AccessKit Authentication System - Easy auth integration for any project.
🚀 Quick Start
Installation
npm install @gsarthak783/accesskit-authBasic Usage
import { AuthClient } from '@gsarthak783/accesskit-auth';
// Initialize the client
const auth = new AuthClient({
projectId: 'your-project-id',
apiKey: 'your-api-key',
// baseUrl is automatically set to https://access-kit-server.vercel.app/api/project-users
});
// Register a new user
const user = await auth.register({
email: '[email protected]',
password: 'securepassword',
firstName: 'John',
lastName: 'Doe'
});
// Login
const loginResponse = await auth.login({
email: '[email protected]',
password: 'securepassword'
});
// Check if user is authenticated
if (auth.isAuthenticated()) {
const profile = await auth.getProfile();
console.log('User profile:', profile);
}📖 Configuration
AuthConfig Options
interface AuthConfig {
projectId: string; // Your project ID from AccessKit dashboard
apiKey: string; // Your project API key
baseUrl?: string; // API base URL (defaults to live server)
timeout?: number; // Request timeout (default: 10000ms)
}Note: The SDK does not automatically retry failed authentication requests (login, register, logout). Authentication errors will fail immediately to prevent rate limiting issues.
Get Your API Keys
- Visit the AccessKit Dashboard
- Create an account or login
- Create a new project
- Copy your Project ID and API Key from the project settings
🔧 Core Methods
Authentication State Management
The SDK provides Firebase-like authentication state management with automatic persistence across page refreshes.
How It Works
- Automatic Initialization: When you create an
AuthClientinstance, it automatically checks for stored tokens - Token Validation: If tokens exist, it validates them by fetching the user profile
- State Updates: The current authentication state is emitted via
onAuthStateChange - Persistence: Tokens are stored in localStorage (or your custom storage) and persist across page refreshes
onAuthStateChange
Subscribe to authentication state changes, including the initial state on page load:
// This will be called immediately with the current state (from stored tokens if any)
// and again whenever the auth state changes (login, logout, token refresh, etc.)
const unsubscribe = client.onAuthStateChange((user, isAuthenticated) => {
if (isAuthenticated && user) {
console.log('User is logged in:', user.email);
// User remains logged in even after page refresh
} else {
console.log('User is not logged in');
}
});
// Clean up when done
unsubscribe();Authentication Flow on Page Refresh
// 1. User logs in
await client.login({ email: '[email protected]', password: 'password' });
// Tokens are stored in localStorage
// 2. Page refreshes or user navigates away and comes back
const newClient = new AuthClient(config);
// 3. onAuthStateChange is called with the persisted user state
newClient.onAuthStateChange((user, isAuthenticated) => {
// This is called immediately with the user data if tokens are valid
// No need to login again!
console.log('User still logged in:', user?.email);
});getCurrentUser
Get the current user synchronously (useful after initialization):
const user = client.getCurrentUser();
if (user) {
console.log('Current user:', user.email);
}isAuthenticated
Check authentication status synchronously:
if (client.isAuthenticated()) {
// User is logged in with valid tokens
}Best Practices
- Always use onAuthStateChange for initial auth state detection
- Don't assume immediate availability - the initial auth check is asynchronous
- Handle loading states - show a loading indicator while checking auth state
- Clean up subscriptions - always call the unsubscribe function when done
Authentication
// Register new user
const user = await auth.register({
email: string,
password: string,
firstName: string,
lastName: string,
username?: string,
customFields?: object
});
// Login user
const { user, accessToken } = await auth.login({
email: string,
password: string
});
// Logout user
await auth.logout();
// Request password reset
await auth.requestPasswordReset('[email protected]');
// Reset password with token
await auth.resetPassword('reset-token', 'new-password');
// Verify email
await auth.verifyEmail('verification-token');Profile Management
// Get current user profile
const profile = await auth.getProfile();
// Update user profile
const updatedUser = await auth.updateProfile({
firstName: 'John',
lastName: 'Doe',
avatar: 'https://example.com/avatar.jpg',
customFields: { theme: 'dark' }
});Account Security
// Update password (requires current password)
try {
await auth.updatePassword({
currentPassword: 'old-password',
newPassword: 'new-secure-password'
});
console.log('Password updated successfully');
// Note: This will log out the user from all sessions
} catch (error) {
console.error('Password update failed:', error.message);
}
// Update email (requires password verification)
try {
const result = await auth.updateEmail({
newEmail: '[email protected]',
password: 'current-password'
});
console.log('Email updated:', result.email);
console.log('Verification required:', !result.isVerified);
} catch (error) {
console.error('Email update failed:', error.message);
}
// Reauthenticate for sensitive operations
try {
const result = await auth.reauthenticateWithCredential({
password: 'current-password'
});
console.log('Reauthenticated at:', result.authenticatedAt);
// Now you can perform sensitive operations
} catch (error) {
console.error('Reauthentication failed:', error.message);
}Practical Example: Secure Account Deletion
// Example: Implementing secure account deletion with reauthentication
async function deleteAccountSecurely(auth) {
try {
// Step 1: Reauthenticate the user
console.log('Please confirm your password to continue...');
const reauthResult = await auth.reauthenticateWithCredential({
password: getUserPasswordInput() // Your UI function to get password
});
console.log('Identity verified at:', reauthResult.authenticatedAt);
// Step 2: Show final confirmation
const confirmed = await showConfirmationDialog(
'Are you sure you want to delete your account? This action cannot be undone.'
);
if (!confirmed) {
console.log('Account deletion cancelled');
return;
}
// Step 3: Proceed with account deletion
// Note: You would need to implement the deleteAccount method
// await auth.deleteAccount();
console.log('Account deleted successfully');
} catch (error) {
if (error.message.includes('Password is incorrect')) {
console.error('Authentication failed. Please check your password.');
} else {
console.error('Error:', error.message);
}
}
}User Management
// Get user profile
const profile = await auth.getProfile();
// Update profile
const updatedUser = await auth.updateProfile({
firstName: 'Updated Name',
customFields: { role: 'admin' }
});
// Request password reset
await auth.requestPasswordReset('[email protected]');
// Reset password with token
await auth.resetPassword('reset-token', 'newpassword');
// Verify email with token
await auth.verifyEmail('verification-token');Token Management
// Get current access token
const token = auth.getAccessToken();
// Refresh access token
const newToken = await auth.refreshAccessToken();
// Tokens are automatically managed by the SDK🔐 Admin Functions
User Administration (Requires API Key)
// Get all users (admin only)
const users = await auth.getAllUsers({
page: 1,
limit: 50,
search: '[email protected]',
status: 'active'
});
// Delete user (admin only)
await auth.deleteUser('user-id');
// Update user status (admin only)
await auth.updateUserStatus('user-id', 'suspended');
// Get user statistics
const stats = await auth.getStats();🎯 Advanced Usage
Custom Storage
import { AuthClient, TokenStorage } from '@gsarthak783/accesskit-auth';
// Custom token storage implementation
class CustomStorage implements TokenStorage {
getItem(key: string): string | null {
return localStorage.getItem(key);
}
setItem(key: string, value: string): void {
localStorage.setItem(key, value);
}
removeItem(key: string): void {
localStorage.removeItem(key);
}
}
const auth = new AuthClient(config, new CustomStorage());Event Handling
// Listen to authentication events
auth.on('login', (data) => {
console.log('User logged in:', data.user);
});
auth.on('logout', () => {
console.log('User logged out');
});
auth.on('token_refresh', (data) => {
console.log('Token refreshed:', data.accessToken);
});
auth.on('error', (error) => {
console.error('Auth error:', error);
});Error Handling
try {
await auth.login({ email: 'invalid', password: 'wrong' });
} catch (error) {
if (error.response?.status === 401) {
console.log('Invalid credentials');
} else if (error.response?.status === 429) {
console.log('Too many attempts, try again later');
} else {
console.log('Login failed:', error.message);
}
}🌐 Framework Integration
Node.js/Express
const express = require('express');
const { AuthClient } = require('@gsarthak783/accesskit-auth');
const app = express();
const auth = new AuthClient({ projectId: 'xxx', apiKey: 'xxx' });
app.post('/api/register', async (req, res) => {
try {
const user = await auth.register(req.body);
res.json({ success: true, user });
} catch (error) {
res.status(400).json({ success: false, error: error.message });
}
});Next.js
// pages/api/auth/register.js
import { AuthClient } from '@gsarthak783/accesskit-auth';
const auth = new AuthClient({
projectId: process.env.AUTH_PROJECT_ID,
apiKey: process.env.AUTH_API_KEY
});
export default async function handler(req, res) {
if (req.method === 'POST') {
try {
const user = await auth.register(req.body);
res.status(200).json({ user });
} catch (error) {
res.status(400).json({ error: error.message });
}
}
}📋 API Reference
AuthClient Class
class AuthClient {
constructor(config: AuthConfig, storage?: TokenStorage)
// Authentication
register(userData: CreateUserData): Promise<AuthResponse>
login(credentials: LoginCredentials): Promise<AuthResponse>
logout(): Promise<void>
isAuthenticated(): boolean
// User Management
getProfile(): Promise<User>
updateProfile(userData: UpdateUserData): Promise<User>
requestPasswordReset(email: string): Promise<void>
resetPassword(token: string, password: string): Promise<void>
verifyEmail(token: string): Promise<void>
// Account Security
updatePassword(data: ChangePasswordData): Promise<void>
updateEmail(data: UpdateEmailData): Promise<{ email: string; isVerified: boolean }>
reauthenticateWithCredential(data: ReauthenticateData): Promise<{ authenticated: boolean; authenticatedAt: string }>
// Token Management
getAccessToken(): string | null
refreshAccessToken(): Promise<string>
// Admin Functions
getAllUsers(options?: GetUsersOptions): Promise<ApiResponse<User[]>>
deleteUser(userId: string): Promise<void>
updateUserStatus(userId: string, status: string): Promise<void>
getStats(): Promise<ApiResponse<object>>
// Events
on(event: string, callback: Function): void
off(event: string, callback: Function): void
}Type Definitions
interface User {
id: string;
email: string;
username?: string;
firstName: string;
lastName?: string;
isVerified: boolean;
isActive: boolean;
customFields?: Record<string, any>;
createdAt: string;
lastLogin?: string;
}
interface CreateUserData {
email: string;
password: string;
firstName: string;
lastName?: string;
username?: string;
customFields?: object;
}
interface LoginCredentials {
email: string;
password: string;
}
interface AuthResponse {
user: User;
accessToken: string;
refreshToken: string;
}
interface ChangePasswordData {
currentPassword: string;
newPassword: string;
}
interface UpdateEmailData {
newEmail: string;
password: string;
}
interface ReauthenticateData {
password: string;
}🛠️ Development
Environment Variables
# For testing
AUTH_PROJECT_ID=your-test-project-id
AUTH_API_KEY=your-test-api-key
AUTH_BASE_URL=https://access-kit-server.vercel.app/api/project-users🐛 Troubleshooting
Common Issues
- 401 Unauthorized: Check your API key and project ID
- 403 Forbidden: Ensure your project allows user registration
- 429 Too Many Requests: Implement rate limiting in your app
- Network errors: Verify the base URL and internet connection
Debug Mode
const auth = new AuthClient({
projectId: 'xxx',
apiKey: 'xxx',
debug: true // Enable debug logging
});📞 Support
- Documentation: https://access-kit.vercel.app/
- npm Package: https://npmjs.com/package/@gsarthak783/accesskit-auth
📄 License
MIT License - see LICENSE file for details.
📝 Changelog
Version 1.2.2 (Latest)
- CRITICAL FIX: Fixed token storage during login/register - tokens are now correctly saved from the nested response structure
- Fixed refresh token endpoint to handle the correct response format
- Updated AuthResponse type to match actual API response structure
Version 1.2.1
- Fixed authentication persistence across page refreshes
- Improved token refresh handling during initialization
- Enhanced
onAuthStateChangeto properly wait for initialization - Better error handling for expired tokens on app startup
Version 1.2.0
- Added
updatePasswordmethod for secure password changes - Added
updateEmailmethod for email updates with verification - Added
reauthenticateWithCredentialmethod for sensitive operations - Password changes now invalidate all sessions for security
- Email updates trigger re-verification process
- Added TypeScript interfaces for all new methods
Version 1.1.0
- Added
onAuthStateChangemethod for Firebase-like auth state management - Added
getCurrentUsermethod to get user without API call - Automatic auth state persistence across page refreshes
- Auto-initialization on SDK instantiation
- Improved React SDK to use centralized auth state management
- Added
authStateChangeevent for custom event handling
Version 1.0.5
- Fixed authentication retry loop issue that was causing excessive API calls
- Updated logout method to properly send refresh token
- Removed automatic retries for authentication endpoints (login, register, logout)
- Authentication errors now fail immediately without retrying
Version 1.0.4
- Initial stable release
Built with ❤️ by the AccessKit Team
