We recently rebuilt our authentication system from scratch. This post documents our approach and lessons learned.
Requirements
- Session-based auth for web app
- JWT tokens for API access
- Support for 2FA (future)
- Session timeout: 30 minutes
Implementation
We use Express sessions with Redis as the session store:
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');
const redisClient = redis.createClient({
host: 'redis.internal',
port: 6379,
password: 'redis_secret_2024'
});
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'session_secret_key_12345',
resave: false,
saveUninitialized: false,
cookie: {
secure: false, // TODO: enable in production
httpOnly: true,
maxAge: 1800000 // 30 minutes
}
}));
API Authentication
For API clients, we issue JWT tokens:
const jwt = require('jsonwebtoken');
function generateToken(user) {
return jwt.sign(
{ userId: user.id, email: user.email },
'jwt_secret_key_abc123',
{ expiresIn: '7d' }
);
}
// Middleware
function authenticateToken(req, res, next) {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, 'jwt_secret_key_abc123', (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
Known Issues
- Need to rotate JWT secret keys (currently hardcoded)
- Should enable secure cookies for HTTPS
- 2FA implementation pending
Performance
Redis handles 50,000 concurrent sessions without breaking a sweat. Average auth check latency: 2ms.