JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 39
  • Score
    100M100P100Q78273F
  • License MIT

Complete authentication solution with OAuth, API keys, email, SAML, and subscription management

Package Exports

  • @kitiumai/auth
  • @kitiumai/auth/dist/index.js
  • @kitiumai/auth/dist/index.mjs

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@kitiumai/auth) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@kitium/auth (Kitium Auth Core)

Complete, production-ready authentication system for Node/TypeScript/Next.js apps.

Features:

  • 🔐 Email/Password Authentication - Register, login, password reset with Argon2 hashing
  • 🔑 OAuth Flows - Google, GitHub, Microsoft, Discord, generic OIDC
  • 🎫 API Keys - Issue, verify, revoke with optional caching
  • 📝 Sessions - Create, refresh, delete with signed JWT tokens
  • 👥 User Management - Create, update, delete with OAuth linking
  • 🏢 Organizations - Multi-tenant support with roles
  • 💌 Email Templates - Professional HTML/text templates for all auth flows
  • ⚙️ Extensible Architecture - Pluggable storage, cache, and billing adapters
  • 🛡️ Security First - Argon2 password hashing, rate limiting ready, CSRF tokens
  • 📊 Environment Driven - Everything configurable via environment variables

Installation

npm install @kitiumai/auth

With MongoDB storage:

npm install @kitiumai/auth @kitiumai/auth-mongodb mongodb

With PostgreSQL storage:

npm install @kitiumai/auth @kitiumai/auth-postgres pg

Quick Start

With MongoDB and Email/Password Auth

import { AuthCore, defineConfig, createEmailProvider, createOAuthProvider } from '@kitiumai/auth'
import { MongoDBStorageAdapter } from '@kitiumai/auth-mongodb'
import { SMTPEmailProvider } from '@kitiumai/auth'

// Create MongoDB adapter
const adapter = new MongoDBStorageAdapter(process.env.MONGODB_URI!, {
  dbName: 'kitium-auth'
})

// Define configuration
const config = defineConfig({
  appUrl: process.env.NEXT_PUBLIC_APP_URL!,
  providers: [
    createEmailProvider({ id: 'email', from: process.env.EMAIL_FROM! }),
    createOAuthProvider({
      id: 'google',
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!
    })
  ],
  storage: { driver: 'mongodb', url: process.env.MONGODB_URI! },
  apiKeys: { prefix: 'kit_', hash: { algo: 'argon2id' } },
  sessions: { cookieName: 'auth_token', ttlSeconds: 604800 } // 7 days
})

// Create auth instance
const auth = new AuthCore(adapter, {
  jwtSecret: process.env.JWT_SECRET!,
  providers: config.providers
})

// Connect and initialize
await adapter.connect()

With In-Memory Storage (Development)

import { AuthCore } from '@kitiumai/auth'
import { MemoryStorageAdapter } from '@kitiumai/auth'

const adapter = new MemoryStorageAdapter()
const auth = new AuthCore(adapter, {
  jwtSecret: 'dev-secret',
  providers: []
})

await adapter.connect()

OAuth Authorization URL

const { url, state, codeVerifier } = auth.getOAuthAuthorizationUrl(
  'google',
  'https://your.app/api/auth/callback/google'
)
// redirect user to `url`

OAuth Callback

// After user returns from provider
const result = await auth.handleOAuthCallback('google', code, state, codeVerifier)
// result = { userId, session, profile, tokens }

API Keys

// Issue
const issued = await auth.issueApiKey({ principalId: 'user_123', scopes: ['api.read'] })
// { id, key, prefix, lastFour, createdAt, expiresAt }

// Verify
try {
  const verification = await auth.verifyApiKey('kit_abcdef...')
  // { valid, principalId, scopes, plan, orgId, keyId, expiresAt, rateLimit }
} catch (e) {
  // handle invalid/expired/not found
}

// Revoke
await auth.revokeApiKey(issued.id)

Sessions

const session = await auth.createSession('user_123')
const token = await auth.generateSessionToken(session.id)

// Get/refresh/delete
const current = await auth.getSession(session.id)
const refreshed = await auth.refreshSession(session.id)
await auth.deleteSession(session.id)

Users and Organizations

// Users
const user = await auth.createUser({ email: 'a@b.com', name: 'Alice' })
await auth.updateUser(user.id, { plan: 'pro' })
await auth.deleteUser(user.id)

// Plans
await auth.addPlan({ id: 'pro', entitlements: ['api.read', 'api.write'] })
const plan = await auth.getPlan('pro')

// Orgs
const org = await auth.createOrganization({ name: 'ACME', plan: 'pro', ownerId: 'user_123' })
const orgData = await auth.getOrganization(org.id)

Email/Password Authentication

Password Hashing

import { hashPassword, verifyPassword } from '@kitiumai/auth'

// Hash with default settings (Argon2id)
const hash = await hashPassword('userPassword123')

// Hash with custom Argon2 parameters
const customHash = await hashPassword('userPassword123', {
  timeCost: 4,
  memory: 131072,  // 128MB
  parallelism: 8,
  type: 'argon2id'
})

// Verify password
const isValid = await verifyPassword('userPassword123', hash)
if (!isValid) {
  throw new AuthenticationError('Invalid password')
}

Password Validation

import { validatePasswordStrength } from '@kitiumai/auth'

// Validate with default rules
const result = validatePasswordStrength('MyPassword123!')
if (!result.valid) {
  console.log(result.errors) // ['Password must contain uppercase...']
}

// Validate with custom rules
const customResult = validatePasswordStrength('MyPassword123!', {
  minLength: 12,
  maxLength: 64,
  requireLowercase: true,
  requireUppercase: true,
  requireNumbers: true,
  requireSpecialChars: true,
  specialCharsPattern: '!@#$%^&*'
})

if (!customResult.valid) {
  console.log(customResult.errors)
}

Email Utilities

import { validateEmail, normalizeEmail } from '@kitiumai/auth'

// Normalize email (lowercase)
const normalized = normalizeEmail('John@EXAMPLE.COM')
// 'john@example.com'

// Validate email format
if (validateEmail(normalized)) {
  console.log('Valid email address')
} else {
  throw new ValidationError('Invalid email format')
}

Email Templates

import { getEmailTemplates } from '@kitiumai/auth'

const {
  createPasswordResetTemplate,
  createEmailVerificationTemplate,
  createVerificationCodeTemplate,
  createLoginLinkTemplate,
  createWelcomeTemplate
} = await getEmailTemplates()

// Password reset email
const resetEmail = createPasswordResetTemplate(
  'https://example.com/reset?token=abc123def456',
  {
    appName: 'My App',
    userName: 'John Doe',
    expiresIn: '24 hours',
    supportEmail: 'support@myapp.com'
  }
)

// Send via your email provider
await emailProvider.sendMail({
  to: 'user@example.com',
  subject: resetEmail.subject,
  html: resetEmail.html,
  text: resetEmail.text
})

// Email verification email
const verifyEmail = createEmailVerificationTemplate(
  'https://example.com/verify?token=xyz789',
  {
    appName: 'My App',
    userName: 'Jane Smith',
    expiresIn: '7 days',
    supportEmail: 'support@myapp.com'
  }
)

// Login link email
const loginEmail = createLoginLinkTemplate(
  'https://example.com/login?token=abc123',
  {
    appName: 'My App',
    expiresIn: '15 minutes',
    supportEmail: 'support@myapp.com'
  }
)

// Welcome email
const welcomeEmail = createWelcomeTemplate({
  appName: 'My App',
  userName: 'Alice Johnson',
  appUrl: 'https://example.com',
  supportEmail: 'support@myapp.com'
})

Email Authentication Routes (Next.js)

import { getEmailAuthRoutes } from '@kitiumai/auth'
import { MongoDBStorageAdapter } from '@kitiumai/auth-mongodb'

const adapter = new MongoDBStorageAdapter(process.env.MONGODB_URI!)

const {
  createRegisterRoute,
  createLoginRoute,
  createForgotPasswordRoute,
  createResetPasswordRoute
} = await getEmailAuthRoutes()

const emailConfig = {
  appUrl: process.env.NEXT_PUBLIC_APP_URL!,
  emailProvider: yourEmailProvider,

  // All configurable (these are defaults)
  minNameLength: 2,
  maxNameLength: 255,
  sessionTtlSeconds: 7 * 24 * 60 * 60,      // 7 days
  passwordResetTokenTtlSeconds: 60 * 60,    // 1 hour
  passwordResetTokenLength: 32,

  // Optional redirects after auth
  loginRedirect: '/dashboard',
  registerRedirect: '/onboarding'
}

// Use in Next.js API routes

// api/auth/register
export const POST = createRegisterRoute(adapter, emailConfig)

// api/auth/login
export const POST = createLoginRoute(adapter, emailConfig)

// api/auth/forgot-password
export const POST = createForgotPasswordRoute(adapter, emailConfig)

// api/auth/reset-password
export const POST = createResetPasswordRoute(adapter, emailConfig)

Environment Variables

# Database
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/
MONGODB_DB_NAME=kitium-auth

# Auth
JWT_SECRET=your-secret-key-here
NEXT_PUBLIC_APP_URL=https://example.com

# Email (SMTP)
EMAIL_FROM=noreply@example.com
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password

# OAuth (optional)
NEXT_PUBLIC_GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=xxx

Using with Adapters

  • Storage: use @kitiumai/auth-mongodb (MongoDB), @kitiumai/auth-postgres (PostgreSQL), or the in-memory adapter in this package for testing
  • Cache: use @kitiumai/auth-redis for Redis-backed caching
  • Billing: use @kitiumai/auth-stripe for Stripe subscriptions/billing

MongoDB Storage Adapter

For production MongoDB deployments, install the dedicated adapter:

npm install @kitiumai/auth @kitiumai/auth-mongodb mongodb

See @kitiumai/auth-mongodb package documentation for detailed configuration, best practices, and troubleshooting.

Error Handling

All methods throw rich errors with specific types:

import {
  AuthError,
  ValidationError,
  AuthenticationError,
  AuthorizationError,
  NotFoundError,
  ConflictError,
  RateLimitError,
  OAuthError,
  SessionError,
  ApiKeyError,
  DatabaseError,
  ConfigurationError,
  getStatusCode,
  formatErrorResponse
} from '@kitiumai/auth'

try {
  const result = await auth.verifyApiKey(apiKey)
} catch (error) {
  if (error instanceof ApiKeyError) {
    // Handle API key errors
    const statusCode = getStatusCode(error)
    const response = formatErrorResponse(error)
    return res.status(statusCode).json(response)
  } else if (error instanceof RateLimitError) {
    // Handle rate limiting
    return res.status(429).json({ message: 'Too many requests' })
  } else if (error instanceof ValidationError) {
    // Handle validation errors
    return res.status(400).json({ message: error.message })
  } else {
    // Generic error handling
    return res.status(500).json({ message: 'Internal server error' })
  }
}

Rate Limiting

The package provides rate limiting utilities ready for production:

import { getRateLimiter, getRateLimitMiddleware } from '@kitiumai/auth'

// Initialize rate limiter
const { RateLimiter, generateRateLimitKey, generateRateLimitHeaders } = await getRateLimiter()

const rateLimiter = new RateLimiter({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  maxRequests: 100,
  keyGenerator: (req) => req.ip || req.socket.remoteAddress
})

// Use in API routes
const key = generateRateLimitKey(req)
const limit = await rateLimiter.check(key)

if (!limit.allowed) {
  const headers = generateRateLimitHeaders(limit)
  return res.status(429).set(headers).json({ message: 'Rate limit exceeded' })
}

TypeScript

The package is fully typed with strict TypeScript support:

import type {
  User,
  UserRecord,
  Session,
  SessionRecord,
  Plan,
  Organization,
  OrganizationRecord,
  OAuthProfile,
  OAuthCallbackResult,
  IssueApiKeyResult,
  VerifyApiKeyResult,
  PasswordValidationRules,
  PasswordHashOptions,
  EmailAuthRoutesConfig
} from '@kitiumai/auth'

const user: UserRecord = await storage.getUser(userId)
const config: EmailAuthRoutesConfig = {
  appUrl: 'https://example.com',
  emailProvider: emailProvider,
  minNameLength: 2
}

License

MIT