@rs-tech-hub/nestjs-activation-token

Secure activation token management for NestJS applications. Generate, validate, and manage time-limited activation tokens for user verification workflows with automatic expiration and invalidation support.


๐Ÿ“š Table of Contents


๐Ÿ”‘ License

This package requires a valid commercial license. A valid license key must be configured to use this package.

Visit https://rstechhub.gumroad.com to purchase a license.

โœจ Features

  • ๐Ÿ” Secure token generation with SHA-256 hashing
  • โฐ Automatic token expiration (default: 2 days)
  • โœ… Token validation and verification
  • ๐Ÿ”„ Token invalidation for previously issued tokens
  • ๐Ÿงน Automatic cleanup of expired tokens
  • ๐Ÿ›ก๏ธ One-time use token enforcement
  • ๐Ÿ“Š Built-in token lifecycle tracking

๐Ÿ“‹ Prerequisites

  • Node.js >= 18
  • TypeScript >= 5.1.0
  • NestJS >= 11.1.6
  • Prisma ORM v7.0+

๐Ÿš€ Quick Start

Installation

# npm
npm install @rs-tech-hub/nestjs-activation-token \
  @rs-tech-hub/nestjs-clock \
  @rs-tech-hub/nestjs-license-validator \
  @rs-tech-hub/nestjs-prisma \
  @rs-tech-hub/nestjs-service-operation

# yarn
yarn add @rs-tech-hub/nestjs-activation-token \
  @rs-tech-hub/nestjs-clock \
  @rs-tech-hub/nestjs-license-validator \
  @rs-tech-hub/nestjs-prisma \
  @rs-tech-hub/nestjs-service-operation

# pnpm
pnpm add @rs-tech-hub/nestjs-activation-token \
  @rs-tech-hub/nestjs-clock \
  @rs-tech-hub/nestjs-license-validator \
  @rs-tech-hub/nestjs-prisma \
  @rs-tech-hub/nestjs-service-operation

Module Registration

Import the module in your NestJS application:

import { Module } from "@nestjs/common";
import { ActivationTokenModule } from "@rs-tech-hub/nestjs-activation-token";

@Module({
  imports: [ActivationTokenModule],
})
export class AppModule {}

๐Ÿ”ง Service Usage

Inject the service in your own modules:

import { Injectable } from "@nestjs/common";
import { ActivationTokenService } from "@rs-tech-hub/nestjs-activation-token";

@Injectable()
export class UserActivationService {
  constructor(private activationTokenService: ActivationTokenService) {}

  async sendActivationEmail(userId: string) {
    // Generate activation token
    const tokenData = await this.activationTokenService.create(userId);

    // Send email with tokenData.activationKey
    await this.emailService.sendActivationEmail(
      userEmail,
      tokenData.activationKey
    );
  }

  async activateUser(userId: string, activationKey: string) {
    // Validate the activation token
    const isValid = await this.activationTokenService.validate({
      userId,
      activationKey,
    });

    if (isValid) {
      // Activate the user account
      await this.userService.activateAccount(userId);
    }
  }
}

๐Ÿ“– API Reference

ActivationTokenService

create(userId: string)

Creates a new activation token for a user.

Parameters:

  • userId (string): The user ID to associate with the token

Returns: Promise<ActivationTokenCreateServiceOutput>

const tokenData = await activationTokenService.create("user-123");
// Returns:
// {
//   id: 'token-id',
//   userId: 'user-123',
//   tokenHash: 'hashed-token',
//   activationKey: 'plain-token-to-send', // Send this to user
//   createdAt: Date,
//   expiresAt: Date // 2 days from creation
// }

validate(input: ActivationTokenValidateServiceInput)

Validates an activation token and marks it as used.

Parameters:

  • input.userId (string): The user ID
  • input.activationKey (string): The activation key received from user

Returns: Promise<boolean>

const isValid = await activationTokenService.validate({
  userId: "user-123",
  activationKey: "token-from-email",
});

verify(input: ActivationTokenVerifyServiceInput)

Verifies if an activation key matches a token hash (without marking as used).

Parameters:

  • input.activationKey (string): The activation key to verify
  • input.tokenHash (string): The stored token hash

Returns: Promise<boolean>

const matches = await activationTokenService.verify({
  activationKey: "token-key",
  tokenHash: "stored-hash",
});

invalidatePreviousUserTokens(userId: string)

Invalidates all unused tokens for a specific user.

Parameters:

  • userId (string): The user ID

Returns: Promise<boolean>

await activationTokenService.invalidatePreviousUserTokens("user-123");

cleanupExpiredTokens()

Removes all expired tokens from the database.

Returns: Promise<void>

// Run as a cron job or scheduled task
await activationTokenService.cleanupExpiredTokens();

๐Ÿ”„ Common Workflows

User Registration Flow

@Injectable()
export class RegistrationService {
  constructor(
    private userService: UserService,
    private activationTokenService: ActivationTokenService,
    private emailService: EmailService
  ) {}

  async registerUser(email: string, password: string) {
    // 1. Create user account (inactive)
    const user = await this.userService.create({
      email,
      password,
      isActive: false,
    });

    // 2. Generate activation token
    const token = await this.activationTokenService.create(user.id);

    // 3. Send activation email
    await this.emailService.sendActivationEmail(email, token.activationKey);

    return { userId: user.id, message: "Activation email sent" };
  }

  async activateAccount(userId: string, activationKey: string) {
    // Validate and mark token as used
    const isValid = await this.activationTokenService.validate({
      userId,
      activationKey,
    });

    if (!isValid) {
      throw new Error("Invalid or expired activation token");
    }

    // Activate user account
    await this.userService.update(userId, { isActive: true });

    return { message: "Account activated successfully" };
  }
}

Resend Activation Token

async resendActivationToken(userId: string) {
  // Invalidate previous tokens
  await this.activationTokenService.invalidatePreviousUserTokens(userId);

  // Create new token
  const token = await this.activationTokenService.create(userId);

  // Send new email
  await this.emailService.sendActivationEmail(
    userEmail,
    token.activationKey
  );
}

๐Ÿ”’ Security Features

  • SHA-256 Hashing: Activation keys are hashed before storage
  • One-time Use: Tokens are marked as used after validation
  • Expiration: Tokens automatically expire after 2 days
  • Invalidation: Previous tokens can be invalidated when issuing new ones
  • Secure Generation: Uses crypto.randomBytes for token generation

๐Ÿ“ Data Types

ActivationTokenValidateServiceInput

FieldTypeRequiredDescription
userIdstringโœ…User ID to validate token for
activationKeystringโœ…Activation key from email/SMS

ActivationTokenVerifyServiceInput

FieldTypeRequiredDescription
activationKeystringโœ…Activation key to verify
tokenHashstringโœ…Stored token hash to compare

ActivationTokenCreateServiceOutput

FieldTypeDescription
idstringToken ID
userIdstringAssociated user ID
tokenHashstringHashed token (stored)
activationKeystringPlain token (send to user)
createdAtDateToken creation time
expiresAtDateToken expiration time

โš ๏ธ Error Codes

Error CodeDescription
activation-token-error:invalidToken is invalid or expired
activation-token-error:token-not-foundNo token found for user

๐Ÿ’ก Best Practices

  1. Send tokens immediately: Generate and send tokens right after user registration
  2. Cleanup regularly: Schedule cleanupExpiredTokens() to run daily
  3. Invalidate on resend: Always invalidate previous tokens when issuing new ones
  4. Never expose token hash: Only send the activationKey to users
  5. Set reasonable expiration: Default 2 days is suitable for most cases

๐Ÿ“„ License

This package requires a valid commercial license. See LICENSE.txt for details. By using this software, you agree to the terms outlined in the Software License Agreement (SLA.md). The license grants you specific rights to use, modify, and deploy the software within the scope defined in the agreement. For full terms, conditions, and restrictions, please refer to the Software License Agreement.

๐Ÿ“ง Support

For technical support and inquiries: