authia
High-performance JWT verification library for Ed25519 using WebAssembly.
Features
- 🚀 Fast Ed25519 JWT verification using Rust + WebAssembly
- ⚡ v0.3.0 Optimization: Single-pass JSON parsing for maximum performance
- 🔒 Secure by design - algorithm fixed to Ed25519
- 🌐 Universal runtime support (Node.js, Browser, Cloudflare Workers)
- 📦 Zero runtime dependencies
- 🎯 TypeScript type definitions included
- ⚡ Automatic Wasm initialization
📊 Benchmarks
Performance varies significantly by runtime environment:
Cloudflare Workers / Edge Runtimes:
| Library | Avg (ms) | p50 (ms) | p95 (ms) |
|---|---|---|---|
| authia (WASM) | 0.20ms | 0.17ms | 0.36ms |
| jose (WebCrypto) | 0.30ms | 0.28ms | 0.50ms |
Node.js (native crypto):
| Library | Avg (ms) |
|---|---|
| jose (native) | 0.01-0.03ms ⚡ |
| authia (WASM) | 0.17-0.20ms |
In Node.js, jose uses native C++ crypto bindings and is significantly faster. authia is optimized for edge runtimes where both libraries use similar APIs.
Installation
Usage
The library automatically detects the environment (Node.js or Bundler/Workers) and handles WebAssembly loading.
Access Token Verification
import { verifyAccessToken } from "authia";
try {
// ⚡ RECOMMENDED: Use publicKeyJwkRaw for better performance (v0.2.0+)
const payload = await verifyAccessToken(token, {
publicKeyJwkRaw: process.env.JWT_PUBLIC_KEY, // Raw JWK JSON string
audience: "kapock-app",
issuer: "https://auth.kapock.com",
});
console.log(`User ID: ${payload.sub}, Email: ${payload.email}`);
} catch (error) {
console.error("Token verification failed:", error);
}
Legacy (still supported, but slower):
// Base64-encoded JWK (backward compatible)
const payload = await verifyAccessToken(token, {
publicKeyJwk: btoa(process.env.JWT_PUBLIC_KEY), // Requires base64 encoding
audience: "kapock-app",
issuer: "https://auth.kapock.com",
});
Refresh Token Verification
import { verifyRefreshToken } from "authia";
const payload = await verifyRefreshToken(token, {
publicKeyJwkRaw: process.env.JWT_PUBLIC_KEY, // Use raw JWK for better performance
audience: "kapock-app",
issuer: "https://auth.kapock.com",
});
console.log(`JTI: ${payload.jti}`);
Performance Tips
- Use
publicKeyJwkRawinstead ofpublicKeyJwk(2-5x faster in high-throughput scenarios) - Cache your verification options at the worker/process level
- The library automatically caches the decoded public key internally
// Worker-level caching example (Cloudflare Workers)
let cachedPublicKey: string | null = null;
export async function verifyToken(token: string, env: Env) {
if (!cachedPublicKey) {
cachedPublicKey = env.JWT_PUBLIC_KEY.trim();
}
return verifyAccessToken(token, {
publicKeyJwkRaw: cachedPublicKey, // Avoid repeated trim() calls
audience: "kapock-app",
issuer: "https://auth.kapock.com",
});
}
Runtime Behavior
Node.js
Verification is synchronous. The WebAssembly module is loaded and instantiated at startup using the optimized Node.js target.
Cloudflare Workers / Bundlers
Verification is also synchronous. The library automatically handles WebAssembly instantiation during module load. The await in examples is supported but not strictly required for the verification itself (it returns the payload directly).
API
See API Documentation for detailed information.
Known Issues & Limitations
⚠️ Important Notes for Production Use
Performance Considerations
Node.js Environments:
- authia has a JS ↔ WASM boundary overhead of ~0.1-0.15ms per call
- The popular
joselibrary uses native C++ crypto bindings and is typically faster in Node.js (0.01-0.03ms) - Recommendation: For Node.js backends, consider using
joseinstead of authia
Cloudflare Workers / Edge Runtimes:
- authia performs competitively in these environments where
josealso uses WebCrypto APIs - The WASM approach provides consistent performance across different edge platforms
- Recommendation: authia is well-suited for Cloudflare Workers with Ed25519 tokens
Schema Validation (v0.3.x)
- Strict schema validation: v0.3.1-v0.3.3 use strict type checking for JWT claims
- Missing optional fields (like
email) may cause verification to fail - Workaround: Ensure all tokens include expected fields, or use v0.2.x for more lenient parsing
- Future improvement: Planned migration to flexible schema with
Option<T>types
Environment Variable Parsing
- Public key format detection: The library attempts to auto-detect JSON vs Base64-encoded JWK
- Best practice: Use raw JSON format for
publicKeyJwkRawoption (recommended) - If using Base64, ensure proper encoding without PEM headers
Recommended Use Cases
✅ Good fit:
- Cloudflare Workers with Ed25519 JWT tokens
- Edge runtimes requiring consistent cross-platform behavior
- Learning Rust + WebAssembly development
❌ Consider alternatives:
- Node.js backends with high-throughput requirements → use
jose - Tokens with varying claim structures → use v0.2.x or
jose - Production systems requiring maximum stability → use
jose
License
MIT