@cvo/plugin-auth
v0.0.0
Published
Authentication plugin for CVO Framework
Downloads
39
Readme
@cvo/plugin-auth
The core security plugin for CVO Framework, providing a high-performance, isomorphic, and modern full-stack authentication solution.
🚀 Key Philosophy
- Modern & Zero-Dependency: Built entirely on the native Web Crypto API. No heavy third-party JWT or Node-only
cryptomodules. - Isomorphic: The same cryptographic logic runs seamlessly in Browsers, Mini-programs, Node.js, and Edge Computing environments (e.g., Cloudflare Workers).
- High Security: 三重防御 (Triple Defense) — Client-side Pre-hashing, Dynamic Nonce Challenge, and Salted Backend Storage.
- Performance: Utilizes native C++ acceleration in runtimes, significantly faster than pure JS-based crypto libraries.
🧠 Security Architecture
1. Client-Side Pre-hashing
To prevent clear-text password transmission, the client pre-hashes the password using PBKDF2 before it leaves the browser. Even if intercepted, the attacker only gets a hash.
2. Dynamic Nonce Challenge (Anti-Replay)
During login, the client requests a unique nonce. It computes transmitted = sha256(prehashed_password + nonce). Since the nonce is single-use, intercepted requests cannot be replayed.
3. Salted Storage with PBKDF2
The backend uses PBKDF2 with a default of 1,049,600 iterations (2^20 + 2^10) and random salts. This makes brute-force attacks economically unfeasible.
🛠 Server-Side Usage
Register Plugin
import { authPlugin } from '@cvo/plugin-auth';
await server.registerPlugin(authPlugin({
secret: 'your-strong-secret',
expiresIn: '24h',
silentRefresh: true, // Automatically rotate tokens
refreshThreshold: 0.5 // Refresh when 50% of time remains
}));Identity Interception & Injection
Use decorators to secure your APIs and inject session data.
import { Authenticated, CurrentUser } from '@cvo/core';
@Authenticated()
class UserController {
@http('GET', '/api/me')
async getMe(@CurrentUser() user: any) {
return user;
}
@http('POST', '/api/avatar')
async updateAvatar(@CurrentUser('id') userId: string, @Body() body: any) {
return await db.user.update({ where: { id: userId }, data: body });
}
}Silent Refresh
When silentRefresh is enabled, the plugin automatically checks the token's expiration. If it's near the threshold, a new token is generated and returned via the X-Refresh-Token header. The frontend interceptor should watch for this header and update local storage.
🧪 Client-Side Usage
Since it uses the standard Web Crypto API, the client can use the same logic for pre-encryption.
Pre-encryption Flow
- Request a random
noncefrom the server. - Calculate
transmitted = hash(prehashed_password + nonce). - Send
transmittedandnonceto the login API.
Authentication Header
Clients should include the token in the Authorization header for all protected requests:
Authorization: Bearer <your_session_token>Handling Silent Refresh
The server may return a new token in the X-Refresh-Token header. Frontend interceptors should automatically update the local token when this header is present.
🔧 Crypto Utilities
Access advanced crypto functions via useAuth().
import { useAuth } from '@cvo/server';
const auth = useAuth();
// Verify challenge from client
const isValid = await auth.crypto.verifyTransmitted(transmitted, user.password, nonce);
// Manual signing
const token = await auth.sign({ userId: '123' });
// PBKDF2 Hashing
const hash = await auth.crypto.hash('raw_password');
// HMAC signing for URLs/Temp tokens
const signature = await auth.crypto.hmacSign('data', 'temp-secret');