Fix production environment variables
- Remove old Confluence variables - Add NEXT_PUBLIC_API_URL for API access 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
110
lambda/auth/index.js
Normal file
110
lambda/auth/index.js
Normal file
@@ -0,0 +1,110 @@
|
||||
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' });
|
||||
};
|
||||
Reference in New Issue
Block a user