const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); const JWT_SECRET = process.env.JWT_SECRET; const ADMIN_USERNAME = process.env.ADMIN_USERNAME; const ADMIN_PASSWORD_HASH = process.env.ADMIN_PASSWORD_HASH; // CORS headers const headers = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': process.env.CORS_ORIGIN || '*', 'Access-Control-Allow-Headers': 'Content-Type,Authorization', 'Access-Control-Allow-Methods': 'POST,OPTIONS' }; // Helper function to create response const createResponse = (statusCode, body) => ({ statusCode, headers, body: JSON.stringify(body) }); // Login handler const login = async (event) => { try { const { username, password } = JSON.parse(event.body); // Validate credentials if (username !== ADMIN_USERNAME) { return createResponse(401, { error: 'Invalid credentials' }); } // Compare password with hash const isValid = await bcrypt.compare(password, ADMIN_PASSWORD_HASH); if (!isValid) { return createResponse(401, { error: 'Invalid credentials' }); } // Generate JWT token const token = jwt.sign( { username, role: 'admin' }, JWT_SECRET, { expiresIn: '24h' } ); return createResponse(200, { token, expiresIn: 86400 // 24 hours in seconds }); } catch (error) { console.error('Login error:', error); return createResponse(500, { error: 'Authentication failed' }); } }; // Verify token (for Lambda authorizer) const verifyToken = async (event) => { try { const token = event.authorizationToken?.replace('Bearer ', ''); if (!token) { throw new Error('Unauthorized'); } const decoded = jwt.verify(token, JWT_SECRET); return { principalId: decoded.username, policyDocument: { Version: '2012-10-17', Statement: [ { Action: 'execute-api:Invoke', Effect: 'Allow', Resource: event.methodArn } ] }, context: { username: decoded.username, role: decoded.role } }; } catch (error) { console.error('Token verification error:', error); throw new Error('Unauthorized'); } }; // Main handler exports.handler = async (event) => { const { httpMethod, resource } = event; // Handle CORS preflight if (httpMethod === 'OPTIONS') { return createResponse(200, {}); } // Handle login if (resource === '/auth/login' && httpMethod === 'POST') { return login(event); } // Handle token verification (for Lambda authorizer) if (event.type === 'TOKEN') { return verifyToken(event); } return createResponse(404, { error: 'Not found' }); };