npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gsarthak783/accesskit-auth

v1.2.6

Published

JavaScript/TypeScript SDK for AccessKit Authentication System - Easy auth integration for any project

Readme

@gsarthak783/accesskit-auth

JavaScript/TypeScript SDK for AccessKit Authentication System - Easy auth integration for any project.

npm version License: MIT

🚀 Quick Start

Installation

npm install @gsarthak783/accesskit-auth

Basic 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

  1. Visit the AccessKit Dashboard
  2. Create an account or login
  3. Create a new project
  4. 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

  1. Automatic Initialization: When you create an AuthClient instance, it automatically checks for stored tokens
  2. Token Validation: If tokens exist, it validates them by fetching the user profile
  3. State Updates: The current authentication state is emitted via onAuthStateChange
  4. 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

  1. Always use onAuthStateChange for initial auth state detection
  2. Don't assume immediate availability - the initial auth check is asynchronous
  3. Handle loading states - show a loading indicator while checking auth state
  4. 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

  1. 401 Unauthorized: Check your API key and project ID
  2. 403 Forbidden: Ensure your project allows user registration
  3. 429 Too Many Requests: Implement rate limiting in your app
  4. 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

📄 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 onAuthStateChange to properly wait for initialization
  • Better error handling for expired tokens on app startup

Version 1.2.0

  • Added updatePassword method for secure password changes
  • Added updateEmail method for email updates with verification
  • Added reauthenticateWithCredential method 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 onAuthStateChange method for Firebase-like auth state management
  • Added getCurrentUser method 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 authStateChange event 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