0.1.9 • Published 9 months ago

@pardnchiu/jwt-auth v0.1.9

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

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: "john@example.com",
        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

0.1.9

9 months ago

0.1.8

9 months ago

0.1.7

9 months ago

0.1.6

9 months ago

0.1.5

9 months ago

0.1.4

9 months ago

0.1.3

9 months ago

0.1.2

9 months ago

0.1.1

9 months ago

0.1.0

9 months ago