Skip to content

Authentication Guide

This guide covers authentication methods, security best practices, and implementation details for Trae IDE's authentication system.

Overview

Trae IDE supports multiple authentication methods to ensure secure access to your development environment:

  • Local Authentication: Username/password with local storage
  • OAuth 2.0: Integration with popular providers (GitHub, Google, Microsoft)
  • SAML 2.0: Enterprise single sign-on (SSO)
  • LDAP/Active Directory: Enterprise directory integration
  • Multi-Factor Authentication (MFA): Enhanced security with 2FA/TOTP
  • API Keys: Programmatic access for automation
  • JWT Tokens: Stateless authentication for distributed systems

Quick Start

Basic Setup

javascript
// Initialize authentication
const auth = new TraeAuth({
    provider: 'oauth2',
    clientId: 'your-client-id',
    redirectUri: 'http://localhost:3000/callback',
    scopes: ['read:user', 'repo']
});

// Login
auth.login().then(user => {
    console.log('Authenticated user:', user);
}).catch(error => {
    console.error('Authentication failed:', error);
});

Environment Configuration

bash
# .env file
TRAE_AUTH_PROVIDER=oauth2
TRAE_AUTH_CLIENT_ID=your-client-id
TRAE_AUTH_CLIENT_SECRET=your-client-secret
TRAE_AUTH_REDIRECT_URI=http://localhost:3000/callback
TRAE_JWT_SECRET=your-jwt-secret
TRAE_SESSION_TIMEOUT=3600

Authentication Methods

OAuth 2.0 Integration

GitHub OAuth

javascript
// GitHub OAuth configuration
const githubAuth = {
    provider: 'github',
    clientId: process.env.GITHUB_CLIENT_ID,
    clientSecret: process.env.GITHUB_CLIENT_SECRET,
    scope: 'user:email repo',
    endpoints: {
        authorization: 'https://github.com/login/oauth/authorize',
        token: 'https://github.com/login/oauth/access_token',
        userInfo: 'https://api.github.com/user'
    }
};

// Implementation
class GitHubAuthProvider {
    async authenticate(code) {
        // Exchange code for access token
        const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                client_id: this.clientId,
                client_secret: this.clientSecret,
                code: code
            })
        });
        
        const { access_token } = await tokenResponse.json();
        
        // Get user information
        const userResponse = await fetch('https://api.github.com/user', {
            headers: {
                'Authorization': `token ${access_token}`,
                'User-Agent': 'Trae-IDE'
            }
        });
        
        const user = await userResponse.json();
        
        return {
            id: user.id,
            username: user.login,
            email: user.email,
            name: user.name,
            avatar: user.avatar_url,
            provider: 'github',
            accessToken: access_token
        };
    }
}

Google OAuth

javascript
// Google OAuth configuration
const googleAuth = {
    provider: 'google',
    clientId: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    scope: 'openid email profile',
    endpoints: {
        authorization: 'https://accounts.google.com/o/oauth2/v2/auth',
        token: 'https://oauth2.googleapis.com/token',
        userInfo: 'https://www.googleapis.com/oauth2/v2/userinfo'
    }
};

// Google Auth implementation
class GoogleAuthProvider {
    async authenticate(code) {
        const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: new URLSearchParams({
                client_id: this.clientId,
                client_secret: this.clientSecret,
                code: code,
                grant_type: 'authorization_code',
                redirect_uri: this.redirectUri
            })
        });
        
        const { access_token, id_token } = await tokenResponse.json();
        
        // Verify and decode ID token
        const userInfo = this.decodeJWT(id_token);
        
        return {
            id: userInfo.sub,
            username: userInfo.email,
            email: userInfo.email,
            name: userInfo.name,
            avatar: userInfo.picture,
            provider: 'google',
            accessToken: access_token
        };
    }
    
    decodeJWT(token) {
        const [header, payload, signature] = token.split('.');
        return JSON.parse(atob(payload));
    }
}

Microsoft OAuth

javascript
// Microsoft OAuth configuration
const microsoftAuth = {
    provider: 'microsoft',
    clientId: process.env.MICROSOFT_CLIENT_ID,
    clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
    tenant: process.env.MICROSOFT_TENANT || 'common',
    scope: 'openid email profile User.Read',
    endpoints: {
        authorization: `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize`,
        token: `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token`,
        userInfo: 'https://graph.microsoft.com/v1.0/me'
    }
};

// Microsoft Auth implementation
class MicrosoftAuthProvider {
    async authenticate(code) {
        const tokenResponse = await fetch(
            `https://login.microsoftonline.com/${this.tenant}/oauth2/v2.0/token`,
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                body: new URLSearchParams({
                    client_id: this.clientId,
                    client_secret: this.clientSecret,
                    code: code,
                    grant_type: 'authorization_code',
                    redirect_uri: this.redirectUri,
                    scope: this.scope
                })
            }
        );
        
        const { access_token } = await tokenResponse.json();
        
        // Get user profile
        const userResponse = await fetch('https://graph.microsoft.com/v1.0/me', {
            headers: {
                'Authorization': `Bearer ${access_token}`
            }
        });
        
        const user = await userResponse.json();
        
        return {
            id: user.id,
            username: user.userPrincipalName,
            email: user.mail || user.userPrincipalName,
            name: user.displayName,
            provider: 'microsoft',
            accessToken: access_token
        };
    }
}

SAML 2.0 Integration

SAML Configuration

javascript
// SAML 2.0 configuration
const samlConfig = {
    entryPoint: 'https://your-idp.com/sso/saml',
    issuer: 'trae-ide',
    callbackUrl: 'https://your-app.com/auth/saml/callback',
    cert: process.env.SAML_CERT, // IdP certificate
    privateCert: process.env.SAML_PRIVATE_CERT, // SP private key
    identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
    signatureAlgorithm: 'sha256',
    digestAlgorithm: 'sha256'
};

// SAML implementation
class SAMLAuthProvider {
    constructor(config) {
        this.config = config;
        this.saml = new SAML(config);
    }
    
    async getLoginUrl() {
        return new Promise((resolve, reject) => {
            this.saml.getAuthorizeUrl({}, (err, loginUrl) => {
                if (err) reject(err);
                else resolve(loginUrl);
            });
        });
    }
    
    async validateResponse(samlResponse) {
        return new Promise((resolve, reject) => {
            this.saml.validatePostResponse({
                SAMLResponse: samlResponse
            }, (err, profile) => {
                if (err) reject(err);
                else {
                    resolve({
                        id: profile.nameID,
                        username: profile.nameID,
                        email: profile.email || profile.nameID,
                        name: profile.displayName || profile.name,
                        attributes: profile.attributes,
                        provider: 'saml'
                    });
                }
            });
        });
    }
}

SAML Metadata

xml
<!-- Service Provider Metadata -->
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
                     entityID="trae-ide">
    <md:SPSSODescriptor AuthnRequestsSigned="true"
                        WantAssertionsSigned="true"
                        protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        
        <md:KeyDescriptor use="signing">
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:X509Data>
                    <ds:X509Certificate><!-- Your certificate --></ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </md:KeyDescriptor>
        
        <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
        
        <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                                     Location="https://your-app.com/auth/saml/callback"
                                     index="1" />
    </md:SPSSODescriptor>
</md:EntityDescriptor>

LDAP/Active Directory Integration

LDAP Configuration

javascript
// LDAP configuration
const ldapConfig = {
    url: 'ldap://your-ldap-server:389',
    bindDN: 'cn=admin,dc=company,dc=com',
    bindCredentials: process.env.LDAP_PASSWORD,
    searchBase: 'ou=users,dc=company,dc=com',
    searchFilter: '(uid={{username}})',
    searchAttributes: ['uid', 'cn', 'mail', 'memberOf'],
    tlsOptions: {
        rejectUnauthorized: false
    }
};

// LDAP implementation
class LDAPAuthProvider {
    constructor(config) {
        this.config = config;
        this.client = ldap.createClient({
            url: config.url,
            tlsOptions: config.tlsOptions
        });
    }
    
    async authenticate(username, password) {
        try {
            // Bind with admin credentials
            await this.bind(this.config.bindDN, this.config.bindCredentials);
            
            // Search for user
            const user = await this.searchUser(username);
            if (!user) {
                throw new Error('User not found');
            }
            
            // Authenticate user
            await this.bind(user.dn, password);
            
            return {
                id: user.uid,
                username: user.uid,
                email: user.mail,
                name: user.cn,
                groups: user.memberOf || [],
                provider: 'ldap'
            };
        } catch (error) {
            throw new Error(`LDAP authentication failed: ${error.message}`);
        }
    }
    
    async bind(dn, password) {
        return new Promise((resolve, reject) => {
            this.client.bind(dn, password, (err) => {
                if (err) reject(err);
                else resolve();
            });
        });
    }
    
    async searchUser(username) {
        const searchFilter = this.config.searchFilter.replace('{{username}}', username);
        
        return new Promise((resolve, reject) => {
            this.client.search(this.config.searchBase, {
                filter: searchFilter,
                attributes: this.config.searchAttributes,
                scope: 'sub'
            }, (err, res) => {
                if (err) {
                    reject(err);
                    return;
                }
                
                let user = null;
                
                res.on('searchEntry', (entry) => {
                    user = {
                        dn: entry.dn.toString(),
                        ...entry.object
                    };
                });
                
                res.on('end', () => {
                    resolve(user);
                });
                
                res.on('error', (err) => {
                    reject(err);
                });
            });
        });
    }
}

Multi-Factor Authentication (MFA)

TOTP Implementation

javascript
// TOTP (Time-based One-Time Password) implementation
class TOTPProvider {
    constructor() {
        this.speakeasy = require('speakeasy');
        this.qrcode = require('qrcode');
    }
    
    generateSecret(username) {
        const secret = this.speakeasy.generateSecret({
            name: `Trae IDE (${username})`,
            issuer: 'Trae IDE',
            length: 32
        });
        
        return {
            secret: secret.base32,
            qrCodeUrl: secret.otpauth_url,
            backupCodes: this.generateBackupCodes()
        };
    }
    
    async generateQRCode(secret) {
        return await this.qrcode.toDataURL(secret.qrCodeUrl);
    }
    
    verifyToken(secret, token) {
        return this.speakeasy.totp.verify({
            secret: secret,
            encoding: 'base32',
            token: token,
            window: 2 // Allow 2 time steps (60 seconds) of drift
        });
    }
    
    generateBackupCodes() {
        const codes = [];
        for (let i = 0; i < 10; i++) {
            codes.push(Math.random().toString(36).substring(2, 10).toUpperCase());
        }
        return codes;
    }
}

// MFA workflow
class MFAManager {
    async enableMFA(userId) {
        const totp = new TOTPProvider();
        const secret = totp.generateSecret(userId);
        
        // Store secret temporarily (user needs to verify)
        await this.storeTempSecret(userId, secret);
        
        return {
            secret: secret.secret,
            qrCode: await totp.generateQRCode(secret),
            backupCodes: secret.backupCodes
        };
    }
    
    async verifyAndActivateMFA(userId, token) {
        const tempSecret = await this.getTempSecret(userId);
        const totp = new TOTPProvider();
        
        if (totp.verifyToken(tempSecret.secret, token)) {
            // Move from temp to permanent storage
            await this.activateMFA(userId, tempSecret);
            await this.deleteTempSecret(userId);
            return true;
        }
        
        return false;
    }
    
    async verifyMFA(userId, token) {
        const user = await this.getUser(userId);
        
        if (!user.mfaEnabled) {
            return true; // MFA not required
        }
        
        const totp = new TOTPProvider();
        
        // Check TOTP token
        if (totp.verifyToken(user.mfaSecret, token)) {
            return true;
        }
        
        // Check backup codes
        if (user.backupCodes.includes(token)) {
            await this.useBackupCode(userId, token);
            return true;
        }
        
        return false;
    }
}

SMS/Email MFA

javascript
// SMS MFA implementation
class SMSMFAProvider {
    constructor(twilioConfig) {
        this.twilio = require('twilio')(twilioConfig.accountSid, twilioConfig.authToken);
        this.fromNumber = twilioConfig.fromNumber;
    }
    
    async sendCode(phoneNumber) {
        const code = Math.floor(100000 + Math.random() * 900000).toString();
        
        await this.twilio.messages.create({
            body: `Your Trae IDE verification code is: ${code}`,
            from: this.fromNumber,
            to: phoneNumber
        });
        
        // Store code with expiration (5 minutes)
        await this.storeCode(phoneNumber, code, 300);
        
        return true;
    }
    
    async verifyCode(phoneNumber, code) {
        const storedCode = await this.getStoredCode(phoneNumber);
        
        if (storedCode && storedCode === code) {
            await this.deleteStoredCode(phoneNumber);
            return true;
        }
        
        return false;
    }
}

// Email MFA implementation
class EmailMFAProvider {
    constructor(emailConfig) {
        this.nodemailer = require('nodemailer');
        this.transporter = this.nodemailer.createTransporter(emailConfig);
    }
    
    async sendCode(email) {
        const code = Math.floor(100000 + Math.random() * 900000).toString();
        
        await this.transporter.sendMail({
            from: 'noreply@trae-ide.com',
            to: email,
            subject: 'Trae IDE Verification Code',
            html: `
                <h2>Verification Code</h2>
                <p>Your verification code is: <strong>${code}</strong></p>
                <p>This code will expire in 5 minutes.</p>
            `
        });
        
        // Store code with expiration
        await this.storeCode(email, code, 300);
        
        return true;
    }
    
    async verifyCode(email, code) {
        const storedCode = await this.getStoredCode(email);
        
        if (storedCode && storedCode === code) {
            await this.deleteStoredCode(email);
            return true;
        }
        
        return false;
    }
}

API Key Authentication

API Key Management

javascript
// API Key implementation
class APIKeyManager {
    async generateAPIKey(userId, name, permissions = []) {
        const key = this.generateSecureKey();
        const hashedKey = await this.hashKey(key);
        
        const apiKey = {
            id: this.generateId(),
            userId: userId,
            name: name,
            keyHash: hashedKey,
            permissions: permissions,
            createdAt: new Date(),
            lastUsed: null,
            isActive: true
        };
        
        await this.storeAPIKey(apiKey);
        
        // Return the plain key only once
        return {
            id: apiKey.id,
            key: key,
            name: name,
            permissions: permissions
        };
    }
    
    async validateAPIKey(key) {
        const hashedKey = await this.hashKey(key);
        const apiKey = await this.getAPIKeyByHash(hashedKey);
        
        if (!apiKey || !apiKey.isActive) {
            return null;
        }
        
        // Update last used timestamp
        await this.updateLastUsed(apiKey.id);
        
        return {
            id: apiKey.id,
            userId: apiKey.userId,
            permissions: apiKey.permissions
        };
    }
    
    generateSecureKey() {
        const crypto = require('crypto');
        return 'trae_' + crypto.randomBytes(32).toString('hex');
    }
    
    async hashKey(key) {
        const crypto = require('crypto');
        return crypto.createHash('sha256').update(key).digest('hex');
    }
    
    async revokeAPIKey(keyId) {
        await this.updateAPIKey(keyId, { isActive: false });
    }
    
    async listAPIKeys(userId) {
        const keys = await this.getAPIKeysByUser(userId);
        
        return keys.map(key => ({
            id: key.id,
            name: key.name,
            permissions: key.permissions,
            createdAt: key.createdAt,
            lastUsed: key.lastUsed,
            isActive: key.isActive
        }));
    }
}

// API Key middleware
function apiKeyAuth(requiredPermissions = []) {
    return async (req, res, next) => {
        const authHeader = req.headers.authorization;
        
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
            return res.status(401).json({ error: 'API key required' });
        }
        
        const apiKey = authHeader.substring(7);
        const keyManager = new APIKeyManager();
        
        try {
            const validatedKey = await keyManager.validateAPIKey(apiKey);
            
            if (!validatedKey) {
                return res.status(401).json({ error: 'Invalid API key' });
            }
            
            // Check permissions
            if (requiredPermissions.length > 0) {
                const hasPermission = requiredPermissions.every(permission => 
                    validatedKey.permissions.includes(permission)
                );
                
                if (!hasPermission) {
                    return res.status(403).json({ error: 'Insufficient permissions' });
                }
            }
            
            req.user = { id: validatedKey.userId };
            req.apiKey = validatedKey;
            next();
        } catch (error) {
            return res.status(500).json({ error: 'Authentication error' });
        }
    };
}

JWT Token Authentication

JWT Implementation

javascript
// JWT token manager
class JWTManager {
    constructor(secret, options = {}) {
        this.jwt = require('jsonwebtoken');
        this.secret = secret;
        this.options = {
            expiresIn: options.expiresIn || '1h',
            issuer: options.issuer || 'trae-ide',
            audience: options.audience || 'trae-users'
        };
    }
    
    generateToken(payload) {
        return this.jwt.sign(payload, this.secret, this.options);
    }
    
    generateRefreshToken(userId) {
        return this.jwt.sign(
            { userId, type: 'refresh' },
            this.secret,
            { expiresIn: '7d' }
        );
    }
    
    verifyToken(token) {
        try {
            return this.jwt.verify(token, this.secret);
        } catch (error) {
            throw new Error(`Invalid token: ${error.message}`);
        }
    }
    
    refreshAccessToken(refreshToken) {
        try {
            const decoded = this.jwt.verify(refreshToken, this.secret);
            
            if (decoded.type !== 'refresh') {
                throw new Error('Invalid refresh token');
            }
            
            // Generate new access token
            return this.generateToken({
                userId: decoded.userId,
                type: 'access'
            });
        } catch (error) {
            throw new Error(`Token refresh failed: ${error.message}`);
        }
    }
    
    decodeToken(token) {
        return this.jwt.decode(token);
    }
}

// JWT middleware
function jwtAuth(options = {}) {
    return (req, res, next) => {
        const authHeader = req.headers.authorization;
        
        if (!authHeader || !authHeader.startsWith('Bearer ')) {
            return res.status(401).json({ error: 'Access token required' });
        }
        
        const token = authHeader.substring(7);
        const jwtManager = new JWTManager(process.env.JWT_SECRET);
        
        try {
            const decoded = jwtManager.verifyToken(token);
            
            if (decoded.type !== 'access') {
                return res.status(401).json({ error: 'Invalid token type' });
            }
            
            req.user = { id: decoded.userId };
            req.token = decoded;
            next();
        } catch (error) {
            return res.status(401).json({ error: 'Invalid or expired token' });
        }
    };
}

Session Management

Session Configuration

javascript
// Session management
class SessionManager {
    constructor(options = {}) {
        this.redis = require('redis').createClient(options.redis);
        this.sessionTimeout = options.timeout || 3600; // 1 hour
        this.maxSessions = options.maxSessions || 5;
    }
    
    async createSession(userId, metadata = {}) {
        const sessionId = this.generateSessionId();
        const session = {
            id: sessionId,
            userId: userId,
            createdAt: new Date(),
            lastActivity: new Date(),
            ipAddress: metadata.ipAddress,
            userAgent: metadata.userAgent,
            isActive: true
        };
        
        // Store session
        await this.redis.setex(
            `session:${sessionId}`,
            this.sessionTimeout,
            JSON.stringify(session)
        );
        
        // Manage session limit
        await this.enforceSessionLimit(userId);
        
        return sessionId;
    }
    
    async getSession(sessionId) {
        const sessionData = await this.redis.get(`session:${sessionId}`);
        
        if (!sessionData) {
            return null;
        }
        
        const session = JSON.parse(sessionData);
        
        // Update last activity
        session.lastActivity = new Date();
        await this.redis.setex(
            `session:${sessionId}`,
            this.sessionTimeout,
            JSON.stringify(session)
        );
        
        return session;
    }
    
    async destroySession(sessionId) {
        await this.redis.del(`session:${sessionId}`);
    }
    
    async destroyAllUserSessions(userId) {
        const sessions = await this.getUserSessions(userId);
        
        for (const session of sessions) {
            await this.destroySession(session.id);
        }
    }
    
    async enforceSessionLimit(userId) {
        const sessions = await this.getUserSessions(userId);
        
        if (sessions.length >= this.maxSessions) {
            // Remove oldest sessions
            const sessionsToRemove = sessions
                .sort((a, b) => new Date(a.lastActivity) - new Date(b.lastActivity))
                .slice(0, sessions.length - this.maxSessions + 1);
            
            for (const session of sessionsToRemove) {
                await this.destroySession(session.id);
            }
        }
    }
    
    generateSessionId() {
        const crypto = require('crypto');
        return crypto.randomBytes(32).toString('hex');
    }
}

Session Security

javascript
// Session security measures
class SessionSecurity {
    constructor(sessionManager) {
        this.sessionManager = sessionManager;
        this.suspiciousActivityThreshold = 5;
        this.geoLocationService = new GeoLocationService();
    }
    
    async validateSession(sessionId, request) {
        const session = await this.sessionManager.getSession(sessionId);
        
        if (!session) {
            throw new Error('Session not found');
        }
        
        // Check for suspicious activity
        await this.checkSuspiciousActivity(session, request);
        
        // Validate IP address (optional)
        if (process.env.STRICT_IP_VALIDATION === 'true') {
            await this.validateIPAddress(session, request.ip);
        }
        
        // Check for concurrent sessions
        await this.checkConcurrentSessions(session.userId);
        
        return session;
    }
    
    async checkSuspiciousActivity(session, request) {
        const activities = await this.getRecentActivities(session.userId);
        
        // Check for rapid location changes
        const currentLocation = await this.geoLocationService.getLocation(request.ip);
        const lastLocation = activities.length > 0 ? activities[0].location : null;
        
        if (lastLocation && this.isRapidLocationChange(lastLocation, currentLocation)) {
            await this.flagSuspiciousActivity(session.userId, 'rapid_location_change');
        }
        
        // Check for unusual user agent
        if (session.userAgent !== request.headers['user-agent']) {
            await this.flagSuspiciousActivity(session.userId, 'user_agent_change');
        }
    }
    
    async flagSuspiciousActivity(userId, type) {
        const flags = await this.getSuspiciousFlags(userId);
        flags.push({
            type: type,
            timestamp: new Date(),
            resolved: false
        });
        
        await this.storeSuspiciousFlags(userId, flags);
        
        // If too many flags, require re-authentication
        if (flags.filter(f => !f.resolved).length >= this.suspiciousActivityThreshold) {
            await this.sessionManager.destroyAllUserSessions(userId);
            await this.notifySecurityTeam(userId, flags);
        }
    }
}

Security Best Practices

Password Security

javascript
// Password hashing and validation
class PasswordManager {
    constructor() {
        this.bcrypt = require('bcrypt');
        this.saltRounds = 12;
        this.minLength = 8;
        this.maxLength = 128;
    }
    
    async hashPassword(password) {
        this.validatePassword(password);
        return await this.bcrypt.hash(password, this.saltRounds);
    }
    
    async verifyPassword(password, hash) {
        return await this.bcrypt.compare(password, hash);
    }
    
    validatePassword(password) {
        if (password.length < this.minLength) {
            throw new Error(`Password must be at least ${this.minLength} characters`);
        }
        
        if (password.length > this.maxLength) {
            throw new Error(`Password must be no more than ${this.maxLength} characters`);
        }
        
        // Check for common patterns
        if (this.isCommonPassword(password)) {
            throw new Error('Password is too common');
        }
        
        // Strength requirements
        const strength = this.calculatePasswordStrength(password);
        if (strength < 3) {
            throw new Error('Password is too weak');
        }
    }
    
    calculatePasswordStrength(password) {
        let score = 0;
        
        // Length bonus
        if (password.length >= 12) score++;
        if (password.length >= 16) score++;
        
        // Character variety
        if (/[a-z]/.test(password)) score++;
        if (/[A-Z]/.test(password)) score++;
        if (/[0-9]/.test(password)) score++;
        if (/[^A-Za-z0-9]/.test(password)) score++;
        
        // Patterns (negative)
        if (/(..).*\1/.test(password)) score--; // Repeated patterns
        if (/^\d+$/.test(password)) score--; // Only numbers
        if (/^[a-zA-Z]+$/.test(password)) score--; // Only letters
        
        return Math.max(0, score);
    }
    
    isCommonPassword(password) {
        const commonPasswords = [
            'password', '123456', 'password123', 'admin', 'qwerty',
            'letmein', 'welcome', 'monkey', '1234567890'
        ];
        
        return commonPasswords.includes(password.toLowerCase());
    }
}

Rate Limiting

javascript
// Rate limiting for authentication endpoints
class RateLimiter {
    constructor(redis) {
        this.redis = redis;
        this.limits = {
            login: { requests: 5, window: 900 }, // 5 attempts per 15 minutes
            register: { requests: 3, window: 3600 }, // 3 attempts per hour
            passwordReset: { requests: 3, window: 3600 }, // 3 attempts per hour
            mfaVerify: { requests: 10, window: 300 } // 10 attempts per 5 minutes
        };
    }
    
    async checkLimit(identifier, action) {
        const limit = this.limits[action];
        if (!limit) return true;
        
        const key = `ratelimit:${action}:${identifier}`;
        const current = await this.redis.get(key);
        
        if (current && parseInt(current) >= limit.requests) {
            const ttl = await this.redis.ttl(key);
            throw new Error(`Rate limit exceeded. Try again in ${ttl} seconds.`);
        }
        
        // Increment counter
        const multi = this.redis.multi();
        multi.incr(key);
        multi.expire(key, limit.window);
        await multi.exec();
        
        return true;
    }
    
    async resetLimit(identifier, action) {
        const key = `ratelimit:${action}:${identifier}`;
        await this.redis.del(key);
    }
}

// Rate limiting middleware
function rateLimitMiddleware(action) {
    return async (req, res, next) => {
        const rateLimiter = new RateLimiter(req.app.locals.redis);
        const identifier = req.ip; // or req.user?.id for authenticated requests
        
        try {
            await rateLimiter.checkLimit(identifier, action);
            next();
        } catch (error) {
            res.status(429).json({ error: error.message });
        }
    };
}

CSRF Protection

javascript
// CSRF token management
class CSRFProtection {
    constructor() {
        this.crypto = require('crypto');
    }
    
    generateToken(sessionId) {
        const token = this.crypto.randomBytes(32).toString('hex');
        const timestamp = Date.now();
        const signature = this.crypto
            .createHmac('sha256', process.env.CSRF_SECRET)
            .update(`${token}:${sessionId}:${timestamp}`)
            .digest('hex');
        
        return `${token}:${timestamp}:${signature}`;
    }
    
    validateToken(token, sessionId) {
        if (!token) return false;
        
        const [tokenValue, timestamp, signature] = token.split(':');
        
        if (!tokenValue || !timestamp || !signature) {
            return false;
        }
        
        // Check if token is expired (1 hour)
        if (Date.now() - parseInt(timestamp) > 3600000) {
            return false;
        }
        
        // Verify signature
        const expectedSignature = this.crypto
            .createHmac('sha256', process.env.CSRF_SECRET)
            .update(`${tokenValue}:${sessionId}:${timestamp}`)
            .digest('hex');
        
        return signature === expectedSignature;
    }
}

// CSRF middleware
function csrfProtection(req, res, next) {
    if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) {
        return next();
    }
    
    const csrf = new CSRFProtection();
    const token = req.headers['x-csrf-token'] || req.body._csrf;
    const sessionId = req.session?.id;
    
    if (!csrf.validateToken(token, sessionId)) {
        return res.status(403).json({ error: 'Invalid CSRF token' });
    }
    
    next();
}

Troubleshooting

Common Issues

OAuth Callback Errors

javascript
// OAuth error handling
class OAuthErrorHandler {
    static handleCallback(error, req, res) {
        switch (error.code) {
            case 'access_denied':
                return res.redirect('/login?error=access_denied');
            
            case 'invalid_request':
                console.error('OAuth invalid request:', error);
                return res.redirect('/login?error=configuration_error');
            
            case 'server_error':
                console.error('OAuth server error:', error);
                return res.redirect('/login?error=server_error');
            
            default:
                console.error('Unknown OAuth error:', error);
                return res.redirect('/login?error=unknown_error');
        }
    }
    
    static validateState(receivedState, sessionState) {
        if (!receivedState || !sessionState) {
            throw new Error('Missing state parameter');
        }
        
        if (receivedState !== sessionState) {
            throw new Error('Invalid state parameter - possible CSRF attack');
        }
    }
}

Session Issues

javascript
// Session debugging
class SessionDebugger {
    static async diagnoseSession(sessionId) {
        const sessionManager = new SessionManager();
        const session = await sessionManager.getSession(sessionId);
        
        if (!session) {
            return {
                status: 'not_found',
                message: 'Session does not exist or has expired'
            };
        }
        
        const now = new Date();
        const lastActivity = new Date(session.lastActivity);
        const timeSinceActivity = now - lastActivity;
        
        return {
            status: 'found',
            session: {
                id: session.id,
                userId: session.userId,
                createdAt: session.createdAt,
                lastActivity: session.lastActivity,
                timeSinceActivity: `${Math.floor(timeSinceActivity / 1000)} seconds`,
                isActive: session.isActive
            }
        };
    }
    
    static async listUserSessions(userId) {
        const sessionManager = new SessionManager();
        return await sessionManager.getUserSessions(userId);
    }
}

MFA Issues

javascript
// MFA troubleshooting
class MFATroubleshooter {
    static async diagnoseMFA(userId) {
        const user = await getUserById(userId);
        
        if (!user.mfaEnabled) {
            return {
                status: 'disabled',
                message: 'MFA is not enabled for this user'
            };
        }
        
        const totp = new TOTPProvider();
        const currentTime = Math.floor(Date.now() / 1000);
        const timeStep = Math.floor(currentTime / 30);
        
        return {
            status: 'enabled',
            mfaInfo: {
                secretLength: user.mfaSecret.length,
                currentTimeStep: timeStep,
                backupCodesRemaining: user.backupCodes.length,
                lastUsed: user.mfaLastUsed
            },
            troubleshooting: {
                timeSync: 'Ensure device time is synchronized',
                appRecommendation: 'Use Google Authenticator or Authy',
                backupCodes: 'Use backup codes if TOTP fails'
            }
        };
    }
    
    static generateTestToken(secret) {
        const totp = new TOTPProvider();
        return totp.speakeasy.totp({
            secret: secret,
            encoding: 'base32'
        });
    }
}

Logging and Monitoring

javascript
// Authentication logging
class AuthLogger {
    constructor(logger) {
        this.logger = logger;
    }
    
    logLoginAttempt(userId, success, metadata = {}) {
        this.logger.info('Login attempt', {
            userId,
            success,
            ipAddress: metadata.ipAddress,
            userAgent: metadata.userAgent,
            provider: metadata.provider,
            timestamp: new Date().toISOString()
        });
    }
    
    logMFAAttempt(userId, success, method) {
        this.logger.info('MFA attempt', {
            userId,
            success,
            method,
            timestamp: new Date().toISOString()
        });
    }
    
    logSuspiciousActivity(userId, activity, metadata = {}) {
        this.logger.warn('Suspicious activity detected', {
            userId,
            activity,
            metadata,
            timestamp: new Date().toISOString()
        });
    }
    
    logPasswordChange(userId, success) {
        this.logger.info('Password change', {
            userId,
            success,
            timestamp: new Date().toISOString()
        });
    }
    
    logAPIKeyUsage(keyId, userId, endpoint) {
        this.logger.info('API key usage', {
            keyId,
            userId,
            endpoint,
            timestamp: new Date().toISOString()
        });
    }
}

This authentication guide provides comprehensive coverage of authentication methods, security best practices, and troubleshooting techniques for Trae IDE. Regular security audits and updates ensure the authentication system remains secure against evolving threats.

Your Ultimate AI-Powered IDE Learning Guide