import { Repository } from 'typeorm'; import { BaseApiKey } from '../entities/api-key.entity'; import { BaseUser } from '../entities/user.entity'; import { NAuthConfig } from '../interfaces/config.interface'; import { NAuthLogger } from '../utils/nauth-logger'; import { InternalAuthAuditService } from './auth-audit.service'; import { CreateApiKeyDTO, UpdateApiKeyDTO, RevokeApiKeyDTO, DeleteApiKeyDTO, ApiKeyResponseDTO, CreateApiKeyResponseDTO, ListApiKeysResponseDTO, RevokeApiKeyResponseDTO, DeleteApiKeyResponseDTO } from '../dto/api-key.dto'; import { AdminCreateApiKeyDTO, AdminUpdateApiKeyDTO, AdminManageApiKeyDTO } from '../dto/admin-api-key.dto'; /** Result of a successful API key validation (internal auth path). */ export interface ApiKeyValidationResult { /** External key identifier (UUID v4) */ keyId: string; /** Owning user's external identifier (UUID v4) — callers load the user context from this */ sub: string; } /** * API Key Service * * Owns the full API key lifecycle and validation. Keys authenticate **as their owning user**. * * Identity convention (matches the rest of the toolkit): * - **Self-service** methods (`createKey`, `listKeys`, `updateKey`, `revokeKey`, `deleteKey`) * act on the *currently authenticated* user, resolved from request context. They take no * user identifier. * - **Admin** methods (`adminCreateKey`, `adminListKeys`, `adminUpdateKey`, `adminRevokeKey`, * `adminDeleteKey`) act on a target user identified by `sub`. Protect them with admin auth. * * Every public method takes a request DTO and returns a response DTO, and validates the DTO at * runtime (via {@link ensureValidatedDto}) so non-NestJS callers are protected from invalid input. * * Security: * - Only a SHA-256 hash of the key is stored; the plaintext is returned once at creation. * - Presented keys are hashed and looked up by that hash (indexed, unique) — the plaintext never * leaves the caller and is never compared field-by-field. * - Per-key IP allowlists (optional) restrict which source IPs may use a key. */ export declare class ApiKeyService { private readonly apiKeyRepository; private readonly userRepository; private readonly config; private readonly logger; private readonly auditService?; constructor(apiKeyRepository: Repository, userRepository: Repository, config: NAuthConfig, logger: NAuthLogger, auditService?: InternalAuthAuditService | undefined); /** * Create an API key for the currently authenticated user. * * @throws {NAuthException} API_KEY_CREATION_DISABLED, API_KEY_LIMIT_REACHED, * API_KEY_EXPIRY_REQUIRED, API_KEY_INDEFINITE_NOT_ALLOWED, API_KEY_EXPIRY_TOO_LONG, * VALIDATION_FAILED, FORBIDDEN (not authenticated) */ createKey(dto: CreateApiKeyDTO): Promise; /** * List the current user's API keys (sanitized; never includes secrets). */ listKeys(): Promise; /** * Update the current user's key (label and/or IP allowlist). Secret and expiry are immutable. * * @throws {NAuthException} API_KEY_NOT_FOUND, VALIDATION_FAILED, FORBIDDEN */ updateKey(dto: UpdateApiKeyDTO): Promise; /** * Revoke (soft-delete) one of the current user's keys. * * @throws {NAuthException} API_KEY_NOT_FOUND, FORBIDDEN */ revokeKey(dto: RevokeApiKeyDTO): Promise; /** * Permanently delete one of the current user's keys. * * @throws {NAuthException} API_KEY_NOT_FOUND, FORBIDDEN */ deleteKey(dto: DeleteApiKeyDTO): Promise; /** * Create an API key on behalf of a user. Bypasses `allowUserCreation`, but still enforces * `maxKeysPerUser`, expiry, and IP-restriction rules. * * @throws {NAuthException} USER_NOT_FOUND, or any API_KEY_* creation error */ adminCreateKey(dto: AdminCreateApiKeyDTO): Promise; /** * List a user's API keys (admin). * * @throws {NAuthException} USER_NOT_FOUND */ adminListKeys(dto: AdminManageApiKeyDTO): Promise; /** * Update a user's key (admin). * * @throws {NAuthException} USER_NOT_FOUND, API_KEY_NOT_FOUND, VALIDATION_FAILED */ adminUpdateKey(dto: AdminUpdateApiKeyDTO): Promise; /** * Revoke (soft-delete) a user's key (admin). * * @throws {NAuthException} USER_NOT_FOUND, API_KEY_NOT_FOUND, VALIDATION_FAILED */ adminRevokeKey(dto: AdminManageApiKeyDTO): Promise; /** * Permanently delete a user's key (admin). * * @throws {NAuthException} USER_NOT_FOUND, API_KEY_NOT_FOUND, VALIDATION_FAILED */ adminDeleteKey(dto: AdminManageApiKeyDTO): Promise; /** * Validate a presented API key and resolve its owner. * * On any failure this throws a precise {@link NAuthException} (access denied) — callers * MUST NOT fall back to other credentials. * * @param rawKey - The full plaintext key from the request header * @param callerIp - Source IP of the request (for IP-allowlist enforcement + usage tracking) * @throws {NAuthException} API_KEY_INVALID, API_KEY_EXPIRED, API_KEY_IP_NOT_ALLOWED */ validateKey(rawKey: string, callerIp?: string | null): Promise; /** * Core key creation for a resolved user. */ private createForUser; /** * List a resolved user's keys. */ private listForUser; /** * Update a resolved user's key (label / IP allowlist). */ private updateForUser; /** * Revoke (soft-delete) a resolved user's key. */ private revokeForUser; /** * Permanently delete a resolved user's key. */ private deleteForUser; /** * Resolve the currently authenticated user from request context. * * @throws {NAuthException} FORBIDDEN when no authenticated user is present */ private getCurrentUserOrThrow; /** * Resolve an internal user id from an external sub (UUID). * * @throws {NAuthException} USER_NOT_FOUND */ private resolveUserIdBySub; /** * Ensure a keyId is present for admin revoke/delete operations. */ private requireKeyId; /** * Resolve the mandatory, config-bounded expiry. */ private resolveExpiry; /** * Validate and normalize an IP allowlist per configuration. */ private normalizeAllowedIps; /** * Compute the SHA-256 hex hash of a key string (used for storage + indexed lookup). */ private hashKey; /** * Update last-used metadata, throttled to avoid a write on every request. * Never throws — usage tracking must not block authentication. */ private recordUsage; /** * Build a sanitized response DTO from an entity. */ private toResponse; /** * Record an audit event (no-op when audit logging is disabled). Never throws. */ private audit; } //# sourceMappingURL=api-key.service.d.ts.map