API Key Auth Guard: extract key từ header, validate trong DB hoặc cache:
typescript
@Injectable()
export class ApiKeyGuard implements CanActivate {
constructor(private apiKeysService: ApiKeysService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const apiKey = request.headers['x-api-key'];
if (!apiKey) throw new UnauthorizedException('API key required');
const keyRecord = await this.apiKeysService.validateKey(apiKey);
if (!keyRecord) throw new UnauthorizedException('Invalid API key');
request.tenant = keyRecord.tenant; // Attach tenant context
return true;
}
}Multi-tenant pattern: mỗi request mang tenant context, services filter data theo tenant:
typescript
// REQUEST scope — instance riêng mỗi request
@Injectable({ scope: Scope.REQUEST })
export class TenantContext {
constructor(@Inject(REQUEST) private req: Request) {}
get tenantId(): string {
return (this.req as any).tenant?.id;
}
}Các strategies: separate DB per tenant, shared DB với tenant_id column, schema per tenant.
Cân bằng giữa isolation và cost.