Node.js is widely used for building server-side applications, and security is of utmost importance to ensure that your application is robust against common vulnerabilities such as SQL injection, cross-site scripting (XSS), and command injection. Here are some ways you can secure your Node.js API:
- Input Validation: Validate all inputs received from the user to prevent malicious input from being executed. Use libraries like Joi or express-validator to validate incoming requests.
const Joi = require('joi');
app.post('/user', (req, res) => {
const { error } = Joi.validate(req.body, {
username: Joi.string().required(),
password: Joi.string().min(6).required()
});
if (error) {
return res.status(400).send(error.details[0].message);
}
// Process the request
});
- Use Middleware for Authentication and Authorization: Use middleware like express-jwt for authentication and passport.js for authorization. These middleware can validate tokens and check user roles.
const jwt = require('express-jwt');
const passport = require('passport');
app.use(jwt({ secret: 'secret' }));
app.use(passport.initialize());
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: 'secret'
}, (payload, done) => {
User.findById(payload.sub, (err, user) => {
if (err) return done(err, false);
if (user) return done(null, user);
return done(null, false);
});
}));
app.get('/protected', passport.authenticate('jwt', { session: false }), (req, res) => {
// Access the authenticated user using req.user
});
- Prevent Cross-Site Scripting (XSS): Use libraries like ejs or handlebars to escape any user input that may be rendered in HTML.
const ejs = require('ejs');
app.get('/profile', (req, res) => {
const username = ejs.escape(req.user.username);
res.render('profile', { username });
});
- Prevent SQL Injection: Use parameterized queries or ORM libraries like Sequelize or Mongoose to prevent SQL injection.
const User = require('./models/User');
app.get('/user/:id', (req, res) => {
User.findByPk(req.params.id)
.then(user => {
res.json(user);
})
.catch(err => {
res.status(500).send(err);
});
});
- Prevent Command Injection: Use libraries like shelljs or child_process to safely execute commands from user input.
const shell = require('shelljs');
app.get('/run/command', (req, res) => {
if (!/^[a-zA-Z0-9]+$/.test(req.query.command)) {
return res.status(400).send('Invalid command');
}
const result = shell.exec(`${__dirname}/commands/${req.query.command}.sh`);
if (result.code !== 0) {
return res.status(500).send('Error executing command');
}
res.json({ output: result.stdout });
});
Remember, security is a process that involves identifying vulnerabilities, testing for them, and fixing them. Keep your dependencies up to date, use secure libraries and frameworks, and regularly test your application.