HbarSuite Docs
  • Welcome to HbarSuite
  • HbarSuite Developer Documentation
    • HbarSuite Smart Engine Applications
      • @hsuite/cross-chain-exchange
      • @hsuite/dao
        • DAO Application Testing
      • @hsuite/exchange
      • @hsuite/launchpad
      • @hsuite/multisig
      • @hsuite/nft-exchange
      • HSuite Smart App - Enterprise Hedera Application Framework
    • HSuite Libraries
      • @hsuite/api-key - Enterprise API Key Authentication System
      • @hsuite/auth-types
      • @hsuite/auth - Authentication Module
      • @hsuite/client-types
      • @hsuite/client - Client Service Module
      • @hsuite/dkg-types - Distributed Key Generation Type Definitions
      • @hsuite/hashgraph-types - Hedera Hashgraph Type Definitions
      • @hsuite/health - Comprehensive System Health Monitoring
      • @hsuite/helpers - Utility Library
      • @hsuite/ipfs - InterPlanetary File System Integration
      • @hsuite/shared-types - Shared Type Definitions
      • @hsuite/smart-config - Configuration Management
      • @hsuite/smart-ledgers - Multi-Ledger Management
      • @hsuite/smart-network-types - Smart Network Type Definitions
      • @hsuite/smart-transaction-types - Smart Transaction Type Definitions
      • @hsuite/smartnode-sdk - SmartNode Software Development Kit
      • @hsuite/snapshots - Multi-Ledger Token Snapshot Management
      • @hsuite/subscriptions-types - Subscription Management Type Definitions
      • @hsuite/subscriptions - Enterprise Subscription Management System
      • @hsuite/throttler-types - Rate Limiting Type Definitions
      • @hsuite/throttler - Advanced Rate Limiting for NestJS
      • @hsuite/users-types - User Type Definitions
      • @hsuite/users - User Management Module
      • @hsuite/validators-types
  • General Documentation
    • Smart Apps and Interaction
      • Subscription-Based Model
      • Token-Gate Model
    • The Smart Node Network
      • security-layer
      • Type of Validators Explained
      • Understanding Validators in Our System
      • Automating Responses to Network Changes & Key Rotation
      • Ensuring Continuous Operation and Recovery
      • Generating and Sharing Keys Collaboratively
      • Handling Node Expulsion and Replacement
      • Managing Cluster Membership
      • Protecting Secrets with Shamir's Method
      • Security Layer Integration
      • Setting Up Secure Clusters
    • Tokenomics
      • Tokenomics v1
      • Tokenomics V2
    • What is a Smart Node?
  • Restful APIs Documentation
Powered by GitBook
On this page
  • 📚 Table of Contents
  • ✨ Quick Start
  • Installation
  • Basic Setup
  • Basic Usage
  • 🏗️ Architecture
  • Core Authentication Framework
  • Module Structure
  • 🔧 API Reference
  • ApiKeyModule
  • ApiKeyService
  • ApiKeyAuthGuard
  • ApiKeyStrategy
  • User Tag Structure
  • Error Types
  • 📖 Guides
  • API Key Generation Guide
  • Route Protection Guide
  • User Integration Guide
  • Security Best Practices Guide
  • 🎯 Examples
  • Enterprise API Key Management Service
  • Advanced Route Protection Implementation
  • Multi-Application API Key Integration
  • 🔗 Integration
  • Required Dependencies
  • Environment Configuration
  • Module Integration
  • Request Flow Example
  • Database Queries
  1. HbarSuite Developer Documentation
  2. HSuite Libraries

@hsuite/api-key - Enterprise API Key Authentication System

PreviousHSuite LibrariesNext@hsuite/auth-types

Last updated 2 days ago

🔐 Comprehensive NestJS module for API key-based authentication with user integration and Passport.js support

Enterprise-grade API key authentication module providing robust user-based validation, Bearer token support, route protection through guards, and seamless integration with the HSuite ecosystem for secure application access control.


📚 Table of Contents


✨ Quick Start

Installation

npm install @hsuite/api-key

Basic Setup

import { ApiKeyModule } from '@hsuite/api-key';

@Module({
  imports: [
    ApiKeyModule.forRoot() // Global registration with automatic guard protection
  ]
})
export class AppModule {}

Basic Usage

import { ApiKeyAuthGuard, ApiKeyService } from '@hsuite/api-key';
import { UseGuards, Controller, Get } from '@nestjs/common';

@Controller('api')
export class ApiController {
  constructor(private apiKeyService: ApiKeyService) {}

  @UseGuards(ApiKeyAuthGuard)
  @Get('protected')
  async getProtectedResource() {
    return {
      message: 'This route is protected by API key authentication',
      timestamp: new Date().toISOString()
    };
  }
}

🏗️ Architecture

Core Authentication Framework

🔐 API Key Validation System

  • User-Based Authentication - API keys stored in user tags for ownership tracking

  • Bearer Token Support - Standard Authorization header with Bearer scheme

  • Tag-Based Storage - Flexible key storage using user document tags

  • Database Integration - MongoDB queries through @hsuite/users module

🛡️ Route Protection System

  • Passport.js Integration - Custom strategy using passport-headerapikey

  • NestJS Guards - Type-safe route protection with automatic validation

  • Global Protection - Optional global authentication guard registration

  • Flexible Configuration - Per-route or controller-level protection

🌐 HSuite Ecosystem Integration

  • User Module Integration - Seamless @hsuite/users module compatibility

  • Logging Integration - Comprehensive logging with @hsuite/helpers

  • TypeScript First - Full type safety and IDE support

  • Modular Design - Clean separation of concerns and dependency injection

📊 Request Processing

  • Header Extraction - Automatic API key extraction from Authorization header

  • User Attachment - Authenticated user object attached to request

  • Error Handling - Comprehensive validation error reporting

  • Session Support - Optional session management integration

Module Structure

src/
├── api-key.module.ts           # Main NestJS module configuration
├── api-key.service.ts          # Core API key validation service
├── api-key.strategy.ts         # Passport.js authentication strategy
├── api-key-auth.guard.ts       # NestJS authentication guard
└── index.ts                    # Public API exports

🔧 API Reference

ApiKeyModule

Static Methods

forRoot(): DynamicModule

  • Purpose: Registers the module globally with automatic guard configuration

  • Returns: Dynamic module with global scope and providers

  • Features: Automatic global authentication guard registration

  • Usage: Application-wide API key authentication

forFeature(): DynamicModule

  • Purpose: Registers the module for specific feature modules

  • Returns: Dynamic module without global scope

  • Features: Feature-specific authentication without global guards

  • Usage: Selective route protection in specific modules

ApiKeyService

Core Methods

validateApiKey(apiKey: string, user: UserDocument): Promise<User | null>

  • Purpose: Validates API key against user's stored credentials

  • Parameters:

    • apiKey: string - The API key to validate

    • user: UserDocument - User document for validation context

  • Returns: User object if valid, null if invalid

  • Database Query: { _id: user._id, "tags.key": "api-key", "tags.value": apiKey }

  • Error Handling: Throws InternalServerErrorException on database errors

extractApiKeyFromHeader(request: Request): string | null

  • Purpose: Extracts API key from Authorization header

  • Parameters: request: Request - HTTP request object

  • Returns: API key string or null if not found

  • Format: Expects "Bearer {api-key}" format

  • Validation: Strips Bearer prefix and validates format

getUserByApiKey(apiKey: string): Promise<User | null>

  • Purpose: Retrieves user by API key

  • Parameters: apiKey: string - API key to search for

  • Returns: User object or null if not found

  • Database Query: Searches users collection for matching tag

  • Indexing: Optimized for tag-based queries

ApiKeyAuthGuard

Guard Implementation

canActivate(context: ExecutionContext): Promise<boolean>

  • Purpose: Guards routes requiring API key authentication

  • Parameters: context: ExecutionContext - NestJS execution context

  • Returns: Boolean indicating authentication success

  • Process: Extracts key, validates, attaches user to request

  • Integration: Extends Passport AuthGuard with 'api-key' strategy

ApiKeyStrategy

Passport Strategy

Strategy Configuration

  • Header: Authorization

  • Prefix: Bearer

  • Session Support: Enabled for stateful authentication

  • Validation: Custom user-based API key validation

validate(apiKey: string): Promise<User>

  • Purpose: Core validation method called by Passport

  • Parameters: apiKey: string - Extracted API key

  • Returns: Authenticated user object

  • Process: Database lookup, validation, user return

  • Error Handling: Throws UnauthorizedException on validation failure

User Tag Structure

Database Schema

API keys are stored in the user document's tags array:

interface UserTag {
  key: 'api-key';
  value: string;  // The actual API key
}

interface User {
  _id: string;
  tags: UserTag[];
  // ... other user properties
}

Error Types

Error Type
Status Code
Description
Resolution

UnauthorizedException

401

Invalid or missing API key

Provide valid API key in Authorization header

ForbiddenException

403

Valid key but insufficient permissions

Check user permissions and access level

InternalServerErrorException

500

Database or validation error

Check database connection and service health

BadRequestException

400

Malformed Authorization header

Use proper "Bearer {api-key}" format


📖 Guides

API Key Generation Guide

Complete guide to generating and managing API keys for users. This module provides comprehensive API key generation functionality with secure random key creation, user tag integration, and metadata management for enterprise applications.

Route Protection Guide

Advanced route protection patterns and guard configuration. Learn how to implement route-level authentication using the ApiKeyAuthGuard, configure global protection, and customize authentication behavior for different endpoints.

User Integration Guide

Integrating with @hsuite/users module and tag management. The API key system seamlessly integrates with the HSuite user management system by storing API keys in user tags, enabling flexible key-to-user relationships and permission management.

Security Best Practices Guide

Security recommendations and authentication patterns. This covers secure API key generation, proper header formatting, rate limiting implementation, key rotation strategies, and protection against common authentication vulnerabilities.


🎯 Examples

Enterprise API Key Management Service

import { ApiKeyService, ApiKeyAuthGuard } from '@hsuite/api-key';
import { Injectable, Logger, UnauthorizedException } from '@nestjs/common';
import { UsersService } from '@hsuite/users';

@Injectable()
export class EnterpriseApiKeyService {
  private readonly logger = new Logger(EnterpriseApiKeyService.name);

  constructor(
    private readonly apiKeyService: ApiKeyService,
    private readonly usersService: UsersService
  ) {}

  async generateApiKeyForUser(userId: string, keyName?: string) {
    try {
      // Generate secure API key
      const apiKey = await this.generateSecureApiKey();
      
      // Get user document
      const user = await this.usersService.findById(userId);
      if (!user) {
        throw new Error('User not found');
      }

      // Add API key to user tags
      const tagData = {
        key: 'api-key',
        value: apiKey,
        metadata: {
          name: keyName || 'Default API Key',
          createdAt: new Date().toISOString(),
          lastUsed: null,
          permissions: ['read', 'write'],
          rateLimit: {
            requests: 1000,
            period: 'hour'
          }
        }
      };

      await this.usersService.addTag(userId, tagData);

      this.logger.log(`API key generated for user: ${userId}`);

      return {
        success: true,
        apiKey,
        keyInfo: {
          userId,
          keyName: tagData.metadata.name,
          permissions: tagData.metadata.permissions,
          rateLimit: tagData.metadata.rateLimit,
          createdAt: tagData.metadata.createdAt
        },
        usage: {
          headerFormat: `Authorization: Bearer ${apiKey}`,
          curlExample: `curl -H "Authorization: Bearer ${apiKey}" https://api.example.com/protected`
        }
      };

    } catch (error) {
      this.logger.error('API key generation error:', error);
      throw new Error(`Failed to generate API key: ${error.message}`);
    }
  }

  async validateEnterpriseApiKey(apiKey: string, requiredPermissions: string[] = []) {
    try {
      // Find user by API key
      const user = await this.getUserByApiKey(apiKey);
      if (!user) {
        throw new UnauthorizedException('Invalid API key');
      }

      // Get API key metadata
      const apiKeyTag = user.tags.find(tag => 
        tag.key === 'api-key' && tag.value === apiKey
      );

      if (!apiKeyTag || !apiKeyTag.metadata) {
        throw new UnauthorizedException('API key metadata not found');
      }

      // Check permissions
      const hasRequiredPermissions = requiredPermissions.every(permission =>
        apiKeyTag.metadata.permissions?.includes(permission)
      );

      if (!hasRequiredPermissions) {
        throw new UnauthorizedException('Insufficient API key permissions');
      }

      // Check rate limiting
      const rateLimitCheck = await this.checkRateLimit(user._id, apiKey);
      if (!rateLimitCheck.allowed) {
        throw new UnauthorizedException(`Rate limit exceeded: ${rateLimitCheck.message}`);
      }

      // Update last used timestamp
      await this.updateLastUsed(user._id, apiKey);

      return {
        user,
        apiKeyInfo: apiKeyTag.metadata,
        rateLimitStatus: rateLimitCheck
      };

    } catch (error) {
      this.logger.error('API key validation error:', error);
      throw error;
    }
  }

  async revokeApiKey(userId: string, apiKey: string) {
    try {
      const user = await this.usersService.findById(userId);
      if (!user) {
        throw new Error('User not found');
      }

      // Remove API key tag
      await this.usersService.removeTag(userId, 'api-key', apiKey);

      this.logger.log(`API key revoked for user: ${userId}`);

      return {
        success: true,
        message: 'API key successfully revoked',
        revokedAt: new Date().toISOString()
      };

    } catch (error) {
      this.logger.error('API key revocation error:', error);
      throw error;
    }
  }

  async listUserApiKeys(userId: string) {
    try {
      const user = await this.usersService.findById(userId);
      if (!user) {
        throw new Error('User not found');
      }

      const apiKeys = user.tags
        .filter(tag => tag.key === 'api-key')
        .map(tag => ({
          id: this.hashApiKey(tag.value), // Don't expose full key
          name: tag.metadata?.name || 'Unnamed Key',
          permissions: tag.metadata?.permissions || [],
          createdAt: tag.metadata?.createdAt,
          lastUsed: tag.metadata?.lastUsed,
          rateLimit: tag.metadata?.rateLimit,
          status: 'active'
        }));

      return {
        success: true,
        userId,
        apiKeys,
        totalKeys: apiKeys.length
      };

    } catch (error) {
      this.logger.error('API key listing error:', error);
      throw error;
    }
  }

  private async generateSecureApiKey(): Promise<string> {
    const crypto = require('crypto');
    const prefix = 'hsk'; // HSuite Key prefix
    const randomBytes = crypto.randomBytes(32).toString('hex');
    return `${prefix}_${randomBytes}`;
  }

  private async getUserByApiKey(apiKey: string) {
    return await this.usersService.findOne({
      'tags.key': 'api-key',
      'tags.value': apiKey
    });
  }

  private async checkRateLimit(userId: string, apiKey: string): Promise<any> {
    // Implementation would check Redis for rate limiting
    return {
      allowed: true,
      remaining: 999,
      resetTime: new Date(Date.now() + 3600000).toISOString()
    };
  }

  private async updateLastUsed(userId: string, apiKey: string) {
    // Implementation would update the tag metadata
    await this.usersService.updateTagMetadata(userId, 'api-key', apiKey, {
      lastUsed: new Date().toISOString()
    });
  }

  private hashApiKey(apiKey: string): string {
    const crypto = require('crypto');
    return crypto.createHash('sha256').update(apiKey).digest('hex').substring(0, 8);
  }
}

Advanced Route Protection Implementation

import { ApiKeyAuthGuard } from '@hsuite/api-key';
import { Controller, Get, Post, UseGuards, SetMetadata, createParamDecorator, ExecutionContext } from '@nestjs/common';

// Custom decorator for API key permissions
export const RequirePermissions = (...permissions: string[]) => 
  SetMetadata('apikey-permissions', permissions);

// Parameter decorator to get API key info
export const ApiKeyInfo = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.apiKeyInfo; // Set by enhanced guard
  },
);

@Controller('enterprise')
export class EnterpriseController {
  
  @UseGuards(ApiKeyAuthGuard)
  @Get('public-data')
  async getPublicData() {
    return {
      data: 'Public enterprise data',
      accessLevel: 'basic',
      timestamp: new Date().toISOString()
    };
  }

  @UseGuards(ApiKeyAuthGuard)
  @RequirePermissions('read', 'analytics')
  @Get('analytics')
  async getAnalyticsData(@ApiKeyInfo() keyInfo: any) {
    return {
      data: 'Advanced analytics data',
      accessLevel: 'analytics',
      keyName: keyInfo?.name,
      permissions: keyInfo?.permissions,
      timestamp: new Date().toISOString()
    };
  }

  @UseGuards(ApiKeyAuthGuard)
  @RequirePermissions('write', 'admin')
  @Post('admin-operation')
  async performAdminOperation(@ApiKeyInfo() keyInfo: any) {
    return {
      operation: 'Admin operation completed',
      executedBy: keyInfo?.name,
      timestamp: new Date().toISOString(),
      permissions: keyInfo?.permissions
    };
  }
}

// Enhanced guard with permission checking
@Injectable()
export class EnhancedApiKeyGuard extends ApiKeyAuthGuard {
  constructor(
    private reflector: Reflector,
    private enterpriseApiKeyService: EnterpriseApiKeyService
  ) {
    super();
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    // First check basic API key authentication
    const basicAuth = await super.canActivate(context);
    if (!basicAuth) return false;

    // Get required permissions from metadata
    const requiredPermissions = this.reflector.getAllAndOverride<string[]>(
      'apikey-permissions',
      [context.getHandler(), context.getClass()]
    );

    if (!requiredPermissions) return true; // No specific permissions required

    // Extract API key and validate permissions
    const request = context.switchToHttp().getRequest();
    const apiKey = this.extractApiKey(request);
    
    try {
      const validation = await this.enterpriseApiKeyService.validateEnterpriseApiKey(
        apiKey,
        requiredPermissions
      );

      // Attach API key info to request for later use
      request.apiKeyInfo = validation.apiKeyInfo;
      
      return true;
    } catch (error) {
      return false;
    }
  }

  private extractApiKey(request: any): string {
    const authHeader = request.headers.authorization;
    if (authHeader && authHeader.startsWith('Bearer ')) {
      return authHeader.substring(7);
    }
    return null;
  }
}

Multi-Application API Key Integration

import { ApiKeyService } from '@hsuite/api-key';
import { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class MultiAppApiKeyService {
  private readonly logger = new Logger(MultiAppApiKeyService.name);

  constructor(private readonly apiKeyService: ApiKeyService) {}

  async configureApplicationApiKeys() {
    const applications = [
      {
        name: 'Smart Node Dashboard',
        permissions: ['read', 'write', 'admin'],
        rateLimit: { requests: 10000, period: 'hour' }
      },
      {
        name: 'Analytics Service',
        permissions: ['read', 'analytics'],
        rateLimit: { requests: 5000, period: 'hour' }
      },
      {
        name: 'Mobile App',
        permissions: ['read'],
        rateLimit: { requests: 1000, period: 'hour' }
      }
    ];

    const results = [];

    for (const app of applications) {
      try {
        const apiKeyResult = await this.generateApplicationApiKey(app);
        results.push(apiKeyResult);
        
        this.logger.log(`API key configured for application: ${app.name}`);
      } catch (error) {
        this.logger.error(`Failed to configure API key for ${app.name}:`, error);
        results.push({
          application: app.name,
          success: false,
          error: error.message
        });
      }
    }

    return {
      success: true,
      configuredApplications: results.length,
      results
    };
  }

  async validateCrossApplicationAccess(apiKey: string, targetApplication: string) {
    try {
      const validation = await this.apiKeyService.validateApiKey(apiKey);
      
      if (!validation) {
        throw new Error('Invalid API key');
      }

      // Check application-specific access
      const hasApplicationAccess = await this.checkApplicationAccess(
        validation.user,
        targetApplication
      );

      if (!hasApplicationAccess) {
        throw new Error(`Access denied for application: ${targetApplication}`);
      }

      return {
        valid: true,
        user: validation.user,
        application: targetApplication,
        accessLevel: this.getAccessLevel(validation.user, targetApplication)
      };

    } catch (error) {
      this.logger.error('Cross-application access validation error:', error);
      throw error;
    }
  }

  private async generateApplicationApiKey(appConfig: any) {
    // Implementation would create application-specific API keys
    const apiKey = `app_${appConfig.name.toLowerCase().replace(/\s+/g, '_')}_${Date.now()}`;
    
    return {
      application: appConfig.name,
      apiKey,
      permissions: appConfig.permissions,
      rateLimit: appConfig.rateLimit,
      success: true
    };
  }

  private async checkApplicationAccess(user: any, application: string): Promise<boolean> {
    // Implementation would check user's application access rights
    return true; // Simplified for example
  }

  private getAccessLevel(user: any, application: string): string {
    // Implementation would determine access level based on user and application
    return 'standard'; // Simplified for example
  }
}

🔗 Integration

Required Dependencies

{
  "@nestjs/common": "^10.4.2",
  "@nestjs/core": "^10.4.2",
  "@nestjs/passport": "^10.0.3",
  "passport": "^0.7.0",
  "passport-headerapikey": "^1.2.2",
  "@hsuite/users": "^2.1.0",
  "@hsuite/helpers": "^2.0.8"
}

Environment Configuration

# API Key Authentication Configuration
API_KEY_ENABLED=true
API_KEY_GLOBAL_GUARD=true
API_KEY_SESSION_SUPPORT=true

# Rate Limiting Configuration
API_KEY_RATE_LIMIT_ENABLED=true
API_KEY_DEFAULT_RATE_LIMIT=1000
API_KEY_RATE_LIMIT_PERIOD=hour

# Security Configuration
API_KEY_REQUIRE_BEARER=true
API_KEY_MIN_LENGTH=32
API_KEY_ENCRYPTION_ENABLED=false

Module Integration

import { ApiKeyModule } from '@hsuite/api-key';
import { UsersModule } from '@hsuite/users';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot(),
    UsersModule.forRootAsync({
      useFactory: (config: ConfigService) => ({
        mongodb: {
          uri: config.get('MONGODB_URI')
        }
      }),
      inject: [ConfigService]
    }),
    ApiKeyModule.forRoot()
  ]
})
export class ApiKeyIntegrationModule {}

Request Flow Example

// 1. Client makes request with API key
const response = await fetch('/api/protected', {
  headers: {
    'Authorization': 'Bearer hsk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6'
  }
});

// 2. ApiKeyAuthGuard intercepts request
// 3. ApiKeyStrategy extracts and validates key
// 4. ApiKeyService queries user database
// 5. User object attached to request
// 6. Route handler receives authenticated request

Database Queries

// User lookup by API key
db.users.find({
  "tags.key": "api-key",
  "tags.value": "hsk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
});

// Recommended index for performance
db.users.createIndex({ "tags.key": 1, "tags.value": 1 });

🔐 Secure Authentication: Enterprise-grade API key validation with user-based ownership and tag storage.

🛡️ Route Protection: Comprehensive guard system with Passport.js integration and flexible protection patterns.

🌐 HSuite Integration: Seamless compatibility with @hsuite/users module and ecosystem-wide authentication standards.


Built with ❤️ by the HbarSuite Team Copyright © 2024 HbarSuite. All rights reserved.

Quick Start
Architecture
API Reference
Guides
Examples
Integration