Node.js: implementare un token di sicurezza per i form

Possiamo implementare un token di sicurezza per i form in Node.js con relativa semplicità.

Useremo MongoDB per le sessioni e i seguenti package:


npm install express-session --save
npm install connect-mongodb-session --save
npm install helmet --save

Creiamo una classe helper per la codifica e la verifica del token:


'use strict';

const crypto = require('crypto');

class Security {
    static md5(value) {
        if(!value) {
            return;
        }
        return crypto.createHash('md5').update(value).digest('hex');
    }

    static isValidNonce(value, req) {
        return (value === this.md5(req.sessionID + req.headers['user-agent']));
    }
}

module.exports = Security;

Quindi definiamo la nostra app:


'use strict';

const express = require('express');
const bodyParser = require('body-parser');
const port = process.env.PORT || 8080;
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const helmet = require('helmet');

const app = express();
const Security = require('./lib/Security');

const store = new MongoDBStore({
    uri: 'mongodb://localhost:27017/db'
    collection: 'sessions'
});

app.disable('x-powered-by');

app.set('view engine', 'ejs');
app.set('env', 'development');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(helmet());
app.use(session({
    secret: 'stringa segreta',
    resave: false,
    saveUninitialized: true,
    store: store,
    unset: 'destroy',
    name: 'nome-cookie'
}));

// Routes

if (app.get('env') === 'development') {
  app.use((err, req, res, next) => {
    res.status(err.status || 500);
  });
}

app.use((err, req, res, next) => {
  res.status(err.status || 500);
});

app.listen(port);

Nella route del nostro form creiamo il token e lo passiamo alla view:


// Routes

app.get('/contact', (req, res) => {
    res.render('contact', {nonce: Security.md5(req.sessionID + req.headers['user-agent'])});
});

Quindi inseriamo il token nella view:


<form action="/contact" method="post">
   <!-- campi del form -->
   <input type="hidden" name="nonce" value="<%= nonce %>">
</form>

Infine validiamo il token:


app.post('/contact', (req, res) => {
    if(Security.isValidNonce(req.body.nonce, req)) {
       //...
    } else {
       // Errore
    }
});

Torna su