@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
JavaScript
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 };