UNPKG

@dax-crafta/auth

Version:

A powerful, flexible, and secure authentication plugin for the Crafta framework. Supports JWT, social login, 2FA, RBAC, audit logging, and enterprise-grade security features.

267 lines (239 loc) 7.26 kB
const passport = require('passport'); const GoogleStrategy = require('passport-google-oauth20').Strategy; const FacebookStrategy = require('passport-facebook').Strategy; const GitHubStrategy = require('passport-github2').Strategy; const AuthService = require('./services/auth.service'); const RoleService = require('./services/role.service'); const AuditService = require('./services/audit.service'); const MFAService = require('./utils/mfa'); const PasswordPolicy = require('./utils/password-policy'); const createAuthMiddleware = require('./middlewares/auth.middleware'); const defaultConfig = { strategy: 'jwt', fields: ['email', 'password'], routes: { register: '/register', login: '/login', verify: '/verify', forgotPassword: '/forgot-password', resetPassword: '/reset-password', refreshToken: '/refresh-token', profile: '/profile', twoFactor: '/2fa', roles: '/roles', permissions: '/permissions' }, mongoUrl: process.env.MONGODB_URI || 'mongodb://localhost:27017/forge-auth', maxLoginAttempts: 5, emailVerification: true, loginAlerts: true, passwordPolicy: { minLength: 8, requireUppercase: true, requireNumbers: true, requireSpecialChars: true, expiryDays: 90 }, smtp: null, social: { google: null, facebook: null, github: null } }; function auth(config = {}) { const finalConfig = { ...defaultConfig, ...config }; if (!finalConfig.env?.JWT_SECRET) { throw new Error('JWT_SECRET is required in environment configuration'); } if (finalConfig.emailVerification && !finalConfig.smtp) { throw new Error('SMTP configuration is required for email verification'); } // Initialize services const authService = new AuthService(finalConfig); const roleService = new RoleService(); const auditService = new AuditService(); const mfaService = new MFAService(); const passwordPolicy = new PasswordPolicy(finalConfig.passwordPolicy); const { rateLimiter, verifyToken, checkRole } = createAuthMiddleware(finalConfig); // Configure social login strategies if (finalConfig.social.google) { passport.use(new GoogleStrategy(finalConfig.social.google, async (accessToken, refreshToken, profile, done) => { try { const user = await authService.handleSocialLogin('google', profile); done(null, user); } catch (error) { done(error); } } )); } return function(app) { app.use(passport.initialize()); app.use(rateLimiter); // Attach services to app app.authService = authService; app.roleService = roleService; app.auditService = auditService; app.mfaService = mfaService; app.passwordPolicy = passwordPolicy; // Register route with password policy app.post(finalConfig.routes.register, async (req, res) => { try { const { isValid, errors } = passwordPolicy.validate(req.body.password, { email: req.body.email, name: req.body.name }); if (!isValid) { return res.status(400).json({ success: false, errors }); } const user = await authService.register(req.body); await auditService.logActivity({ userId: user._id, action: 'register', ipAddress: req.ip, userAgent: req.headers['user-agent'], status: 'success' }); res.status(201).json({ success: true, message: 'Registration successful' }); } catch (error) { res.status(400).json({ success: false, error: error.message }); } }); // Login route with audit logging and MFA support app.post(finalConfig.routes.login, async (req, res) => { try { const deviceInfo = { browser: req.headers['user-agent'], ip: req.ip }; const result = await authService.login( req.body.email, req.body.password, deviceInfo ); await auditService.logActivity({ userId: result.user?._id, action: 'login', ipAddress: req.ip, userAgent: req.headers['user-agent'], status: 'success' }); res.json({ success: true, ...result }); } catch (error) { await auditService.logActivity({ action: 'login', ipAddress: req.ip, userAgent: req.headers['user-agent'], status: 'failure', details: { error: error.message } }); res.status(401).json({ success: false, error: error.message }); } }); // 2FA verification app.post(finalConfig.routes.twoFactor, async (req, res) => { try { const result = await authService.verify2FA( req.body.userId, req.body.code ); await auditService.logActivity({ userId: result.user._id, action: '2fa_verify', status: 'success' }); res.json({ success: true, ...result }); } catch (error) { res.status(401).json({ success: false, error: error.message }); } }); // Role management routes app.post('/roles', verifyToken, checkRole(['admin']), async (req, res) => { try { const role = await roleService.createRole(req.body); res.status(201).json({ success: true, role }); } catch (error) { res.status(400).json({ success: false, error: error.message }); } }); // Update profile with audit logging app.put(finalConfig.routes.profile, verifyToken, async (req, res) => { try { const user = await authService.updateProfile(req.user.id, req.body); await auditService.logActivity({ userId: user._id, action: 'profile_update', status: 'success' }); res.json({ success: true, user }); } catch (error) { res.status(400).json({ success: false, error: error.message }); } }); // Social login routes if (finalConfig.social.google) { app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }) ); app.get('/auth/google/callback', passport.authenticate('google', { session: false }), async (req, res) => { const { accessToken, refreshToken } = authService.generateTokens(req.user); await auditService.logActivity({ userId: req.user._id, action: 'social_login', status: 'success', details: { provider: 'google' } }); res.json({ success: true, accessToken, refreshToken, user: req.user }); } ); } // Error handling middleware app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ success: false, error: 'Internal Server Error' }); }); }; } module.exports = { auth };