A comprehensive npm package for preventing SaaS trial abuse through intelligent detection of suspicious sign-up patterns, including email similarity detection, temporary email blocking, IP analysis, and VPN detection.
- Email Similarity Detection: Identifies users creating multiple accounts with similar email addresses
- Temporary Email Blocking: Detects and blocks disposable/temporary email services
- IP Risk Analysis: Analyzes IP addresses for suspicious activity and hosting providers
- VPN/Proxy Detection: Identifies connections from VPN servers, proxies, and Tor networks
- Risk Scoring: Provides comprehensive risk scores with actionable recommendations
- Database Integration: Built-in adapters for MongoDB, PostgreSQL, and Redis
- Easy Integration: Simple API that works with any Node.js application
- TypeScript Support: Fully typed for better development experience
npm install trial-abuse-guardconst { TrialAbuseGuard } = require('trial-abuse-guard');
const guard = new TrialAbuseGuard();
// Check a user for trial abuse - exactly as requested!
const result = await guard.checkUser(
'[email protected]',
'192.168.1.100'
);
console.log(result.recommendation); // 'allow', 'flag', or 'block'
console.log(result.overall); // Risk score 0-100
console.log(result.details); // Detailed explanationThe package automatically maintains and updates a persistent list of temporary email domains:
// Automatic updates from multiple external sources
const guard = new TrialAbuseGuard({
tempEmailAutoUpdate: true, // Auto-update enabled (default)
tempEmailUpdateInterval: 24, // Update every 24 hours
tempEmailStoragePath: './domains.json' // Custom storage location
});
// Add your own domains to the blacklist
await guard.addTempEmailDomains(['suspicious.com', 'fake-trials.org']);
// Remove domains if needed
await guard.removeTempEmailDomains(['legit-domain.com']);
// Get statistics
const stats = guard.getTempEmailStats();
console.log(`Tracking ${stats.totalDomains} temp email domains`);
// Search domains
const results = guard.searchTempEmailDomains('temp');
// Export/Import domain lists
await guard.exportTempEmailDomains('./backup.json');
await guard.importTempEmailDomains('./custom-domains.txt');
// Force update from external sources
await guard.updateTempEmailDomains();The package provides seamless integration with popular authentication libraries:
import NextAuth from 'next-auth';
import { NextAuthTrialAbuseAdapter } from 'trial-abuse-guard/nextauth';
const trialAbuseAdapter = new NextAuthTrialAbuseAdapter({
blockHighRisk: true,
blockThreshold: 80,
onUserBlocked: async (email, riskData) => {
console.log(`Blocked user: ${email} (Risk: ${riskData.overall})`);
}
});
export const { handlers, auth } = NextAuth(
trialAbuseAdapter.getNextAuthConfig({
providers: [/* your providers */],
// Your existing config is preserved and enhanced
})
);Features:
- π« Automatically blocks high-risk sign-ups
β οΈ Flags suspicious users for review- π Adds risk data to session and JWT
- π§ Preserves all existing NextAuth configuration
- π― Custom callbacks for handling blocked/flagged users
// Webhook handler: app/api/webhooks/clerk/route.ts
import { ClerkTrialAbuseAdapter } from 'trial-abuse-guard/clerk';
const clerkAdapter = new ClerkTrialAbuseAdapter({
blockHighRisk: true,
clerkSecretKey: process.env.CLERK_SECRET_KEY,
onUserBlocked: async (email, riskData) => {
// User is automatically deleted from Clerk
console.log(`Blocked and deleted: ${email}`);
}
});
export async function POST(request) {
const webhookHandler = clerkAdapter.createWebhookHandler();
return Response.json(await webhookHandler(request));
}Features:
- ποΈ Automatically deletes high-risk users
- π·οΈ Adds risk metadata to user profiles
- π‘οΈ Middleware for route protection
- π Admin dashboard integration
- β‘ Real-time risk assessment
// Check risk before allowing signup
const { allowed, risk, action } = await clerkAdapter.preSignUpCheck(
email,
ipAddress
);
if (!allowed) {
return res.status(403).json({ error: 'Sign-up not available' });
}const { TrialAbuseGuard, MongoStorageAdapter } = require('trial-abuse-guard');
// Configure with MongoDB storage
const mongoAdapter = new MongoStorageAdapter({
connectionString: 'mongodb://localhost:27017',
databaseName: 'myapp'
});
await mongoAdapter.connect();
const guard = new TrialAbuseGuard({
// Detection settings
emailSimilarityCheck: true,
emailSimilarityThreshold: 0.8,
tempEmailCheck: true,
ipCheck: true,
vpnCheck: true,
// Custom disposable domains
customDisposableDomains: ['mydisposable.com'],
// API keys for enhanced detection
apiKeys: {
ipQualityScore: 'your-api-key',
vpnapi: 'your-api-key',
proxyCheck: 'your-api-key'
},
// Storage adapter
storageAdapter: mongoAdapter
});const express = require('express');
const { TrialAbuseGuard } = require('trial-abuse-guard');
const app = express();
const guard = new TrialAbuseGuard();
app.post('/register', async (req, res) => {
const { email } = req.body;
const ipAddress = req.ip;
const risk = await guard.checkUser(email, ipAddress);
if (risk.recommendation === 'block') {
return res.status(403).json({
error: 'Registration blocked due to security concerns'
});
}
// Proceed with registration...
});// pages/api/register.ts
import { TrialAbuseGuard } from 'trial-abuse-guard';
const guard = new TrialAbuseGuard();
export default async function handler(req, res) {
const { email } = req.body;
const ipAddress = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const risk = await guard.checkUser(email, ipAddress);
if (risk.recommendation === 'block') {
return res.status(403).json({ error: 'Registration not available' });
}
// Continue with registration...
}const { MongoStorageAdapter } = require('trial-abuse-guard');
const mongoAdapter = new MongoStorageAdapter({
connectionString: 'mongodb://localhost:27017',
databaseName: 'myapp',
collectionName: 'trial_users' // optional
});const { PostgreSQLStorageAdapter } = require('trial-abuse-guard');
const pgAdapter = new PostgreSQLStorageAdapter({
connectionString: 'postgresql://user:pass@localhost/mydb',
tableName: 'trial_users' // optional
});const { RedisStorageAdapter } = require('trial-abuse-guard');
const redisAdapter = new RedisStorageAdapter({
host: 'localhost',
port: 6379,
password: 'your-password', // optional
keyPrefix: 'trial_abuse:' // optional
});The package returns a comprehensive risk assessment:
{
overall: 75, // Overall risk score (0-100)
recommendation: 'flag', // 'allow', 'flag', or 'block'
factors: {
emailSimilarity: {
score: 85,
detected: true,
confidence: 0.9,
details: "Similar to existing emails: [email protected]"
},
tempEmail: {
score: 0,
detected: false,
confidence: 0.05,
details: "Email appears legitimate"
},
ipRisk: {
score: 60,
detected: true,
confidence: 0.8,
details: "IP Risk Score: 60, Country: US"
},
vpnDetection: {
score: 80,
detected: true,
confidence: 0.9,
details: "VPN/Proxy detected: VPN=true, Proxy=false, Tor=false"
}
},
details: [
"Similar to existing emails: [email protected]",
"VPN/Proxy detected: VPN=true, Proxy=false, Tor=false"
]
}For enhanced detection accuracy, obtain API keys from:
- IPQualityScore: https://www.ipqualityscore.com/
- VPNAPI: https://vpnapi.io/
- ProxyCheck: https://proxycheck.io/
The package works without API keys but with reduced detection capabilities.
| Score | Level | Recommendation | Action |
|---|---|---|---|
| 0-29 | Low | Allow | Proceed normally |
| 30-59 | Medium | Flag | Manual review recommended |
| 60-79 | High | Flag | Enhanced monitoring |
| 80-100 | Critical | Block | Deny access |
class CustomStorageAdapter {
async getExistingEmails() {
// Return array of existing emails
return ['[email protected]', '[email protected]'];
}
async getExistingIPs(email) {
// Return array of IPs for this email
return ['192.168.1.1', '203.0.113.1'];
}
async storeUserData(data) {
// Store user data for future comparisons
console.log('Storing:', data);
}
}
const guard = new TrialAbuseGuard({
storageAdapter: new CustomStorageAdapter()
});const {
EmailSimilarityDetector,
TempEmailDetector,
IPAnalyzer,
VPNDetector
} = require('trial-abuse-guard');
// Use individual detectors for specific needs
const emailDetector = new EmailSimilarityDetector(config);
const result = await emailDetector.checkSimilarity('[email protected]');npm test
npm run test:watch
npm run test:coverage- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
This package is designed to enhance security but should be part of a comprehensive security strategy. Always:
- Keep your API keys secure
- Regularly update the package
- Monitor and adjust risk thresholds based on your needs
- Implement proper logging and monitoring
- Lightweight with minimal dependencies
- Async/await support for non-blocking operations
- Caching strategies for improved performance
- Configurable timeouts for external API calls
- π Documentation
- π Issues
- π¬ Discussions
Transform your web forms into engaging, AI-powered conversations with Jotchats. Instead of static fields, guide users through natural, full-screen dialogues that feel like chatting with a helpful assistant.
Why Jotchats?
- π Higher Conversion Rates - See significant improvements in response rates vs. traditional forms
- π― Better Data Collection - Collect more accurate, detailed information through conversational flows
- π¨ Brand Integration - Customize the experience to match your brand perfectly
- π Smart Analytics - Track engagement and optimize your forms
- π Easy Integration - Embed seamlessly into websites, apps, or existing workflows
Perfect for lead capture, onboarding, surveys, feedback, and more. Replace clunky forms with something that actually drives results!
Learn more about Jotchats | Jotchats vs Typeform Comparison
Made with β€οΈ for the developer community