> [!NOTE]
> This README was generated by [SKILL](https://github.com/agenvoy/skill-readme-generate), get the ZH version from [here](https://github.com/pardnio/node-jwt-auth/blob/main/doc/README.zh.md).

***

<p align="center">
<strong>DUAL-TOKEN JWT AUTH BOUND TO EVERY DEVICE!</strong>
</p>

<p align="center">
<a href="https://www.npmjs.com/package/@pardnchiu/jwt-auth"><img src="https://img.shields.io/npm/v/@pardnchiu/jwt-auth?include_prereleases&style=for-the-badge" alt="npm"></a>
<a href="https://www.jsdelivr.com/package/npm/@pardnchiu/jwt-auth"><img src="https://img.shields.io/jsdelivr/npm/hm/@pardnchiu/jwt-auth?include_prereleases&style=for-the-badge" alt="Downloads"></a>
<a href="https://www.npmjs.com/package/@pardnchiu/jwt-auth"><img src="https://img.shields.io/npm/l/@pardnchiu/jwt-auth?include_prereleases&style=for-the-badge" alt="License"></a>
</p>

***

> A Node.js JWT authentication library for Express with refresh token rotation, device fingerprint binding, and Redis revocation

## Table of Contents

- [Features](#features)
- [Architecture](#architecture)
- [License](#license)
- [Author](#author)

## Features

> `npm install @pardnchiu/jwt-auth` · [Documentation](https://github.com/pardnio/node-jwt-auth/blob/main/doc/doc.md)

- **Seamless Dual-Token Refresh** — When the Access Token expires, the same request re-signs an ES256 token from the Refresh ID and writes it back through cookies and headers, so users never log in again.
- **Device Fingerprint Binding** — Tokens are bound to a SHA-256 fingerprint of OS, browser, device type, and Device ID, so a token replayed from another device is flagged as suspicious.
- **Automatic Refresh ID Rotation** — After 5 refreshes or once less than half its lifetime remains, the Refresh ID is reissued while the old one stays valid for a 5-second grace window to absorb concurrent requests.
- **Redis Revocation Blacklist** — Logout writes the Access Token to a Redis blacklist whose TTL matches the token lifetime, so stale entries clean themselves up.
- **Three-State Verification** — Every verification reports authenticated, erroneous, and guest states at once, letting routes split 401 from 400 without parsing error strings.

## Architecture

> [Full Architecture](https://github.com/pardnio/node-jwt-auth/blob/main/doc/architecture.md)

```mermaid
graph TB
    Client[Client] -->|Cookie / Bearer / X-Refresh-ID| App[Express Route]
    App --> Auth[JWTAuth]
    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
```

## License

This project is licensed under the [MIT LICENSE](https://github.com/pardnio/node-jwt-auth/blob/main/LICENSE).

## Author

Just [open an issue](https://github.com/pardnio/node-jwt-auth/issues/new) to share an idea.

<a href="https://github.com/pardnio/node-jwt-auth/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=pardnio/node-jwt-auth&cache_bust=2026-10-07" alt="node-jwt-auth contributors" />
</a>

***

©️ 2025 [邱敬幃 Pardn Chiu](https://www.linkedin.com/in/pardnchiu)
