npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pardnchiu/jwt-auth

v0.1.10

Published

A JWT authentication package providing both Access Token and Refresh Token mechanisms, featuring fingerprint recognition, Redis storage, and automatic refresh functionality.

Readme

JWT Auth (Node.js)

A JWT authentication package providing both Access Token and Refresh Token mechanisms, featuring fingerprint recognition, Redis storage, and automatic refresh functionality. version Golang can get here

version

Feature

  • Dual Token System

    • Access Token (short-term) + Refresh Token (long-term)
    • Automatic token refresh without requiring re-login
    • ES256 algorithm (Elliptic Curve Digital Signature)
  • Device Fingerprinting

    • Generates unique fingerprints based on User-Agent, Device ID, OS, and Browser
    • Prevents token misuse across different devices
    • Automatic device type detection (Desktop, Mobile, Tablet)
  • Token Revocation

    • Adds Access Token to blacklist upon logout
    • Redis TTL automatically cleans expired revocation records
    • Prevents reuse of logged-out tokens
  • Version Control Protection

    • Refresh Token version tracking
    • Auto-generates new Refresh ID after 5 refresh attempts
    • Prevents replay attacks
  • Smart Refresh Strategy

    • Auto-regenerates when Refresh Token has less than half lifetime remaining
    • 5-second grace period for old tokens to reduce concurrency issues
    • Minimizes database queries
  • Multiple Authentication Methods

    • Automatic cookie reading
    • Authorization Bearer Header
    • Custom Headers (X-Device-ID, X-Refresh-ID)
  • Flexible Configuration

    • Supports file paths or direct key content
    • Customizable Cookie names
    • Production/Development environment auto-switching

How to use

  • Installation

    npm install @pardnchiu/jwt-auth
  • Initialize

    import { JWTAuth } from '@pardnchiu/jwt-auth';
    
    // initialize the JWT instance
    await JWTAuth.init({
      privateKeyPath: "./keys/private.pem",
      publicKeyPath: "./keys/public.pem",
      // or paste keys directly:
      // privateKey: "-----BEGIN EC PRIVATE KEY-----...",
      // publicKey: "-----BEGIN PUBLIC KEY-----...",
      accessTokenExpires: 900, // seconds
      refreshTokenExpires: 604800, // seconds
      // true: domain=domain, samesite=none, secure=true
      // false: domain=localhost, samesite=lax, secure=false
      isProd: false,
      domain: "pardn.io",
      // cookie key, default access_token/refresh_id
      AccessTokenCookieKey: "access_token",
      RefreshTokenCookieKey: "refresh_id",
      // store with redis
      redis: {
        host: "localhost",
        port: 6379,
        password: "", // optional
        db: 0 // optional
      },
      checkUserExists: async (userId: string): Promise<boolean> => {
        // return true if user exists, false otherwise
        return true;
      }
    });
    
    process.on("SIGINT", async () => {
      await JWTAuth.close();
      process.exit(0);
    });
  • CreateJWT

    import { Request, Response } from 'express';
    import { JWTAuth } from '@pardnchiu/jwt-auth';
    
    async function loginHandler(req: Request, res: Response) {
      // after verifying user login info...
        
      const userData = {
        id: "user123",
        name: "",
        email: "[email protected]",
        thumbnail: "avatar.jpg",
        role: "user",
        level: 1,
        scope: ["read", "write"]
      };
    
      try {
        const tokenResult = await JWTAuth.CreateJWT(req, res, userData);
          
        // automatically set in cookies
        res.json({
          success: true,
          token: tokenResult.token,
          refresh_id: tokenResult.refresh_id
        });
      } catch (error) {
        res.status(500).json({ error: error.message });
      }
    }
  • VerifyJWT

    import { Request, Response } from 'express';
    import { JWTAuth } from '@pardnchiu/jwt-auth';
    
    async function protectedHandler(req: Request, res: Response) {
      try {
        const result = await JWTAuth.VerifyJWT(req, res);
          
        if (!result.isAuth) {
          // Authentication failed
          return res.status(result).json({ 
            error: result.isError ? "Bad Request" : "Unauthorized" 
          });
        }
          
        // Authentication success, user result.data to get user data
        res.json({
          message: "Protected resource accessed",
          user: result.data
        });
      } catch (error) {
        res.status(500).json({ error: error.message });
      }
    }
  • RevokeJWT

    import { Request, Response } from "express";
    import { JWTAuth } from "@pardnchiu/jwt-auth";
    
    async function logoutHandler(req: Request, res: Response) {
      try {
        await JWTAuth.RevokeJWT(req, res);
          
        res.json({
          message: "Successfully logged out"
        });
      } catch (error) {
        res.status(500).json({ error: error.message });
      }
    }

Configuration

Config

  • privateKeyPath / privateKey: private key file path or content
  • publicKeyPath / publicKey: public key file path or content
  • accessTokenExpires: access token expire time
  • refreshTokenExpires: refresh id expire time
  • isProd: is production or not (affects cookie setting)
  • domain: cookie domain
  • redis: redis connection
    • host: redis host
    • port: redis port
    • password: redis password (optional)
    • db: redis db (optional)
  • checkUserExists: user existence check function
  • AccessTokenCookieKey: access token cookie name (default: 'access_token')
  • RefreshTokenCookieKey: refresh id cookie name (default: 'refresh_id')

Supported methods

  1. Cookie: Automatically reads token from cookie
  2. Authorization Header: Authorization: Bearer <token>
  3. Custom Headers:
    • X-Device-ID: Device ID
    • X-Refresh-ID: Custom Refresh ID

Token refresh

The system automatically generates a new Refresh ID in the following cases:

  • Refresh version exceeds 5 times
  • Remaining Refresh Token time is less than half

The new tokens are returned via:

  • HTTP Header: X-New-Access-Token
  • HTTP Header: X-New-Refresh-ID
  • Cookie auto-update

Security features

  • Fingerprint recognition: Generates a unique fingerprint based on User-Agent, Device-ID, OS, Browser, and Device type
  • Token revocation: Adds token to a blacklist on logout
  • Automatic expiration: Supports TTL to automatically clean up expired tokens
  • Version control: Tracks Refresh Token versions to prevent replay attacks
  • Fingerprint validation: Ensures tokens are used from the same device/browser

Error handling

The VerifyJWT method returns:

  • AuthData object on successful authentication
  • HTTP status code number on failure:
    • 401: Unauthorized (invalid/expired tokens, user doesn't exist)
    • 400: Bad Request (invalid fingerprint, malformed tokens)

Common error scenarios:

  • Token revoked
  • Fingerprint mismatch
  • Refresh data not found
  • JWT expired or invalid
  • User not found

License

This source code project is licensed under the MIT license.

Creator


©️ 2025 邱敬幃 Pardn Chiu