Reputation: 1610
I started learning NodeJs
and pushed by my knowledge of js I start writing some code for create the user registration logic.
Essentially I have configured ExpressJS
in the following way:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const session = require('express-session');
const csrf = require('csurf');
const cookieParser = require('cookie-parser');
app.use(session({
secret: 'foofofoo',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(csrf());
app.use(function (req, res, next) {
var csrfToken = req.csrfToken();
res.cookie('XSRF-TOKEN', csrfToken);
res.locals.csrfToken = csrfToken;
next();
});
then I created a basic .ejs
view for the user registration:
<meta name="csrf-token" content="<%= csrfToken %>">
<p>
<label class="w3-text-blue"><b>User Name</b></label>
<input class="w3-input w3-border" id="uname" name="uname" type="text"></p>
<p>
<label class="w3-text-blue"><b>Password</b></label>
<input class="w3-input w3-border" id="upass" name="pass" type="text"></p>
<p>
<button class="w3-btn w3-blue" id="regForm">Register</button></p>
the csrfToken
is taken by the middleware
above.
When the user press the button regForm
this code is called:
$("#regForm").click(function () {
let uname = $("#uname").val();
let upass = $("#upass").val();
let token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
let regData =
{
'name': uname,
'pass': upass
};
$.ajax({
type: 'POST',
url: '/registerUser',
headers: {"X-CSRF-Token": token },
data: regData,
success: function (data) {
$("#mainDiv").html(data);
}
});
});
and looking at the ajax
request the token is passed correctly:
but inside the console I get:
ForbiddenError: invalid csrf token
this is the route method:
app.post('/registerUser', function(req, res, next){
//todo
});
Upvotes: 4
Views: 1376
Reputation: 2727
First of all kudos to you, as you have started working on nodejs and trying these stuff by yourself.
There is no need to change the structure or the code itself as it is written correctly. There is only one mistake which is causing the issue and it is in your csrf initialization. Kindly add the cookie parameter in your csrf initialization as shown below:
app.use(csrf({ cookie: true }));
Also, always use a session store in your application. Below is an example to use the express session as your session store:
var session = require('express-session');
var MemoryStore = require('session-memory-store')(session);
app.use(session({
store : new MemoryStore({ expires : 86400, checkperiod : 1800}),
secret: 'foofofoo',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
Upvotes: 2
Reputation: 16052
From the csurf docs:
Inside the view, set the csrfToken value as the value of a hidden input field named _csrf
First, change this:
<meta name="csrf-token" content="<%= csrfToken %>">
to this:
<input type="hidden" name="_csrf" value="<%= csrfToken %>" id="csrf">
Then on your jQuery page change this:
let token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
{
'name': uname,
'pass': upass
};
to this:
let token = $('#csrf').val();
{
'name': uname,
'pass': upass,
'_csrf':token
};
If you are still having issues let me know what happens when you try this.
PS: this question was a pretty good reference for your problem.
Upvotes: 1