@verifi-sdk/auth-core
v0.1.0
Published
Framework-agnostic authentication core - JWE encryption, session management, storage interfaces
Readme
@verifi-sdk/auth-core
Universal authentication primitives for blockchain applications.
Features
✅ Blockchain-agnostic - Works with any chain (Aptos, Solana, EVM, etc.) ✅ Framework-agnostic - Works with Next.js, Express, Hono, etc. ✅ JWE encryption - AES-256-GCM session encryption (more secure than JWT) ✅ Pluggable storage - Memory, Redis, Database adapters ✅ TypeScript-first - Full type safety ✅ Lightweight - ~200kb (jose + @noble/hashes)
Installation
npm install @verifi-sdk/auth-core
# or
pnpm add @verifi-sdk/auth-coreQuick Start
import { initJWE, encryptSession, decryptSession } from '@verifi-sdk/auth-core';
// 1. Initialize (once at startup)
initJWE({ secret: process.env.JWT_SECRET });
// 2. Create encrypted session (after signature verification)
const token = await encryptSession({
address: '0x123...',
publicKey: '0xabc...',
loginTime: Date.now(),
});
// 3. Verify session
const session = await decryptSession(token);
if (session) {
console.log('Authenticated:', session.address);
}Usage with Different Chains
This package is designed to be used with chain-specific packages:
Aptos
import { verifySignInSignature } from '@verifi-sdk/auth-aptos';
import { encryptSession } from '@verifi-sdk/auth-core';
const result = await verifySignInSignature(output);
if (result.valid) {
const token = await encryptSession({
address: result.address,
publicKey: output.publicKey,
loginTime: Date.now(),
});
}Solana (future)
import { verifySignature } from '@verifi-sdk/auth-solana';
import { encryptSession } from '@verifi-sdk/auth-core';
const isValid = await verifySignature(signature, message, publicKey);
if (isValid) {
const token = await encryptSession({
address: publicKey.toBase58(),
publicKey: publicKey.toBase58(),
loginTime: Date.now(),
});
}EVM (future)
import { verifyMessage } from '@verifi-sdk/auth-evm';
import { encryptSession } from '@verifi-sdk/auth-core';
const address = await verifyMessage(message, signature);
const token = await encryptSession({
address,
publicKey: address,
loginTime: Date.now(),
});API Reference
Session Management
initJWE(config: JWEConfig)
Initialize JWE encryption module (MUST be called before use).
initJWE({ secret: process.env.JWT_SECRET });encryptSession(session: AuthSession, options?: SessionOptions): Promise<string>
Encrypt session data as JWE token.
const token = await encryptSession({
address: '0x123...',
publicKey: '0xabc...',
loginTime: Date.now(),
}, {
expiresIn: '24h', // default: 24h
});decryptSession(token: string): Promise<AuthSession | null>
Decrypt and verify JWE token (returns null if invalid/expired).
const session = await decryptSession(token);
if (!session) {
return res.status(401).json({ error: 'Unauthorized' });
}decryptSessionStrict(token: string): Promise<AuthSession>
Decrypt session and throw on error (for middleware use).
try {
const session = await decryptSessionStrict(token);
} catch (error) {
return res.status(401).json({ error: 'Unauthorized' });
}Helper Functions
getSessionFromCookie(cookies: Record<string, string>, cookieName?: string): Promise<AuthSession | null>
Extract and decrypt session from cookie.
const session = await getSessionFromCookie(req.cookies, 'auth_token');getSessionFromHeader(authHeader: string | undefined): Promise<AuthSession | null>
Extract and decrypt session from Authorization header.
const session = await getSessionFromHeader(req.headers.authorization);extractTokenFromHeader(authHeader: string | undefined): string | null
Extract token from Authorization header (supports "Bearer token" format).
const token = extractTokenFromHeader(req.headers.authorization);isValidSession(session: AuthSession): boolean
Validate session data structure.
if (!isValidSession(session)) {
return res.status(401).json({ error: 'Invalid session' });
}isSessionExpired(session: AuthSession, maxAgeMs?: number): boolean
Check if session is expired based on loginTime.
if (isSessionExpired(session, 24 * 60 * 60 * 1000)) {
return res.status(401).json({ error: 'Session expired' });
}generateSessionSecret(): Uint8Array
Generate a secure random 32-byte secret for AES-256-GCM.
const secret = generateSessionSecret();
console.log('Secret:', bytesToHex(secret));Privacy-Preserving Sessions (ZK Mode)
encryptZKSession(params): Promise<string>
Create privacy-preserving session with ZK proof hash.
const token = await encryptZKSession({
addressCommitment: '0xabc...', // Hash of address
zkProofHash: '0xdef...', // Proof verification hash
publicKey: '0x123...',
loginTime: Date.now(),
});Types
interface AuthSession extends JWTPayload {
address: string; // User's blockchain address
publicKey: string; // Public key (hex)
loginTime: number; // Login timestamp (Unix ms)
zkProofHash?: string; // Optional: ZK proof hash
userId?: string; // Optional: External user ID
}
interface SessionOptions {
expiresIn?: string | number; // Default: '24h'
claims?: Record<string, unknown>;
}
interface JWEConfig {
secret: Uint8Array | string; // 32-byte secret for AES-256-GCM
}Storage Adapters
Coming soon: Redis, Prisma, and custom storage adapters for nonce and session management.
Security Best Practices
- Secret Management: Use a strong 32-byte secret and store it securely (env vars, secrets manager)
- HTTPS Only: Always use HTTPS in production
- HTTP-Only Cookies: Store tokens in HTTP-only cookies to prevent XSS
- SameSite: Use
SameSite=LaxorSameSite=Strictfor CSRF protection - Expiration: Set appropriate session expiration times (default: 24h)
License
MIT
