I'm having issues with CSRF tokens. When I submit a form, a new XSRF-TOKEN
is being generated but I think I'm generating two different tokens, I'm kinda confused. There's also a token called _csrf
, so I see two different cookies in developer tools (XSRF-TOKEN and _csrf), _csrf
doesn't change after a post.
What I want to do is to generate a new token for each post request and check whether it's valid or not. One thing I know that I should do it for security, but I stuck.
It has been a long day and I'm new into Express and NodeJS.
Here's my current setup.
var express = require('express')
, passport = require('passport')
, flash = require('connect-flash')
, utils = require('./utils')
, csrf = require('csurf')
// setup route middlewares
,csrfProtection = csrf({ cookie: true })
, methodOverride = require('method-override')
, bodyParser = require("body-parser")
, parseForm = bodyParser.urlencoded({ extended: false })
, cookieParser = require('cookie-parser')
, cookieSession = require('cookie-session')
, LocalStrategy = require('passport-local').Strategy
, RememberMeStrategy = require('../..').Strategy;
var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs-locals'));
app.use(express.logger());
app.use(express.static(__dirname + '/../../public'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(flash());
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(passport.authenticate('remember-me'));
app.use(app.router);
app.use(csrf());
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals.csrftoken = req.csrfToken();
next();
});
Routes
app.get('/form', csrfProtection, function(req, res) {
// pass the csrfToken to the view
res.render('send', { csrfToken: req.csrfToken()});
});
app.post('/process', parseForm, csrfProtection, function(req, res) {
res.send('data is being processed');
});
send.ejs (/form GET)
<form action="/process" method="POST">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
Favorite color: <input type="text" name="favoriteColor">
<button type="submit">Submit</button>
</form>
CSRF tokens are only validated when the acting end user has a valid session Id. This meaning that in the instance of a public community or Force.com site, all users are Guest users. As of Winter 15, for security purposes, Guest users no longer had generated Session Ids.
CSRF Token The tokens are present in all forms as hidden fields. So, when the client proceeds to submit the form, it contains a validation voucher that confirms the user intended this action. To implement CSRF tokens in Node. js, we can use the csurf module for creating and validating tokens.
Both frameworks have CSRF protection built in but don't understand each other without manual adjustments. Express is built on top of the connect framework which has a native csrf middleware. It generates a random string token that is unique for each user. The token is saved in the user's session on the server.
Based on the amount of code you shared, I will mention a few things that don't look quite right to me:
1 . You may need to swap the lines below so that csrf runs before the routes.
app.use(csrf());
app.use(app.router);
2 . The csrftoken setup needs to also be placed before the routes.
app.use(csrf());
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals.csrftoken = req.csrfToken();
next();
});
app.use(app.router);
3 . You'll need to use locals.csrftoken
in your form:
<form action="/process" method="POST">
<input type="hidden" name="_csrf" value="<%= csrftoken %>">
Favorite color: <input type="text" name="favoriteColor">
<button type="submit">Submit</button>
</form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With