@onurege3467/zeroauth
v1.0.0
Published
Universal session management package for Node.js and React/Next.js
Downloads
60
Maintainers
Readme
🚀 @onurege3467/zeroauth
Universal Session Management Package for Node.js, React, and Next.js
A comprehensive, enterprise-grade session management and authentication library designed for universal deployment across Node.js servers, React applications, and Next.js frameworks. This package provides a unified API for handling authentication with multiple strategies, supporting various databases including the native @onurege3467/zerohelper integration, and offering robust security features.
📋 Table of Contents
- Introduction
- Features
- Installation
- Quick Start
- Configuration Guide
- Authentication Strategies
- Database Adapters
- Token Storage
- Security Features
- Cache System
- Frontend Integration
- Backend Integration
- API Reference
- Examples
- TypeScript Support
- Best Practices
- Troubleshooting
- Contributing
- License
- Support
1. Introduction
What is @onurege3467/zeroauth?
The @onurege3467/zeroauth package is a universal authentication and session management solution that works seamlessly across frontend and backend environments. It is designed to provide a consistent authentication experience whether you are building a React single-page application, a Next.js server-rendered application, or a traditional Node.js REST API.
This library was created with the following core principles in mind:
- Universality: Works identically on both client and server sides, supporting multiple frameworks including React, Next.js, Express, and Fastify
- Type Safety: Built with TypeScript from the ground up, providing 100% type inference and autocomplete support
- Security First: Implements industry-standard security practices including AES-256-GCM encryption, CSRF protection, rate limiting, and session fixation prevention
- Flexibility: Supports multiple authentication strategies, storage mechanisms, and database adapters
- Performance: Optimized for high-traffic applications with Redis caching and efficient session management
Why Use @onurege3467/zeroauth?
Modern web applications require sophisticated authentication mechanisms that can handle various scenarios including traditional username/password login, OAuth2 social login, passwordless authentication via passkeys, and API-based authentication for microservices. This package consolidates all these requirements into a single, cohesive solution.
The package integrates natively with @onurege3467/zerohelper, a powerful database framework that provides multiple database adapters including ZPack (binary), TOON, PostgreSQL, MySQL, SQLite, and MongoDB. This integration allows for seamless data persistence while maintaining high performance and reliability.
2. Features
2.1 Authentication Strategies
The package supports six different authentication strategies, each designed for specific use cases:
| Strategy | Description | Use Case | |----------|-------------|----------| | JWT | JSON Web Token with support for HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512 | Stateless authentication for distributed systems | | Session | Server-side session management with automatic cleanup | Traditional web applications | | OAuth2 | Social authentication with Google and Apple support | Social login integration | | Passkey | WebAuthn-based passwordless authentication | Modern passwordless login experiences | | API Key | API key authentication for service-to-service communication | Microservices and API access | | Refresh Token | Automatic token refresh with rotation and reuse detection | Secure token lifecycle management |
2.2 Database Support
Built-in support for multiple database systems with automatic schema management:
- @onurege3467/zerohelper (Primary - Native): High-performance binary database with zero configuration
- PostgreSQL: Enterprise-grade relational database with connection pooling
- MySQL: Popular relational database with InnoDB storage engine
- SQLite: Lightweight embedded database for single-instance applications
- MongoDB: Flexible document database for schema-less requirements
2.3 Token Storage Options
Multiple storage mechanisms for different deployment scenarios:
- Cookie: HTTP-only, Secure, SameSite-aware cookies for maximum security
- LocalStorage: Browser localStorage with optional encryption for client-side applications
- SessionStorage: Session-scoped storage with automatic cleanup
- Bearer Token: HTTP Authorization header for API authentication
2.4 Security Features
Comprehensive security implementation includes:
- AES-256-GCM Encryption: Military-grade encryption for sensitive data
- Rate Limiting: Configurable request throttling to prevent brute force attacks
- CSRF Protection: Double-submit cookie pattern for cross-site request forgery prevention
- Session Fixation Protection: Automatic session ID regeneration on privilege changes
- Security Headers: Automatic injection of Content Security Policy, HSTS, and other security headers
- XSS Protection: Input sanitization and output encoding
2.5 Cache System
Optimized caching for high-performance applications:
- In-Memory LRU Cache: Least-recently-used cache for single-instance deployments
- Redis Cache: Distributed caching for multi-instance deployments with pub/sub support
2.6 Framework Integration
First-class support for popular frameworks:
- React: Comprehensive hooks and context providers
- Next.js: App Router and Pages Router middleware support
- Express: Route-level middleware with authentication guards
- Fastify: Plugin-based integration with typed decorators
3. Installation
3.1 Basic Installation
Install the package using npm, yarn, or pnpm:
# Using npm
npm install @onurege3467/zeroauth
# Using yarn
yarn add @onurege3467/zeroauth
# Using pnpm
pnpm add @onurege3467/zeroauth3.2 Peer Dependencies
The package requires the following peer dependencies. Some are optional based on your use case:
# Required peer dependencies
npm install @onurege3467/zerohelper uuid ioredis
# Optional: Database drivers (install only what you need)
npm install pg # PostgreSQL support
npm install mysql2 # MySQL support
npm install better-sqlite3 # SQLite support
npm install mongodb # MongoDB support3.3 TypeScript Configuration
Ensure your tsconfig.json includes the following settings for optimal TypeScript support:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist",
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}3.4 Environment Requirements
- Node.js 20.0.0 or higher
- TypeScript 5.0.0 or higher
- Modern browsers with ES2022 support (for client-side usage)
4. Quick Start
4.1 Basic Next.js Setup
Create a new file lib/auth.ts in your Next.js project:
// lib/auth.ts
import { createAuth } from '@onurege3467/zeroauth';
export const auth = createAuth({
database: {
adapter: 'zerohelper',
config: {
adapter: 'zpack',
config: {
path: './data/sessions.zpack',
indexFields: {
sessions: ['userId', 'expiresAt', 'active']
}
}
},
cache: {
type: 'memory',
ttl: 300000,
maxSize: 10000
}
},
storage: {
type: 'cookie',
config: {
name: 'za_session',
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 86400 * 7
}
},
session: {
expiresIn: 3600,
updateAge: 300,
absoluteExpiresIn: 86400 * 30
},
strategies: [
{
type: 'jwt',
config: {
algorithm: 'RS256',
secretOrKey: process.env.JWT_PRIVATE_KEY!,
publicKey: process.env.JWT_PUBLIC_KEY,
issuer: 'your-app',
audience: 'your-users'
}
},
{
type: 'refresh-token',
config: {
expiresIn: '30d',
rotation: true,
reuseDetection: true
}
}
],
callbacks: {
onLogin: async (user, session) => {
console.log(`User ${user.email} logged in`);
},
onLogout: async (user, session) => {
console.log(`User ${user.email} logged out`);
}
}
});4.2 Express.js Setup
Create an authentication middleware in your Express application:
// app.ts
import express from 'express';
import { createAuth, createExpressMiddleware } from '@onurege3467/zeroauth';
import { PostgreSQLAdapter } from '@onurege3467/zeroauth/database';
const app = express();
app.use(express.json());
const auth = createAuth({
database: {
adapter: 'postgres',
config: {
host: process.env.DB_HOST!,
port: 5432,
database: process.env.DB_NAME!,
user: process.env.DB_USER!,
password: process.env.DB_PASSWORD!,
tablePrefix: 'za_'
}
},
storage: {
type: 'bearer',
config: {
header: 'Authorization',
prefix: 'Bearer'
}
},
strategies: [
{
type: 'jwt',
config: {
algorithm: 'HS256',
secretOrKey: process.env.JWT_SECRET!
}
},
{
type: 'api-key',
config: {
headerName: 'X-API-Key'
}
}
]
});
// Apply authentication middleware to protected routes
app.use('/api', createExpressMiddleware(auth)({
strategies: ['jwt', 'api-key'],
credentialsRequired: true
}));
// Protected route
app.get('/api/profile', (req, res) => {
res.json({ user: req.user });
});
// Public route
app.post('/api/auth/login', async (req, res) => {
const { email, password } = req.body;
try {
const session = await auth.login(email, password, {
strategy: 'jwt'
});
res.json({
accessToken: session.tokens.accessToken,
refreshToken: session.tokens.refreshToken,
expiresIn: session.tokens.expiresIn
});
} catch (error) {
res.status(401).json({
error: 'Invalid credentials'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});5. Configuration Guide
5.1 Complete Configuration Interface
The following TypeScript interface demonstrates all available configuration options:
interface ZeroAuthConfig<User = DefaultUser, SessionData = DefaultSession> {
database: {
adapter: 'zerohelper' | 'postgres' | 'mysql' | 'sqlite' | 'mongodb';
config: Record<string, unknown>;
cache?: {
type: 'memory' | 'redis';
ttl?: number;
maxSize?: number;
host?: string;
port?: number;
};
};
storage: {
type: 'cookie' | 'localstorage' | 'sessionstorage' | 'bearer';
config: CookieStorageConfig | LocalStorageConfig | BearerStorageConfig;
};
session?: {
expiresIn?: number;
updateAge?: number;
absoluteExpiresIn?: number;
slidingExpiration?: boolean;
};
security?: {
rateLimit?: {
windowMs?: number;
maxRequests?: number;
};
encryption?: {
enabled?: boolean;
key?: string;
};
csrf?: {
enabled?: boolean;
};
headers?: {
enabled?: boolean;
};
};
strategies: Array<{
type: AuthStrategy;
config: JWTConfig | SessionConfig | OAuth2Config | PasskeyConfig | APIKeyConfig | RefreshTokenConfig;
}>;
callbacks?: {
onLogin?: (user: User, session: SessionData) => Promise<void> | void;
onLogout?: (user: User, session: SessionData) => Promise<void> | void;
onSessionCreate?: (session: SessionData) => Promise<void> | void;
onSessionDestroy?: (session: SessionData) => Promise<void> | void;
onSessionRefresh?: (session: SessionData, newToken: string) => Promise<void> | void;
onTokenRefresh?: (oldToken: string, newToken: string, session: SessionData) => Promise<void> | void;
onError?: (error: Error, context: string) => Promise<void> | void;
};
}5.2 Configuration Options Explained
Database Configuration
The database adapter handles session persistence. Each adapter has specific configuration requirements:
ZeroHelper (Primary):
{
adapter: 'zerohelper',
config: {
adapter: 'zpack' | 'toon' | 'postgres' | 'mysql' | 'mongodb' | 'sqlite',
config: {
path?: string;
host?: string;
port?: number;
database?: string;
user?: string;
password?: string;
collectionPrefix?: string;
tablePrefix?: string;
indexFields?: Record<string, string[]>;
autoFlush?: boolean;
}
},
cache: {
type: 'memory' | 'redis',
ttl: 300000,
maxSize: 10000
}
}PostgreSQL:
{
adapter: 'postgres',
config: {
host: string;
port: number;
database: string;
user: string;
password: string;
tablePrefix?: string;
connectionLimit?: number;
},
cache: {
type: 'memory' | 'redis',
ttl: number;
}
}Storage Configuration
Storage adapters determine where tokens are stored:
Cookie Storage:
{
type: 'cookie',
config: {
name: string;
httpOnly: boolean;
secure: boolean;
sameSite: 'strict' | 'lax' | 'none';
domain?: string;
path?: string;
maxAge?: number;
partitioned?: boolean;
}
}Bearer Storage:
{
type: 'bearer',
config: {
header: string;
prefix: string;
caseSensitive: boolean;
}
}Session Configuration
Session behavior customization:
{
expiresIn: 3600, // Session expires in 1 hour
updateAge: 300, // Update session every 5 minutes
absoluteExpiresIn: 2592000, // Absolute timeout after 30 days
slidingExpiration: true // Extend session on activity
}6. Authentication Strategies
6.1 JWT Strategy
The JWT strategy implements JSON Web Token authentication with support for multiple signing algorithms:
const auth = createAuth({
strategies: [
{
type: 'jwt',
config: {
algorithm: 'RS256', // HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512
secretOrKey: process.env.JWT_PRIVATE_KEY!,
publicKey: process.env.JWT_PUBLIC_KEY,
issuer: 'your-application',
audience: 'your-users',
expiresIn: '1h',
notBefore: 0,
jwtid: undefined,
keyId: undefined
}
}
]
});Supported Algorithms:
| Algorithm | Type | Use Case | |-----------|------|----------| | HS256 | Symmetric | Simple deployments with shared secrets | | HS384 | Symmetric | Enhanced security with shared secrets | | HS512 | Symmetric | Maximum security with shared secrets | | RS256 | Asymmetric | Most common for production | | RS384 | Asymmetric | Enhanced RSA security | | RS512 | Asymmetric | Maximum RSA security | | ES256 | Asymmetric | Elliptic curve, small tokens | | ES384 | Asymmetric | Elliptic curve, medium tokens | | ES512 | Asymmetric | Elliptic curve, maximum security |
6.2 Session Strategy
Server-side session management with automatic cleanup:
const auth = createAuth({
strategies: [
{
type: 'session',
config: {
cookieName: 'session_id',
httpOnly: true,
secure: true,
sameSite: 'lax',
domain: undefined,
path: '/',
maxAge: 86400,
absoluteDuration: 604800,
slidingExpiration: true,
concurrentSessions: 'allow',
maxConcurrentSessions: 5
}
}
]
});6.3 OAuth2 Strategy
Google and Apple OAuth 2.0 integration:
const auth = createAuth({
strategies: [
{
type: 'oauth2',
config: {
provider: 'google',
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
redirectUri: 'https://yourapp.com/auth/callback/google',
scope: ['openid', 'email', 'profile'],
accessType: 'online',
prompt: 'consent',
hd: undefined // Google: hosted domain
}
}
]
});OAuth2 Flow:
// Redirect user to authorization URL
const authUrl = await auth.strategies.oauth2.getAuthorizationUrl(
state, // Generate and store state for CSRF protection
nonce // For ID token validation
);
// Handle callback
const tokens = await auth.strategies.oauth2.handleCallback(code, state);
const userInfo = await auth.strategies.oauth2.getUserInfo(tokens.accessToken);6.4 Passkey Strategy
WebAuthn/Passkey authentication for passwordless login:
const auth = createAuth({
strategies: [
{
type: 'passkey',
config: {
rpName: 'Your Application',
rpId: 'yourapp.com',
origin: 'https://yourapp.com',
timeout: 60000,
attestationType: 'none',
authenticatorSelection: {
userVerification: 'preferred',
residentKey: 'preferred',
requireResidentKey: false
}
}
}
]
});Registration Flow:
// Generate registration options
const options = auth.strategies.passkey.generateRegistrationOptions(
userId,
userEmail,
userName
);
// Create credential in browser
const credential = await navigator.credentials.create({
publicKey: options
});
// Verify registration
const isValid = await auth.strategies.passkey.verifyRegistration(
credential,
options.challenge,
userId
);6.5 API Key Strategy
Service-to-service authentication with API keys:
const auth = createAuth({
strategies: [
{
type: 'api-key',
config: {
headerName: 'X-API-Key',
keyPrefix: 'sk_live_',
keyLength: 32,
hashAlgorithm: 'sha256',
rotationEnabled: true,
rotationDays: 90,
scopes: ['read', 'write', 'admin'],
rateLimit: {
requests: 1000,
window: 3600000
}
}
}
]
});
// Create API key for a user
const apiKey = await auth.strategies.apiKey.createKey(
userId,
'Production API Key',
['read', 'write']
);
console.log(apiKey.key); // sk_live_xxxxxxxxxxxxxxxx6.6 Refresh Token Strategy
Secure token refresh with rotation and reuse detection:
const auth = createAuth({
strategies: [
{
type: 'refresh-token',
config: {
expiresIn: '30d',
reuseDetection: true,
reuseDetectionWindow: 5000,
rotation: true,
absoluteDuration: 2592000
}
}
]
});Refresh Token Flow:
// Exchange refresh token for new access token
const tokens = await auth.refresh(refreshToken);
// Automatic rotation - new refresh token is issued
// Old refresh token is invalidated (reuse detection enabled)7. Database Adapters
7.1 ZeroHelper Adapter (Primary)
The native ZeroHelper adapter provides the highest performance and seamless integration:
import { createAuth } from '@onurege3467/zeroauth';
const auth = createAuth({
database: {
adapter: 'zerohelper',
config: {
adapter: 'zpack',
config: {
path: './data/sessions.zpack',
indexFields: {
sessions: ['userId', 'expiresAt', 'active']
}
}
},
cache: {
type: 'memory',
ttl: 300000,
maxSize: 10000
}
}
});7.2 PostgreSQL Adapter
Enterprise-grade PostgreSQL support with connection pooling:
import { PostgreSQLAdapter } from '@onurege3467/zeroauth/database';
const adapter = new PostgreSQLAdapter({
config: {
host: 'localhost',
port: 5432,
database: 'sessions',
user: 'postgres',
password: 'password',
tablePrefix: 'za_',
connectionLimit: 10
},
cache: {
type: 'memory',
ttl: 300000
}
});7.3 MySQL Adapter
High-performance MySQL support:
import { MySQLAdapter } from '@onurege3467/zeroauth/database';
const adapter = new MySQLAdapter({
config: {
host: 'localhost',
port: 3306,
database: 'sessions',
user: 'root',
password: 'password',
tablePrefix: 'za_',
connectionLimit: 10
},
cache: {
type: 'memory',
ttl: 300000
}
});7.4 SQLite Adapter
Embedded database for lightweight deployments:
import { SQLiteAdapter } from '@onurege3467/zeroauth/database';
const adapter = new SQLiteAdapter({
config: {
path: './sessions.db',
tablePrefix: 'za_'
},
cache: {
type: 'memory',
ttl: 300000
}
});7.5 MongoDB Adapter
Flexible document database support:
import { MongoDBAdapter } from '@onurege3467/zeroauth/database';
const adapter = new MongoDBAdapter({
config: {
uri: 'mongodb://localhost:27017',
database: 'sessions',
collectionPrefix: 'za_'
},
cache: {
type: 'memory',
ttl: 300000
}
});8. Token Storage
8.1 Cookie Storage
HTTP-only cookies provide maximum security against XSS attacks:
const storage = new CookieStorage({
name: 'za_session',
httpOnly: true,
secure: true,
sameSite: 'lax',
domain: undefined,
path: '/',
maxAge: 86400 * 7,
partitioned: false
});8.2 LocalStorage
Client-side storage with optional encryption:
const storage = new LocalStorage({
key: 'za_token',
encryption: true,
encryptionKey: process.env.ENCRYPTION_KEY!
});8.3 Bearer Storage
HTTP header-based authentication for APIs:
const storage = new BearerStorage({
header: 'Authorization',
prefix: 'Bearer',
caseSensitive: false
});8.4 Storage Factory
Create storage adapters using the factory pattern:
import { StorageFactory, createStorage } from '@onurege3467/zeroauth/storage';
const storage = createStorage('cookie', {
name: 'session',
httpOnly: true,
secure: true
});9. Security Features
9.1 Encryption
AES-256-GCM encryption for sensitive data:
import { createEncryption } from '@onurege3467/zeroauth/security';
const encryption = createEncryption({
algorithm: 'aes-256-gcm',
keyLength: 32,
ivLength: 16,
tagLength: 16
});
// Encrypt data
const { encrypted, iv, tag } = encryption.encrypt('sensitive data');
// Decrypt data
const { decrypted } = encryption.decrypt(encrypted, iv, tag);9.2 Rate Limiting
Configurable rate limiting to prevent abuse:
const rateLimiter = createRateLimiter({
windowMs: 60000, // 1 minute window
maxRequests: 100, // 100 requests per window
keyGenerator: (request) => request.ip,
skipSuccessfulRequests: false,
skipFailedRequests: false
});
// Check rate limit
const result = await rateLimiter.check(request);
if (!result.allowed) {
throw new Error(`Rate limit exceeded. Retry after ${result.retryAfter} seconds`);
}9.3 CSRF Protection
Cross-site request forgery protection:
import { createCSRFProtection } from '@onurege3467/zeroauth/security';
const csrf = createCSRFProtection({
cookieName: 'csrf_token',
headerName: 'x-csrf-token',
cookieOptions: {
httpOnly: false,
secure: true,
sameSite: 'strict',
path: '/',
maxAge: 3600
}
});
// Generate CSRF token
const token = csrf.generateToken();
// Validate CSRF token
const isValid = csrf.validateToken(token, requestToken);9.4 Security Headers
Automatic security header injection:
import { createSecurityHeaders } from '@onurege3467/zeroauth/security';
const headers = createSecurityHeaders({
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
xFrameOptions: {
action: 'deny'
},
contentSecurityPolicy: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
upgradeInsecureRequests: true
}
});
console.log(headers);
// {
// 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
// 'X-Content-Type-Options': 'nosniff',
// 'X-Frame-Options': 'DENY',
// 'X-XSS-Protection': '1; mode=block',
// 'Referrer-Policy': 'strict-origin-when-cross-origin',
// 'Content-Security-Policy': "default-src 'self'; ..."
// }9.5 Session Fixation Protection
Automatic session ID regeneration:
import { createSessionFixationProtection } from '@onurege3467/zeroauth/security';
const fixation = createSessionFixationProtection({
enabled: true,
regenerateOnLogin: true,
regenerateOnPrivilegeChange: true,
regenerateOnExtend: false,
sessionIdLength: 32
});
// Check if regeneration is needed
const shouldRegenerate = await fixation.shouldRegenerate('login', currentSession);
// Regenerate session
const { oldSessionId, newSessionId } = await fixation.regenerateSession(
currentSession,
async (oldSession, newId) => {
// Create new session with same data
return { ...oldSession, id: newId };
}
);10. Cache System
10.1 In-Memory Cache
LRU cache for single-instance deployments:
import { createMemoryCache } from '@onurege3467/zeroauth/cache';
const cache = createMemoryCache({
type: 'memory',
ttl: 300000, // 5 minutes
maxSize: 10000, // Maximum 10,000 entries
maxMemory: 100 * 1024 * 1024 // 100MB max memory
});
// Set cache value
await cache.set('user:123', { name: 'John', email: '[email protected]' }, 60000);
// Get cache value
const user = await cache.get('user:123');
// Check cache
const exists = await cache.has('user:123');
// Invalidate pattern
await cache.invalidate('user:*');
// Clear cache
await cache.clear();10.2 Redis Cache
Distributed caching for multi-instance deployments:
import { createRedisCache } from '@onurege3467/zeroauth/cache';
const cache = createRedisCache({
type: 'redis',
ttl: 300000,
host: 'localhost',
port: 6379,
password: undefined,
db: 0,
keyPrefix: 'za:session:',
maxRetries: 3,
retryDelay: 100,
connectTimeout: 10000,
commandTimeout: 5000
});
// Use same API as memory cache
await cache.set('key', 'value', 60000);
const value = await cache.get('key');10.3 Cache Manager
Unified cache interface with automatic initialization:
import { CacheManager, createCache } from '@onurege3467/zeroauth/cache';
const cache = CacheManager.getInstance();
cache.initialize({
type: 'memory',
ttl: 300000
});
// Use cache
await cache.set('key', 'value');
const value = await cache.get('key');11. Frontend Integration
11.1 React Integration
The package provides comprehensive React hooks and components:
// app.tsx
import { AuthProvider, useAuth, ProtectedRoute } from '@onurege3467/zeroauth/react';
function App() {
return (
<AuthProvider
config={authConfig}
onAuthChange={(user, isAuthenticated) => {
// Handle auth state changes
console.log('User:', user);
console.log('Authenticated:', isAuthenticated);
}}
>
<Router>
<Route path="/login" element={<LoginPage />} />
<Route
path="/dashboard"
element={
<ProtectedRoute
requireAuth
roles={['admin', 'user']}
fallback={<LoadingSpinner />}
>
<Dashboard />
</ProtectedRoute>
}
/>
</Router>
</AuthProvider>
);
}11.2 useAuth Hook
Primary authentication hook for React applications:
import { useAuth } from '@onurege3467/zeroauth/react';
function UserProfile() {
const {
user, // Current user object
isAuthenticated, // Authentication status
isLoading, // Loading state
error, // Error object
login, // Login function
logout, // Logout function
refresh, // Refresh token function
getAccessToken, // Get access token
hasPermission, // Check permission
hasRole, // Check role
updateUser, // Update user data
clearError // Clear error state
} = useAuth();
if (isLoading) {
return <LoadingSpinner />;
}
if (!isAuthenticated) {
return <LoginPage />;
}
return (
<div>
<h1>Welcome, {user.name}!</h1>
<p>Email: {user.email}</p>
<p>Roles: {user.roles?.join(', ')}</p>
<button onClick={logout}>Logout</button>
</div>
);
}11.3 useSession Hook
Session management hook:
import { useSession } from '@onurege3467/zeroauth/react';
function SessionInfo() {
const {
session, // Current session object
sessionId, // Session ID
isValid, // Session validity
expiresAt, // Expiration date
timeUntilExpiry, // Time until expiry in milliseconds
extendSession, // Extend session function
invalidateSession // Invalidate session function
} = useSession();
const handleExtend = async () => {
await extendSession(3600); // Extend by 1 hour
};
return (
<div>
<p>Session ID: {sessionId}</p>
<p>Valid: {isValid ? 'Yes' : 'No'}</p>
<p>Expires: {expiresAt?.toISOString()}</p>
<p>Time until expiry: {timeUntilExpiry}ms</p>
<button onClick={handleExtend}>Extend Session</button>
</div>
);
}11.4 useToken Hook
Token management hook:
import { useToken } from '@onurege3467/zeroauth/react';
function TokenInfo() {
const {
accessToken, // Access token
refreshToken, // Refresh token
tokenType, // Token type (Bearer)
isTokenValid, // Token validity
setTokens, // Set tokens function
clearTokens // Clear tokens function
} = useToken();
const handleRefresh = async () => {
// Token will be automatically refreshed
};
return (
<div>
<p>Access Token: {accessToken?.substring(0, 20)}...</p>
<p>Token Type: {tokenType}</p>
<p>Valid: {isTokenValid ? 'Yes' : 'No'}</p>
</div>
);
}11.5 ProtectedRoute Component
Route protection with role and permission checking:
import { ProtectedRoute } from '@onurege3467/zeroauth/react';
function AdminPanel() {
return (
<ProtectedRoute
requireAuth={true}
requireRole={['admin']}
requirePermission={['manage:users']}
fallback={<AccessDenied />}
redirectTo="/login"
callbackUrl="/admin"
>
<AdminContent />
</ProtectedRoute>
);
}
// With role array
<ProtectedRoute requireRole={['admin', 'moderator']}>
<ModeratorPanel />
</ProtectedRoute>
// With permission array
<ProtectedRoute requirePermission={['read:users', 'write:users']}>
<UserManagement />
</ProtectedRoute>12. Backend Integration
12.1 Express.js Middleware
Complete Express.js integration:
import express from 'express';
import {
createExpressMiddleware,
requireAuth,
requireRole,
requirePermission
} from '@onurege3467/zeroauth/express';
const app = express();
app.use(express.json());
// Apply to all routes under /api
app.use('/api', createExpressMiddleware(auth)({
strategies: ['jwt', 'api-key'],
credentialsRequired: true,
path: '/api',
excludedPaths: ['/api/health', '/api/auth/login']
}));
// Require authentication
app.get('/api/profile', requireAuth(auth), (req, res) => {
res.json({ user: req.user });
});
// Require specific role
app.get('/api/admin', requireAuth(auth), requireRole(auth, ['admin']), (req, res) => {
res.json({ message: 'Admin area' });
});
// Require specific permission
app.get('/api/users', requireAuth(auth), requirePermission(auth, ['read:users']), (req, res) => {
res.json({ users: [] });
});
// Custom middleware with options
app.use('/api/protected', createExpressMiddleware(auth)({
strategies: ['jwt'],
credentialsRequired: true
}));12.2 Next.js Integration
Next.js App Router and Pages Router support:
Middleware (middleware.ts):
import { createNextJSMiddleware } from '@onurege3467/zeroauth/nextjs';
import { auth } from './lib/auth';
export default createNextJSMiddleware(auth)({
strategies: ['jwt', 'oauth2', 'passkey'],
protectedRoutes: [
'/dashboard/:path*',
'/api/protected/:path*',
'/profile/:path*'
],
publicRoutes: [
'/',
'/login',
'/api/auth/:path*',
'/api/health',
'/api/public/:path*'
],
loginUrl: '/login',
callbackUrlParam: 'callbackUrl'
});
export const config = {
matcher: ['/dashboard/:path*', '/api/protected/:path*', '/profile/:path*']
};Client-side (app/page.tsx):
'use client';
import { useAuth } from '@onurege3467/zeroauth/react';
export default function Dashboard() {
const { user, isAuthenticated, login, logout } = useAuth();
if (!isAuthenticated) {
return <LoginRedirect />;
}
return (
<div>
<h1>Dashboard</h1>
<p>Welcome, {user.name}!</p>
<button onClick={logout}>Logout</button>
</div>
);
}Server Actions (app/actions.ts):
'use server';
import { auth } from '@/lib/auth';
export async function loginAction(formData: FormData) {
const email = formData.get('email') as string;
const password = formData.get('password') as string;
try {
const session = await auth.login(email, password, {
strategy: 'jwt',
storage: 'cookie'
});
return { success: true, user: session.user };
} catch (error) {
return { success: false, error: 'Invalid credentials' };
}
}
export async function logoutAction() {
await auth.logout({});
return { success: true };
}
export async function getUserAction() {
const session = await auth.authenticate({ headers: {} }, {
strategies: ['jwt']
});
if (session) {
return { user: session.user };
}
return { user: null };
}12.3 Fastify Integration
Complete Fastify plugin support:
import Fastify from 'fastify';
import { createFastifyPlugin, requireAuth } from '@onurege3467/zeroauth/fastify';
const fastify = Fastify();
await fastify.register(createFastifyPlugin(auth), {
strategies: ['jwt', 'api-key'],
credentialsRequired: true,
prefix: '/auth'
});
// Login endpoint
fastify.post('/auth/login', async (request, reply) => {
const { email, password } = request.body as { email: string; password: string };
try {
const result = await auth.login(email, password, {
strategy: 'jwt'
});
return {
user: result.user,
tokens: result.tokens
};
} catch (error) {
reply.status(401).send({ error: 'Invalid credentials' });
}
});
// Protected endpoint
fastify.get('/auth/me', {
onRequest: [requireAuth(auth)]
}, async (request, reply) => {
return { user: request.user };
});
// With role requirement
fastify.get('/auth/admin', {
onRequest: [requireAuth(auth)],
preHandler: async (request, reply) => {
const user = request.user as { roles: string[] };
if (!user.roles.includes('admin')) {
reply.status(403).send({ error: 'Forbidden' });
}
}
}, async (request, reply) => {
return { message: 'Admin area' };
});
await fastify.listen({ port: 3000 });13. API Reference
13.1 AuthManager Methods
The main AuthManager class provides the following methods:
| Method | Parameters | Returns | Description |
|--------|-----------|---------|-------------|
| authenticate | request: unknown, options?: { strategies?: string[]; request?: unknown } | { user, session, strategy } \| null | Authenticate a request |
| login | email: string, password: string, options?: { strategy?: string; storage?: string; metadata?: Record } | AuthResult | Login with credentials |
| logout | request: unknown, options?: { everywhere?: boolean } | void | Logout current user |
| refresh | refreshToken: string | SessionTokens | Refresh access token |
| createSession | user: UserData, strategy?: AuthStrategy | SessionData | Create new session |
| validateSession | sessionId: string | SessionData \| null | Validate session |
| deleteSession | sessionId: string | void | Delete specific session |
| listUserSessions | userId: string, options?: { active?: boolean } | SessionData[] | List user sessions |
| deleteUserSessions | userId: string | void | Delete all user sessions |
| getStrategy | type: AuthStrategy | BaseStrategy \| undefined | Get strategy instance |
| hasStrategy | type: AuthStrategy | boolean | Check if strategy exists |
| getUserFromToken | token: string | UserData \| null | Extract user from token |
| checkRateLimit | request: unknown | RateLimitResult | Check rate limit |
| close | void | Promise<void> | Cleanup resources |
13.2 AuthResult Interface
interface AuthResult {
session: SessionData;
user: UserData;
tokens: {
accessToken: string;
refreshToken?: string;
tokenType: string;
expiresIn: number;
};
}13.3 SessionData Interface
interface SessionData {
id: string;
userId: string;
token: string;
refreshToken?: string;
strategy: AuthStrategy;
createdAt: Date;
expiresAt: Date;
lastAccessedAt: Date;
ip?: string;
userAgent?: string;
metadata?: Record<string, unknown>;
active: boolean;
}13.4 UserData Interface
interface UserData {
id: string;
email: string;
name?: string;
picture?: string;
roles?: string[];
permissions?: string[];
[key: string]: unknown;
}13.5 AuthStrategy Type
type AuthStrategy =
| 'jwt'
| 'session'
| 'refresh-token'
| 'oauth2'
| 'passkey'
| 'api-key';14. Examples
14.1 Complete Next.js App Router Example
// lib/auth.ts
import { createAuth } from '@onurege3467/zeroauth';
import { ZeroHelperAdapter } from '@onurege3467/zeroauth/database';
export const auth = createAuth({
database: {
adapter: new ZeroHelperAdapter({
adapter: 'zpack',
config: {
path: './data/sessions.zpack',
indexFields: { sessions: ['userId', 'expiresAt'] }
},
cache: { type: 'memory', ttl: 300000, maxSize: 10000 }
})
},
storage: {
type: 'cookie',
config: {
name: 'za_session',
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 86400 * 7
}
},
strategies: [
{
type: 'jwt',
config: {
algorithm: 'RS256',
secretOrKey: process.env.JWT_PRIVATE_KEY!,
publicKey: process.env.JWT_PUBLIC_KEY,
issuer: 'my-app',
audience: 'my-users'
}
},
{
type: 'refresh-token',
config: { expiresIn: '30d', rotation: true }
},
{
type: 'oauth2',
provider: 'google',
config: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
redirectUri: 'https://myapp.com/api/auth/callback/google',
scope: ['openid', 'email', 'profile']
}
}
],
callbacks: {
onLogin: async (user, session) => {
console.log(`${user.email} logged in`);
},
onLogout: async (user, session) => {
console.log(`${user.email} logged out`);
}
}
});// middleware.ts
import { authMiddleware } from '@onurege3467/zeroauth/nextjs';
import { auth } from './lib/auth';
export default authMiddleware(auth, {
strategies: ['jwt', 'oauth2', 'passkey'],
protectedRoutes: ['/dashboard/:path*', '/api/protected/:path*'],
publicRoutes: ['/', '/login', '/api/auth/:path*'],
loginUrl: '/login'
});
export const config = {
matcher: ['/dashboard/:path*', '/api/protected/:path*']
};// app/api/auth/login/route.ts
import { auth } from '@/lib/auth';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { email, password, strategy = 'jwt' } = await request.json();
try {
const session = await auth.login(email, password, {
strategy: strategy as 'jwt' | 'session',
storage: 'cookie'
});
return NextResponse.json({
user: session.user,
tokens: session.tokens
});
} catch (error) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
}// app/api/auth/logout/route.ts
import { auth } from '@/lib/auth';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
await auth.logout(request);
return NextResponse.json({ success: true });
}// app/api/auth/refresh/route.ts
import { auth } from '@/lib/auth';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { refreshToken } = await request.json();
try {
const tokens = await auth.refresh(refreshToken);
return NextResponse.json(tokens);
} catch (error) {
return NextResponse.json(
{ error: 'Invalid refresh token' },
{ status: 401 }
);
}
}// app/dashboard/page.tsx
'use client';
import { useAuth } from '@onurege3467/zeroauth/react';
export default function Dashboard() {
const { user, isAuthenticated, logout, isLoading } = useAuth();
if (isLoading) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <LoginRedirect />;
}
return (
<div className="dashboard">
<h1>Dashboard</h1>
<div className="user-info">
<p>Welcome, {user.name}!</p>
<p>Email: {user.email}</p>
<p>Roles: {user.roles?.join(', ')}</p>
</div>
<button onClick={logout} className="logout-btn">
Logout
</button>
</div>
);
}14.2 Complete Express.js API Example
// server.ts
import express from 'express';
import cors from 'cors';
import { createAuth, createExpressMiddleware } from '@onurege3467/zeroauth';
import { PostgreSQLAdapter } from '@onurege3467/zeroauth/database';
const app = express();
app.use(cors());
app.use(express.json());
const auth = createAuth({
database: {
adapter: new PostgreSQLAdapter({
config: {
host: process.env.DB_HOST!,
port: 5432,
database: process.env.DB_NAME!,
user: process.env.DB_USER!,
password: process.env.DB_PASSWORD!,
tablePrefix: 'za_'
},
cache: { type: 'memory', ttl: 300000 }
})
},
storage: {
type: 'bearer',
config: { header: 'Authorization', prefix: 'Bearer' }
},
strategies: [
{
type: 'jwt',
config: {
algorithm: 'HS256',
secretOrKey: process.env.JWT_SECRET!
}
},
{
type: 'refresh-token',
config: { expiresIn: '30d', rotation: true }
}
],
security: {
rateLimit: {
windowMs: 60000,
maxRequests: 100
}
}
});
// Public routes
app.post('/api/auth/register', async (req, res) => {
const { email, password, name } = req.body;
// Register user logic here
const user = { id: '1', email, name, roles: ['user'], permissions: [] };
const session = await auth.createSession(user, 'jwt');
res.status(201).json({
user: session.user,
tokens: session.tokens
});
});
app.post('/api/auth/login', async (req, res) => {
const { email, password } = req.body;
try {
const session = await auth.login(email, password, {
strategy: 'jwt'
});
res.json({
user: session.user,
tokens: session.tokens
});
} catch (error) {
res.status(401).json({ error: 'Invalid credentials' });
}
});
app.post('/api/auth/refresh', async (req, res) => {
const { refreshToken } = req.body;
try {
const tokens = await auth.refresh(refreshToken);
res.json(tokens);
} catch (error) {
res.status(401).json({ error: 'Invalid refresh token' });
}
});
// Protected routes
app.use('/api', createExpressMiddleware(auth)({
strategies: ['jwt'],
credentialsRequired: true
}));
app.get('/api/me', (req, res) => {
res.json({ user: req.user });
});
app.get('/api/users', async (req, res) => {
const permissions = (req.user as Record<string, unknown>).permissions as string[] || [];
if (!permissions.includes('read:users')) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
// Fetch users logic
res.json({ users: [] });
});
app.post('/api/auth/logout', async (req, res) => {
await auth.logout(req);
res.json({ success: true });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});15. Advanced Use Cases
16.1 Security Best Practices
Use Environment Variables for Secrets:
secretOrKey: process.env.JWT_SECRET!, encryptionKey: process.env.ENCRYPTION_KEY!,Enable HTTPS in Production:
secure: process.env.NODE_ENV === 'production'Use Proper Cookie Settings:
httpOnly: true, secure: true, sameSite: 'lax' // or 'strict' for maximum securityImplement Rate Limiting:
security: { rateLimit: { windowMs: 60000, // 1 minute maxRequests: 100 } }Enable Token Rotation:
{ type: 'refresh-token', config: { rotation: true, reuseDetection: true } }
16.2 Performance Best Practices
Use Redis Cache in Production:
cache: { type: 'redis', host: process.env.REDIS_HOST!, port: 6379, ttl: 300000 }Configure Appropriate TTL Values:
session: { expiresIn: 3600, // 1 hour for access token updateAge: 300, // Update session every 5 minutes absoluteExpiresIn: 86400 * 7 // 7 days max session }Use Connection Pooling:
database: { adapter: 'postgres', config: { connectionLimit: 10 // Adjust based on load } }
16.3 Error Handling Best Practices
const auth = createAuth({
callbacks: {
onError: async (error, context) => {
console.error(`Auth error in ${context}:`, error);
// Send to monitoring service
await monitoringService.captureException(error, {
context,
user: error.context?.userId
});
}
}
});
// Handle specific errors
try {
await auth.login(email, password);
} catch (error) {
if (error instanceof AuthError) {
switch (error.code) {
case 'INVALID_CREDENTIALS':
return res.status(401).json({ error: 'Invalid email or password' });
case 'SESSION_EXPIRED':
return res.status(401).json({ error: 'Session expired' });
case 'RATE_LIMIT_EXCEEDED':
return res.status(429).json({ error: 'Too many requests' });
default:
return res.status(500).json({ error: 'Authentication failed' });
}
}
}17. Troubleshooting
17.1 Common Issues
Issue: Token Not Being Sent
Problem: Requests are not being authenticated even with valid tokens.
Solution: Check storage configuration and request headers:
// Verify storage type matches how you're sending the token
storage: {
type: 'bearer', // Make sure this matches your request
config: { header: 'Authorization', prefix: 'Bearer' }
}
// In requests, include the header
fetch('/api/data', {
headers: {
Authorization: `Bearer ${token}`
}
});Issue: CORS Errors
Problem: Cross-origin requests are being blocked.
Solution: Configure CORS properly:
import cors from 'cors';
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || '*',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-CSRF-Token']
}));Issue: Session Not Persisting
Problem: Sessions are not being saved to the database.
Solution: Check database connection and adapter configuration:
// Verify adapter is correctly configured
database: {
adapter: 'postgres', // Correct adapter name
config: {
host: 'localhost',
port: 5432,
database: 'your_db',
user: 'user',
password: 'pass'
}
}
// Ensure the table exists (auto-created)Issue: JWT Verification Fails
Problem: JWT tokens are being rejected even when valid.
Solution: Verify algorithm and key configuration:
// Ensure same algorithm on sign and verify
{
type: 'jwt',
config: {
algorithm: 'RS256', // Must match
secretOrKey: process.env.JWT_PRIVATE_KEY!,
publicKey: process.env.JWT_PUBLIC_KEY
}
}
// For symmetric algorithms, ensure secret is the same
{
type: 'jwt',
config: {
algorithm: 'HS256',
secretOrKey: process.env.JWT_SECRET! // Same secret
}
}17.2 Debug Mode
Enable debug logging:
const auth = createAuth({
// Debug logging will output detailed information
callbacks: {
onError: (error, context) => {
console.debug('Auth Debug:', {
context,
error: error.message,
stack: error.stack
});
}
}
});17.3 Getting Help
If you encounter issues not covered here:
- Check the GitHub Issues
- Review the Examples section
- Search for similar issues in the repository
18. Contributing
18.1 Development Setup
Fork the repository:
git clone https://github.com/onurege3467/zeroauth.git cd zeroauthInstall dependencies:
npm installCreate a feature branch:
git checkout -b feature/amazing-featureMake your changes and add tests.
Run tests:
npm run test npm run buildSubmit a Pull Request.
18.2 Code Style
The project follows strict TypeScript and ESLint rules:
# Lint code
npm run lint
# Fix linting errors
npm run lint:fix
# Format code
npm run format18.3 Testing
All contributions should include tests:
# Run unit tests
npm run test:unit
# Run integration tests
npm run test:integration
# Run all tests with coverage
npm run test:coverage19. License
This project is licensed under the ISC License.
Copyright (c) 2024 Onure9e
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20. Support
20.1 Author
Developer: Onure9e Email: [email protected]
20.2 Related Packages
- @onurege3467/zerohelper - The native database framework that powers this package
20.3 Resources
📊 Package Statistics
| Metric | Value | |--------|-------| | Authentication Strategies | 6 | | Database Adapters | 5 | | Storage Options | 4 | | Security Features | 5+ | | Framework Integrations | 4 | | TypeScript Support | 100% | | Bundle Size (ESM) | ~65KB | | Bundle Size (CJS) | ~68KB |
🙏 Acknowledgments
Special thanks to all contributors and users of this package. Your feedback and contributions help make this project better every day.
Built with ❤️ by Onure9e
