// VULNERABLE: Multiple authentication bypass vulnerabilities
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// PROBLEM 1: Weak JWT validation
function authenticateToken(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (token) {
// DANGEROUS: No signature verification
const decoded = jwt.decode(token);
if (decoded) {
req.user = decoded;
return next();
}
}
res.status(401).json({ error: 'Unauthorized' });
}
// PROBLEM 2: Inconsistent method protection
app.get('/api/users/:id', authenticateToken, (req, res) => {
res.json(getUserById(req.params.id));
});
app.post('/api/users/:id', authenticateToken, (req, res) => {
updateUser(req.params.id, req.body);
res.json({ success: true });
});
// VULNERABLE: Missing authentication on PUT
app.put('/api/users/:id', (req, res) => {
updateUser(req.params.id, req.body);
res.json({ success: true });
});
// PROBLEM 3: Parameter-based bypass
app.use('/api/admin', (req, res, next) => {
if (req.query.admin_key === 'secret123') {
next();
} else {
res.status(401).json({ error: 'Unauthorized' });
}
});
// PROBLEM 4: Weak session handling
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
if (validateCredentials(username, password)) {
const token = jwt.sign({ username }, 'weak-secret');
res.json({ token });
} else {
res.status(401).json({ error: 'Invalid credentials' });
}
});
// PROBLEM 5: OAuth without state validation
app.get('/auth/callback', async (req, res) => {
const { code } = req.query;
const tokenResponse = await exchangeCodeForToken(code);
const userInfo = await getUserInfo(tokenResponse.access_token);
// Auto-create user without verification
const user = await User.findOrCreate({ email: userInfo.email });
const token = jwt.sign({ userId: user.id }, 'weak-secret');
res.json({ token });
});
// SECURE: Comprehensive authentication security implementation
const express = require('express');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const redis = require('redis');
const app = express();
const redisClient = redis.createClient(process.env.REDIS_URL);
const isProduction = process.env.NODE_ENV === 'production';
// Security middleware
app.use(helmet());
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: false }));
// Rate limiting for authentication endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts per window
message: { error: 'Too many authentication attempts' },
standardHeaders: true,
keyGenerator: (req) => `${req.ip}:${req.body.username || 'anonymous'}`
});
// Secure JWT configuration
const JWT_CONFIG = {
algorithm: 'HS256',
expiresIn: '15m',
issuer: 'secure-api',
audience: 'api-users'
};
class SecureAuthManager {
static async generateToken(payload) {
const jti = crypto.randomUUID();
const tokenPayload = {
...payload,
jti,
iat: Math.floor(Date.now() / 1000),
iss: JWT_CONFIG.issuer,
aud: JWT_CONFIG.audience
};
return jwt.sign(tokenPayload, process.env.JWT_SECRET, JWT_CONFIG);
}
static async verifyToken(token) {
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
algorithms: [JWT_CONFIG.algorithm],
issuer: JWT_CONFIG.issuer,
audience: JWT_CONFIG.audience
});
// Check token blacklist
const isBlacklisted = await redisClient.get(`blacklist:${decoded.jti}`);
if (isBlacklisted) {
throw new Error('Token revoked');
}
// Verify user is still active
const user = await User.findById(decoded.userId);
if (!user || !user.isActive) {
throw new Error('User inactive');
}
return decoded;
} catch (error) {
throw new Error(`Token validation failed: ${error.message}`);
}
}
static async revokeToken(token) {
try {
const decoded = jwt.decode(token);
if (decoded?.jti && decoded?.exp) {
const ttl = decoded.exp - Math.floor(Date.now() / 1000);
if (ttl > 0) {
await redisClient.setex(`blacklist:${decoded.jti}`, ttl, 'revoked');
}
}
} catch (error) {
console.error('Token revocation error:', error);
}
}
}
// Secure authentication middleware
function authenticateToken(req, res, next) {
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({
error: 'Access token required',
code: 'TOKEN_MISSING'
});
}
SecureAuthManager.verifyToken(token)
.then(decoded => {
req.user = decoded;
req.tokenJti = decoded.jti;
next();
})
.catch(error => {
console.warn('Authentication failed:', {
error: error.message,
ip: req.ip,
userAgent: req.get('User-Agent')
});
res.status(401).json({
error: 'Invalid token',
code: 'TOKEN_INVALID'
});
});
}
// Secure admin authentication
class AdminAuth {
static async validateApiKey(req, res, next) {
const apiKey = req.headers['x-api-key'];
if (!apiKey || !this.isValidFormat(apiKey)) {
return res.status(401).json({
error: 'Valid API key required',
code: 'API_KEY_INVALID'
});
}
try {
const hashedKey = crypto.createHash('sha256').update(apiKey).digest('hex');
const keyInfo = await ApiKey.findOne({
hashedKey,
isActive: true,
role: 'admin',
expiresAt: { $gt: new Date() }
}).populate('user');
if (!keyInfo) {
throw new Error('API key not found');
}
req.apiKey = keyInfo;
req.user = keyInfo.user;
next();
} catch (error) {
res.status(401).json({
error: 'API key validation failed',
code: 'API_KEY_VALIDATION_FAILED'
});
}
}
static isValidFormat(key) {
return /^[a-f0-9]{64}$/i.test(key);
}
}
// Apply authentication to ALL HTTP methods
function protectAllMethods(authMiddleware) {
return (req, res, next) => {
if (req.method === 'OPTIONS') {
return next();
}
authMiddleware(req, res, next);
};
}
// Secure OAuth state management
class OAuthManager {
static generateState() {
return crypto.randomBytes(32).toString('hex');
}
static async storeState(state, data) {
await redisClient.setex(`oauth_state:${state}`, 600, JSON.stringify(data));
}
static async validateState(state) {
const key = `oauth_state:${state}`;
const data = await redisClient.get(key);
if (!data) {
throw new Error('Invalid OAuth state');
}
await redisClient.del(key);
return JSON.parse(data);
}
}
// Apply security to all user routes
app.use('/api/users/*', protectAllMethods(authenticateToken));
app.use('/api/admin/*', protectAllMethods(AdminAuth.validateApiKey.bind(AdminAuth)));
// Secure login endpoint
app.post('/api/login', authLimiter, async (req, res) => {
const { username, password } = req.body;
try {
const user = await authenticateUser(username, password);
if (!user) {
return res.status(401).json({
error: 'Invalid credentials',
code: 'INVALID_CREDENTIALS'
});
}
const token = await SecureAuthManager.generateToken({
userId: user.id,
username: user.username,
role: user.role
});
res.json({
token,
user: {
id: user.id,
username: user.username,
role: user.role
}
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({
error: 'Login failed',
code: 'LOGIN_ERROR'
});
}
});
// Secure logout
app.post('/api/logout', authenticateToken, async (req, res) => {
try {
const token = req.headers.authorization?.split(' ')[1];
if (token) {
await SecureAuthManager.revokeToken(token);
}
res.json({ success: true });
} catch (error) {
console.error('Logout error:', error);
res.status(500).json({ error: 'Logout failed' });
}
});
// Protected routes with consistent authentication
app.get('/api/users/:id', (req, res) => {
const user = getUserById(req.params.id);
res.json(user);
});
app.post('/api/users/:id', (req, res) => {
updateUser(req.params.id, req.body);
res.json({ success: true });
});
app.put('/api/users/:id', (req, res) => {
updateUser(req.params.id, req.body);
res.json({ success: true });
});
app.patch('/api/users/:id', (req, res) => {
updateUser(req.params.id, req.body);
res.json({ success: true });
});
app.delete('/api/users/:id', (req, res) => {
deleteUser(req.params.id);
res.json({ success: true });
});
// Secure OAuth flow
app.get('/auth/google', async (req, res) => {
try {
const state = OAuthManager.generateState();
const nonce = crypto.randomBytes(16).toString('hex');
await OAuthManager.storeState(state, {
timestamp: Date.now(),
ip: req.ip,
nonce
});
const authUrl = `https://accounts.google.com/o/oauth2/auth?` +
`client_id=${process.env.GOOGLE_CLIENT_ID}&` +
`redirect_uri=${encodeURIComponent(process.env.OAUTH_REDIRECT_URI)}&` +
`scope=openid email profile&` +
`response_type=code&` +
`state=${state}&` +
`nonce=${nonce}`;
res.redirect(authUrl);
} catch (error) {
res.status(500).json({ error: 'OAuth initiation failed' });
}
});
app.get('/auth/callback', async (req, res) => {
const { code, state } = req.query;
try {
if (!code || !state) {
throw new Error('Missing code or state');
}
const stateData = await OAuthManager.validateState(state);
// Exchange code for tokens and validate
const tokenData = await exchangeCodeForToken(code);
const userInfo = await validateAndGetUserInfo(tokenData);
// Secure user creation/lookup
let user = await User.findOne({
email: userInfo.email,
provider: 'google'
});
if (!user && userInfo.verified_email) {
user = await User.create({
email: userInfo.email,
name: userInfo.name,
provider: 'google',
isEmailVerified: true
});
}
if (!user) {
throw new Error('User creation failed');
}
const token = await SecureAuthManager.generateToken({
userId: user.id,
username: user.username,
role: user.role
});
res.redirect(`/dashboard?token=${token}`);
} catch (error) {
console.error('OAuth callback error:', error);
res.redirect('/login?error=oauth_failed');
}
});