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

@tjoc/auth

v3.0.0

Published

Authentication and authorization package for TJOC platform

Readme

@tjoc/auth

A comprehensive authentication and authorization package for the TJOC platform. Provides secure user authentication, JWT management, 2FA support, and device tracking.

Features

  • 🔐 Secure JWT-based authentication
  • 👥 User management and role-based access control
  • 🔒 Two-factor authentication (TOTP)
  • 📱 Device tracking and management
  • 🛡️ Rate limiting and brute force protection
  • 🔄 Token refresh and blacklisting
  • ✉️ Email verification
  • 🔑 Password reset functionality
  • 📝 Comprehensive audit logging

Installation

# If using npm
npm install @tjoc/auth

# If using yarn
yarn add @tjoc/auth

# If using pnpm
pnpm add @tjoc/auth

Quick Start

import { initAuthModule, type InitAuthModuleOptions } from '@tjoc/auth';
import { TypeORMUserRepository } from './repositories/typeorm-user.repository';
import { DataSource } from 'typeorm';

// Initialize TypeORM connection
const dataSource = new DataSource({
  type: 'postgres',
  host: process.env.DB_HOST,
  port: parseInt(process.env.DB_PORT || '5432'),
  username: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  entities: ['dist/entities/*.js'],
  synchronize: false,
});

await dataSource.initialize();

// Configure the auth module
const options: InitAuthModuleOptions = {
  config: {
    jwtSecret: process.env.JWT_SECRET!,
    jwtExpiresIn: 3600, // 1 hour
    refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET!,
    refreshTokenExpiresIn: 604800, // 7 days
    resetPasswordUrl: 'https://your-app.com/reset-password',
    verifyEmailUrl: 'https://your-app.com/verify-email',
  },
  // Provide your TypeORM repository implementation
  userRepository: new TypeORMUserRepository(dataSource),
  // Redis configuration for token blacklist, sessions, etc.
  redis: {
    url: process.env.REDIS_URL!,
    keyPrefix: 'auth:', // optional
    lockout: {
      maxAttempts: 3, // optional, default: 3
      lockoutDuration: 300, // optional, default: 300 (5 minutes)
    },
  },
  // Optional email configuration
  emailConfig: {
    from: '[email protected]',
    verificationEmailTemplate: 'verify-email', // optional
    resetPasswordEmailTemplate: 'reset-password', // optional
  },
  // Two-factor authentication configuration
  twoFactorConfig: {
    issuer: 'Your App Name',
    algorithm: 'SHA256', // optional, default: SHA256
    digits: 6, // optional, default: 6
    step: 30, // optional, default: 30 seconds
  },
};

// Initialize all auth services
const {
  authService,
  tokenBlacklistService,
  deviceService,
  auditService,
  twoFactorService,
  accountLockoutService,
  backupCodesService,
} = initAuthModule(options);

// Login example
const loginResponse = await authService.login({
  email: '[email protected]',
  password: 'securePassword123',
});

// Register example
const registerResponse = await authService.register({
  email: '[email protected]',
  password: 'securePassword123',
  firstName: 'John',
  lastName: 'Doe',
});

Two-Factor Authentication

import { TwoFactorService, TwoFactorConfig } from '@tjoc/auth';

// Configure 2FA
const twoFactorConfig: TwoFactorConfig = {
  issuer: 'TJOC Platform',
  algorithm: 'SHA256',
  digits: 6,
  step: 30,
};

const twoFactorService = new TwoFactorService(twoFactorConfig);

// Generate secret for new user
const secret = twoFactorService.generateSecret();

// Generate QR code for setup
const qrCode = await twoFactorService.generateQRCode(
  '[email protected]',
  secret
);

// Verify token
const isValid = twoFactorService.verifyToken(
  '123456', // Token from authenticator app
  secret
);

Rate Limiting

import { RateLimitMiddleware, RateLimitConfig } from '@tjoc/auth';

// Configure rate limiting
const rateLimitConfig: RateLimitConfig = {
  points: 5, // Number of attempts
  duration: 60, // Per minute
  blockDuration: 300, // Block for 5 minutes
};

const rateLimitMiddleware = new RateLimitMiddleware(rateLimitConfig);

// Use in Express route
app.post('/login', rateLimitMiddleware.loginRateLimit, authController.login);

Device Tracking

import { DeviceService } from '@tjoc/auth';

const deviceService = new DeviceService();

// Track login from new device
const device = await deviceService.trackLogin(userId, req);

// Get user's devices
const devices = await deviceService.getUserDevices(userId);

// Remove device
await deviceService.removeDevice(userId, deviceId);

Security Features

Password Validation

Passwords must meet the following requirements:

  • Minimum 8 characters
  • At least one uppercase letter
  • At least one lowercase letter
  • At least one number
  • At least one special character
import { validatePassword } from '@tjoc/auth';

const { valid, errors } = validatePassword('password123');
if (!valid) {
  console.log(errors); // Array of validation error messages
}

Token Blacklisting

import { TokenBlacklistService } from '@tjoc/auth';

const blacklistConfig = {
  redisUrl: process.env.REDIS_URL!,
  keyPrefix: 'blacklist:',
};

const blacklistService = new TokenBlacklistService(blacklistConfig);

// Blacklist a token
await blacklistService.blacklist(token, expiryInSeconds);

// Check if token is blacklisted
const isBlacklisted = await blacklistService.isBlacklisted(token);

Environment Variables

# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-password
DB_NAME=your-database

# Auth Configuration
JWT_SECRET=your-jwt-secret
REFRESH_TOKEN_SECRET=your-refresh-token-secret

# Redis Configuration
REDIS_URL=redis://localhost:6379

Audit Logging

import { AuditService, AuditEventType } from '@tjoc/auth';

const auditService = new AuditService();

// Log a successful login
await auditService.log(userId, AuditEventType.LOGIN_SUCCESS, req);

// Retrieve user events
const { events, total } = await auditService.getUserEvents(userId, {
  limit: 10,
});

// Search logout events
const { events: logoutEvents } = await auditService.searchEvents({
  type: AuditEventType.LOGOUT,
});

Middleware Usage

Authentication Middleware

import { AuthMiddleware, UserRole } from '@tjoc/auth';

const authMiddleware = new AuthMiddleware({
  jwtSecret: process.env.JWT_SECRET!,
});

// Protect routes
app.get('/profile', authMiddleware.verifyToken, controller.profile);

// Role-based access
app.get(
  '/admin',
  authMiddleware.verifyToken,
  authMiddleware.hasRole([UserRole.ADMIN]),
  controller.admin
);

CSRF Protection

import { CSRFMiddleware } from '@tjoc/auth';

const csrfMiddleware = new CSRFMiddleware({ secret: process.env.CSRF_SECRET! });
app.use(csrfMiddleware.protect());

Session Management

import { SessionMiddleware } from '@tjoc/auth';

const sessionMiddleware = new SessionMiddleware({
  secret: process.env.SESSION_SECRET!,
  redisUrl: process.env.REDIS_URL!,
});

app.use(sessionMiddleware.initialize());

API Reference (Updated)

AuthService

| Method | Description | | ---------------------------------------------------------------- | ------------------------------------- | | login(payload: LoginPayload) | Authenticate user and generate tokens | | register(payload: RegisterPayload) | Register new user | | refreshToken(payload: RefreshTokenPayload) | Generate new access token | | logout(refreshToken: string) | Invalidate refresh token | | resetPassword(payload: ResetPasswordPayload) | Reset user password | | verifyEmail(payload: VerifyEmailPayload) | Verify user email | | requestPasswordReset(payload: RequestPasswordResetPayload) | Send password reset link | | changePassword(userId: string, payload: ChangePasswordPayload) | Change user's password |

TokenBlacklistService

| Method | Description | | --------------------------------------------- | ------------------------------------ | | blacklist(token: string, expiresIn: number) | Add a refresh token to the blacklist | | isBlacklisted(token: string) | Check if a token is blacklisted | | remove(token: string) | Remove a token from the blacklist |

DeviceService

| Method | Description | | ------------------------------------------------ | ------------------ | | trackLogin(userId: string, req: Request) | Track device login | | getUserDevices(userId: string) | Get user's devices | | removeDevice(userId: string, deviceId: string) | Remove device |

TwoFactorService

| Method | Description | | ----------------------------------------------- | --------------------------- | | generateSecret() | Generate a new TOTP secret | | generateQRCode(email: string, secret: string) | Generate QR code for setup | | verifyToken(token: string, secret: string) | Verify TOTP token | | generateToken(secret: string) | Generate current TOTP token |

AuditService

| Method | Description | | -------------------------------------------------------------------- | -------------------------- | | log(userId: string, type: AuditEventType, req: Request, metadata?) | Log an audit event | | getUserEvents(userId: string, options?) | Retrieve user audit events | | getEventsByType(type: AuditEventType, options?) | Retrieve events by type | | searchEvents(query, options?) | Search events with filters |

Validators

| Function | Description | | ------------------------------------ | ---------------------------- | | validatePassword(password: string) | Validate password complexity |

Middleware

| Middleware | Description | | --------------------- | -------------------------------------- | | AuthMiddleware | JWT verification and role-based access | | RateLimitMiddleware | Rate limiting for endpoints | | CSRFMiddleware | CSRF protection | | SessionMiddleware | Express session with Redis store |

Contributing

Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Database Integration

The auth package is database-agnostic and uses the Repository pattern. Here's how to implement the UserRepository interface using TypeORM:

import { UserRepository } from '@tjoc/auth';
import { DataSource, Repository } from 'typeorm';
import { User } from '../entities/user.entity';
import { CreateUserPayload } from '@tjoc/types';

// First, define your User entity
@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ unique: true })
  email: string;

  @Column()
  password: string;

  @Column()
  firstName: string;

  @Column()
  lastName: string;

  @Column({ nullable: true })
  phoneNumber?: string;

  @Column({ default: false })
  emailVerified: boolean;

  @Column()
  role: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;
}

// Then implement the UserRepository interface
export class TypeORMUserRepository implements UserRepository {
  private repository: Repository<User>;

  constructor(dataSource: DataSource) {
    this.repository = dataSource.getRepository(User);
  }

  async findByEmail(email: string) {
    return this.repository.findOne({ where: { email } });
  }

  async findById(id: string) {
    return this.repository.findOne({ where: { id } });
  }

  async create(userData: CreateUserPayload) {
    const user = this.repository.create(userData);
    return this.repository.save(user);
  }

  async updatePassword(id: string, hashedPassword: string) {
    await this.repository.update(id, { password: hashedPassword });
  }

  async updateEmailVerification(id: string, verified: boolean) {
    await this.repository.update(id, { emailVerified: verified });
  }

  async delete(id: string) {
    await this.repository.delete(id);
  }
}

Redis Integration

The package uses Redis for:

  • Token blacklisting
  • Session management
  • Account lockout tracking
  • 2FA backup codes storage

Configure Redis through the module initializer:

const { tokenBlacklistService } = initAuthModule({
  // ... other options ...
  redis: {
    url: process.env.REDIS_URL!,
    keyPrefix: 'auth:', // Optional prefix for all Redis keys
    lockout: {
      maxAttempts: 3, // Max failed 2FA attempts
      lockoutDuration: 300, // Lockout duration in seconds
    },
  },
});

Email Templates

Passwordless Login Code

  • templateId: passwordless-login
  • Variables:
    • code (string): The 6-digit login code
    • email (string): The recipient's email address
  • Recommended Subject: Your TJOC Login Code
  • Sample Body:
Hi,

Your login code is: <strong>{{code}}</strong>

Enter this code in the app or website to sign in. This code will expire in 10 minutes.

If you did not request this, you can ignore this email.

Thanks,
The TJOC Team