1.0.3 • Published 5 months ago

express-jwt-auth-handler v1.0.3

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

Express JWT Auth Handler

A secure and flexible JWT authentication package for Express applications that handles both access and refresh tokens with cookie-based storage.

npm version License: MIT

Features

  • 🔐 Secure JWT-based authentication
  • 🔄 Automatic token refresh mechanism
  • 🍪 HTTP-only cookie management
  • 📦 TypeScript support
  • 🚀 Easy integration with Express
  • 🛡️ Token version control for security
  • ⚡ Lightweight with minimal dependencies

Installation

npm install express-jwt-auth-handler

Quick Start

import express from 'express';
import { Auth } from 'express-jwt-auth-handler';

const app = express();

// Initialize auth handler
const auth = new Auth({
  accessTokenSecret: 'your-access-token-secret',
  refreshTokenSecret: 'your-refresh-token-secret',
});

// Example login route
app.post('/login', async (req, res) => {
  try {
    // Create tokens after successful login
    const tokens = await auth.createAuthTokens(userId, tokenVersion);
    
    // Set tokens as HTTP-only cookies
    auth.sendAuthCookies(res, tokens);
    
    res.json({ success: true });
  } catch (error) {
    res.status(401).json({ error: 'Authentication failed' });
  }
});

Configuration

Auth Configuration Options

interface AuthConfig {
  accessTokenSecret: string;      // Required: Secret for access tokens
  refreshTokenSecret: string;     // Required: Secret for refresh tokens
  accessTokenExpiresIn?: string;  // Optional: Duration for access token (default: '15m')
  refreshTokenExpiresIn?: string; // Optional: Duration for refresh token (default: '7d')
  cookieSecure?: boolean;         // Optional: Secure cookie flag (default: true)
  cookieSameSite?: boolean | 'lax' | 'strict' | 'none'; // Optional: SameSite cookie policy (default: 'lax')
  cookiePath?: string;            // Optional: Cookie path (default: '/')
  cookieDomain?: string;          // Optional: Cookie domain
}

API Reference

Creating an Auth Instance

const auth = new Auth({
  accessTokenSecret: 'your-access-token-secret',
  refreshTokenSecret: 'your-refresh-token-secret',
  // Optional configurations
  accessTokenExpiresIn: '30m',
  refreshTokenExpiresIn: '7d',
  cookieSecure: true,
  cookieSameSite: 'lax',
});

Methods

createAuthTokens(userId: string, tokenVersion: number): Promise<TokenPair>

Creates a new pair of access and refresh tokens.

const tokens = await auth.createAuthTokens('user123', 1);
// Returns: { accessToken: string, refreshToken: string }

sendAuthCookies(res: Response, tokens: TokenPair): void

Sets the tokens as HTTP-only cookies in the response.

auth.sendAuthCookies(res, tokens);

clearAuthCookies(res: Response): void

Clears authentication cookies from the response.

auth.clearAuthCookies(res);

checkTokens(accessToken: string, refreshToken: string, expectedTokenVersion: number, renewalCallback?: TokenRenewalCallback): Promise<TokenCheckResult>

Verifies and potentially renews tokens based on their validity.

const result = await auth.checkTokens(
  accessToken,
  refreshToken,
  tokenVersion,
  async () => {
    // Optional callback for token renewal
    return { userId: 'user123', tokenVersion: 1 };
  }
);

Token Duration Format

Token durations can be specified using the following format:

  • s: seconds (e.g., '30s')
  • m: minutes (e.g., '15m')
  • h: hours (e.g., '24h')
  • d: days (e.g., '7d')

Complete Example

Here's a complete example showing how to integrate the auth handler with an Express application:

import express from 'express';
import { Auth, AuthError } from 'express-jwt-auth-handler';

const app = express();
const auth = new Auth({
  accessTokenSecret: process.env.ACCESS_TOKEN_SECRET!,
  refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET!,
});

// Login route
app.post('/login', async (req, res) => {
  try {
    // Validate user credentials here
    const userId = 'user123';
    const tokenVersion = 1;

    const tokens = await auth.createAuthTokens(userId, tokenVersion);
    auth.sendAuthCookies(res, tokens);

    res.json({ success: true });
  } catch (error) {
    res.status(401).json({ error: 'Login failed' });
  }
});

// Protected route middleware
const authMiddleware = async (req, res, next) => {
  try {
    const accessToken = req.cookies.access_token;
    const refreshToken = req.cookies.refresh_token;

    const result = await auth.checkTokens(
      accessToken,
      refreshToken,
      1, // Expected token version
      async () => {
        // Implement your token renewal logic here
        return { userId: 'user123', tokenVersion: 1 };
      }
    );

    // If new tokens were generated, set them
    if (result.tokens) {
      auth.sendAuthCookies(res, result.tokens);
    }

    req.user = { userId: result.accessTokenData.userId };
    next();
  } catch (error) {
    res.status(401).json({ error: 'Unauthorized' });
  }
};

// Protected route example
app.get('/protected', authMiddleware, (req, res) => {
  res.json({ message: 'Protected data', user: req.user });
});

// Logout route
app.post('/logout', (req, res) => {
  auth.clearAuthCookies(res);
  res.json({ success: true });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Error Handling

The package throws AuthError for various authentication-related issues. Always wrap authentication operations in try-catch blocks:

try {
  const result = await auth.checkTokens(accessToken, refreshToken, tokenVersion);
} catch (error) {
  if (error instanceof AuthError) {
    // Handle authentication error
    console.error(error.message);
  } else {
    // Handle other errors
    console.error('Unexpected error:', error);
  }
}

Security Considerations

  1. Always use strong, unique secrets for access and refresh tokens
  2. Store secrets securely (e.g., environment variables)
  3. Use HTTPS in production (cookieSecure: true)
  4. Implement proper token version control for security
  5. Consider implementing rate limiting for token endpoints
  6. Regularly rotate tokens and implement proper logout mechanisms

License

MIT © mharrismalik

1.0.2

5 months ago

1.0.3

5 months ago

1.0.0

5 months ago