Architecture
Last updated
This page shows, in one diagram, how @pardnchiu/jwt-auth is layered and what it depends on.
System Overview
graph TB
Client[Client] -->|Cookie / Bearer / X-Refresh-ID / X-Device-ID| Route[Express Route]
Route --> Auth[JWTAuth static class]
Auth --> FP[CreateFingerprint]
Auth --> RID[CreateRefreshId]
Auth --> JWT[jsonwebtoken ES256]
Auth --> Redis[(Redis refresh: / revoke:)]
Auth --> Check[checkUserExists callback]
Auth -->|Set-Cookie / X-New-*| Client
Layers
| Layer | File | Responsibility |
|---|---|---|
| Public API | src/JWTAuth.ts |
init, close, CreateJWT, VerifyJWT, RevokeJWT, GetAuth; holds config and the Redis connection in static fields |
| Fingerprint | src/CreateFingerprint.ts |
Derives a SHA-256 fingerprint from User-Agent and Device ID |
| Refresh ID | src/CreateRefreshId.ts |
createRefreshId() derives a SHA-256 identifier from user data, fingerprint, and issue time |
| Types | src/type.ts |
Config, AuthData, VerifyResult, and related interfaces |
| Exports | src/index.ts |
Named and default export of JWTAuth, plus all types |
Cross-Cutting Principles
| Principle | Implementation |
|---|---|
| Single process-wide state | JWTAuth cannot be instantiated; one process holds one config and one Redis connection |
| Server state lives only in Redis | Refresh data and the revocation blacklist are TTL-bound Redis keys that expire on their own |
| Tokens bound to devices | Both the Access Token and refresh data store the fingerprint, checked on every verification |
| Verification does not throw | VerifyJWT throws only when not initialized; every other failure becomes a VerifyResult |
Further Reading
- Full module diagrams, sequences, and state machines: doc/architecture.md
- Refresh flow: Refresh Token Rotation