# Architecture

This page shows, in one diagram, how `@pardnchiu/jwt-auth` is layered and what it depends on.

## System Overview

```mermaid
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](https://github.com/pardnio/node-jwt-auth/blob/main/doc/architecture.md)
- Refresh flow: [Refresh Token Rotation](/token-refresh)
