API Authentication Headers

API Authentication Headers

JWT-Based API Authentication

class APIAuthenticationHeaders {
    constructor() {
        this.jwtSecret = process.env.JWT_SECRET;
        this.jwtExpiry = '1h';
        this.refreshExpiry = '7d';
    }
    
    // Generate tokens with security headers
    generateTokens(user, res) {
        const accessToken = jwt.sign(
            { 
                userId: user.id, 
                type: 'access',
                fingerprint: this.generateTokenFingerprint()
            },
            this.jwtSecret,
            { 
                expiresIn: this.jwtExpiry,
                issuer: 'api.example.com',
                audience: 'app.example.com'
            }
        );
        
        const refreshToken = jwt.sign(
            { 
                userId: user.id, 
                type: 'refresh',
                tokenFamily: uuid.v4()
            },
            this.jwtSecret,
            { 
                expiresIn: this.refreshExpiry,
                issuer: 'api.example.com'
            }
        );
        
        // Set tokens in secure cookies
        res.cookie('access_token', accessToken, {
            secure: true,
            httpOnly: true,
            sameSite: 'strict',
            maxAge: 3600000 // 1 hour
        });
        
        res.cookie('refresh_token', refreshToken, {
            secure: true,
            httpOnly: true,
            sameSite: 'strict',
            maxAge: 604800000, // 7 days
            path: '/api/auth/refresh' // Limit refresh token usage
        });
        
        // Also return in response for mobile apps
        return { accessToken, refreshToken };
    }
    
    // API authentication middleware
    authenticateAPI() {
        return async (req, res, next) => {
            // Check Authorization header
            const authHeader = req.headers.authorization;
            const cookieToken = req.cookies.access_token;
            
            const token = authHeader?.split(' ')[1] || cookieToken;
            
            if (!token) {
                res.setHeader('WWW-Authenticate', 'Bearer realm="API"');
                return res.status(401).json({ error: 'Authentication required' });
            }
            
            try {
                const decoded = jwt.verify(token, this.jwtSecret, {
                    issuer: 'api.example.com',
                    audience: 'app.example.com'
                });
                
                // Additional validation
                if (decoded.type !== 'access') {
                    throw new Error('Invalid token type');
                }
                
                req.user = { id: decoded.userId };
                
                // Set security headers for authenticated requests
                res.setHeader('X-Content-Type-Options', 'nosniff');
                res.setHeader('X-Frame-Options', 'DENY');
                res.setHeader('Cache-Control', 'private, no-cache');
                
                next();
            } catch (error) {
                res.setHeader('WWW-Authenticate', 
                    `Bearer realm="API", error="invalid_token", error_description="${error.message}"`
                );
                return res.status(401).json({ error: 'Invalid token' });
            }
        };
    }
}