Documentation Index
Fetch the complete documentation index at: https://mintlify.com/InsForge/InsForge/llms.txt
Use this file to discover all available pages before exploring further.
Authentication Methods
InsForge supports three authentication methods:
1. JWT Tokens (User Authentication)
JSON Web Tokens for user sessions with 24-hour expiration.
Token Structure:
{
sub: string, // User ID
email: string, // User email
role: 'authenticated' | 'project_admin',
iat: number, // Issued at timestamp
exp: number // Expiration timestamp
}
Token Generation:
const accessToken = tokenManager.generateAccessToken({
sub: userId,
email: user.email,
role: 'authenticated'
});
Usage:
curl -H "Authorization: Bearer <jwt_token>" \
https://your-app.insforge.app/api/resource
2. API Keys (Service Authentication)
Long-lived credentials for server-to-server communication.
Format: ik_<random_string> (minimum 32 characters)
Storage:
- Hashed with bcrypt (cost factor: 10)
- Stored in
auth.secrets table
- Never logged or exposed in responses
Usage:
# Method 1: Bearer token (recommended)
curl -H "Authorization: Bearer ik_your_api_key" \
https://your-app.insforge.app/api/resource
# Method 2: x-api-key header (legacy)
curl -H "x-api-key: ik_your_api_key" \
https://your-app.insforge.app/api/resource
API Key Security:
- Never commit API keys to version control
- Rotate keys regularly (every 90 days recommended)
- Use different keys for different environments
- Revoke compromised keys immediately via dashboard
3. OAuth 2.0 (Social Login)
Supported providers:
- Google
- GitHub
- Discord
- Microsoft
- LinkedIn
- X (Twitter)
- Apple
- Facebook
OAuth Flow:
Configuration:
# Google OAuth
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
# GitHub OAuth
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-secret
Authorization System
Role-Based Access Control (RBAC)
Three built-in roles:
| Role | Description | Use Case |
|---|
anon | Unauthenticated users | Public read access |
authenticated | Logged-in users | Standard user operations |
project_admin | System administrators | Full access to all resources |
Middleware Implementation:
// Verify user (authenticated or admin)
export async function verifyUser(
req: AuthRequest,
res: Response,
next: NextFunction
) {
const apiKey = extractApiKey(req);
if (apiKey) {
return verifyApiKey(req, res, next);
}
return verifyToken(req, res, next);
}
// Verify admin only
export async function verifyAdmin(
req: AuthRequest,
res: Response,
next: NextFunction
) {
const payload = tokenManager.verifyToken(token);
if (payload.role !== 'project_admin') {
throw new AppError('Admin access required', 403);
}
next();
}
Row Level Security (RLS)
PostgreSQL RLS policies enforce data-level access control.
How RLS Works:
- PostgREST sets
request.jwt.claim.role based on JWT
- PostgreSQL applies policies based on current role
- Users only see data they’re authorized to access
Auto-Generated Policy:
-- Automatically created for tables with RLS enabled
CREATE POLICY "project_admin_policy"
ON your_table
FOR ALL
TO project_admin
USING (true)
WITH CHECK (true);
Custom User Policies:
-- Example: Users can only read/update their own data
CREATE POLICY "user_select_own"
ON users
FOR SELECT
TO authenticated
USING (auth.uid() = id);
CREATE POLICY "user_update_own"
ON users
FOR UPDATE
TO authenticated
USING (auth.uid() = id)
WITH CHECK (auth.uid() = id);
-- Example: Public read access
CREATE POLICY "public_read"
ON posts
FOR SELECT
TO anon, authenticated
USING (published = true);
Helper Function:
-- Get current authenticated user ID
CREATE FUNCTION auth.uid() RETURNS UUID AS $$
SELECT NULLIF(current_setting('request.jwt.claim.sub', true), '')::uuid;
$$ LANGUAGE SQL STABLE;
Always enable RLS on tables containing user data:ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
Without RLS policies, tables default to deny all access for anon and authenticated roles.
Encryption
Database Encryption
Application-Level Encryption:
Using PostgreSQL’s pgcrypto extension:
-- Encrypt sensitive data
INSERT INTO secrets (key, value)
VALUES (
'api_key',
pgp_sym_encrypt('secret_value', current_setting('app.encryption_key'))
);
-- Decrypt data
SELECT
key,
pgp_sym_decrypt(value::bytea, current_setting('app.encryption_key')) as decrypted_value
FROM secrets;
Configuration:
postgres:
command: postgres -c config_file=/etc/postgresql/postgresql.conf
-c app.encryption_key='${ENCRYPTION_KEY:-${JWT_SECRET}}'
# Primary encryption key (falls back to JWT_SECRET)
ENCRYPTION_KEY=your-32-char-or-longer-encryption-key
Password Hashing
Algorithm: bcrypt with cost factor 10
import bcrypt from 'bcryptjs';
// Registration
const hashedPassword = await bcrypt.hash(password, 10);
// Login validation
const validPassword = await bcrypt.compare(password, dbUser.password);
Password Requirements:
Configurable via auth.auth_config table:
- Minimum length (default: 8 characters)
- Require uppercase letters
- Require lowercase letters
- Require numbers
- Require special characters
API Key Hashing
Storage Implementation:
// Generate and store API key
async createApiKey(): Promise<string> {
const apiKey = `ik_${crypto.randomBytes(32).toString('hex')}`;
const hashedKey = await bcrypt.hash(apiKey, 10);
await pool.query(
'INSERT INTO auth.secrets (key, value) VALUES ($1, $2)',
['project_api_key', hashedKey]
);
return apiKey; // Return only once, never stored plain
}
// Verify API key
async verifyApiKey(apiKey: string): Promise<boolean> {
const result = await pool.query(
'SELECT value FROM auth.secrets WHERE key = $1',
['project_api_key']
);
if (!result.rows[0]) return false;
return bcrypt.compare(apiKey, result.rows[0].value);
}
Security Best Practices
Environment Variables
Critical Security Settings:# REQUIRED: Change these in production
JWT_SECRET=your-secret-key-min-32-chars-recommended-64
ENCRYPTION_KEY=different-key-from-jwt-secret-32-chars-min
ADMIN_PASSWORD=strong-unique-password-change-immediately
POSTGRES_PASSWORD=secure-database-password
# Generate secure secrets:
openssl rand -base64 48 # For JWT_SECRET
openssl rand -hex 32 # For ENCRYPTION_KEY
Network Security
Production Checklist:
Database Security
Connection Security:
# Production: Use SSL connections
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=require
Audit Logging:
Enable PostgreSQL audit logs:
-- Track all admin actions
CREATE TABLE auth.audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID,
action TEXT,
table_name TEXT,
timestamp TIMESTAMPTZ DEFAULT NOW()
);
-- Trigger function
CREATE FUNCTION log_changes() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO auth.audit_logs (user_id, action, table_name)
VALUES (auth.uid(), TG_OP, TG_TABLE_NAME);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Token Security
JWT Best Practices:
- Short expiration: 24 hours (configurable)
- Refresh tokens: Not implemented yet (coming soon)
- Token storage:
- Frontend: Use
httpOnly cookies (not localStorage)
- Mobile: Secure keychain/keystore
- Token revocation: Clear server-side sessions on logout
Secure File Upload
Upload Validation:
const MAX_FILE_SIZE = process.env.MAX_FILE_SIZE || 52428800; // 50MB
const ALLOWED_MIME_TYPES = [
'image/jpeg',
'image/png',
'image/webp',
'application/pdf'
];
function validateFile(file: File): void {
if (file.size > MAX_FILE_SIZE) {
throw new Error('File too large');
}
if (!ALLOWED_MIME_TYPES.includes(file.mimetype)) {
throw new Error('Invalid file type');
}
}
Compliance
GDPR Considerations
User Data Rights:
- Right to access: Provide user data export API
- Right to deletion: Cascade delete user records
- Right to portability: JSON export format
- Privacy by design: RLS policies enforce data isolation
Implementation:
// Export user data
GET /auth/user/export
// Delete user account
DELETE /auth/user/:id
Data Retention
-- Auto-delete old audit logs (90 days)
CREATE EXTENSION IF NOT EXISTS pg_cron;
SELECT cron.schedule(
'delete-old-audit-logs',
'0 0 * * *', -- Daily at midnight
$$DELETE FROM auth.audit_logs WHERE timestamp < NOW() - INTERVAL '90 days'$$
);
Vulnerability Reporting
If you discover a security vulnerability:
- Do not open a public GitHub issue
- Email: security@insforge.dev
- Include detailed reproduction steps
- Expected response time: 48 hours
Security Updates
Follow security updates: