How to retrieve form data sent over HTTPS in node? - javascript

I'm a bit of a back-end security n00b, so please be gentle if I'm missing something obvious:
When I get values over HTTP in node, the form data is in the request object req.body.{name of input element}
Over HTTPS, req.body doesn't seem to exist. I've tried logging out the req object but I can't see it anywhere in there. What am I doing wrong?
function checkUser(req, res) {
console.dir(req);
//if passwords don't match
if (req.body.password !== req.body.confirm_password) {
return false;
}
return true;
}
app.post('/register', function(req, res) {
if (checkUser(req, res)) {
createUser(req, res)
res.redirect('/browse?p=0');
}
res.render('register', {
error: 'Passwords did not match'
})
});
As soon as it goes to the checkUser method it crashes saying that req.body is not defined. So where is the data kept?
Any help will be appreciated...
Thanks
James

req.body only exists if you link in the appropriate middleware to parse the request body. I recommend the following:
app.use(express.urlencoded());
app.use(express.json());
You often see express.bodyParser() being used, but I recommend avoiding this because it also includes express.multipart(), which has been deprecated, and will disappear when Express updates its dependency on Connect. If you need to parse multipart form data, look into Busboy or Formidable.
I don't think your issue has anything to do with HTTPS: parsing the request body is the same process in HTTP and HTTPS.

OK, I got it...
I'd called things in the right order, but I'd included all the passportjs stuff (and the corresponding middlewares) in a module file. Because of probably scope or race conditions it didn't register the middleware before the route and controller were executed.
in web.js:
app = express();
app.settings.env = 'development';
app.engine('dust', dustjs.dust({
cache: false
}));
app.set('view engine', 'dust');
app.set('views', __dirname + '\\views');
//Middleware
app.use(express.methodOverride());
app.use(express.favicon(__dirname + '/public/images/favicon.ico', {
maxAge: 2592000000
}));
app.use(app.router);
//Environment Variables
//app.configure('development', function() {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
dustjs.isDebug = true;
auth = require('./modules/auth/auth').auth(app);
in auth.js
module.exports.auth = function(app) {
//verification using passport.js
passport = require("passport");
express = require('express');
LocalStrategy = require('passport-local').Strategy;
FacebookStrategy = require('passport-facebook').Strategy;
TwitterStrategy = require('passport-twitter').Strategy;
app.use(express.cookieParser());
app.use(express.urlencoded());
app.use(express.json());
app.use(express.session({
secret: 'SECRET'
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(
etc...

Related

middleware not working when placed in if statement

Can someone tell me why this doesn't work:
app.use((req, res, next) => {
if (req.originalUrl === '/stripewebhook') {
next();
} else {
bodyParser.json();
bodyParser.urlencoded({
extended: true })(req, res, next);
}
});
But this works!
app.use((req, res, next) => {
if (req.originalUrl === '/stripewebhook') {
next();
} else {
bodyParser.json()(req, res, next);
bodyParser.urlencoded({
extended: true });
}
});
My original code was just the two bodyParsers middleware:
......
......
bodyParser.json();
bodyParser.urlencoded({
extended: true });
.....
I needed to add the if statement so that the webhook endpoint is skipped but I noticed that I had to set the statements like the above working example...what I am not sure about is if the .urlencoded() ever get executed??
I suspect that the Content Type of the Header may be not matching. You may take a look at this documentation: https://expressjs.com/en/resources/middleware/body-parser.html.
and also regarding the implementation: Trying to parse JSON Object from POST Request in Express v4 using body-parser
In node.js, middlewares like bodyParser.json() return functions. If the returned functions are not called, their behaviour does not apply.
The usual way to use them is to give their return values to app.use().
To have a conditional use of a middleware based on the route url, you can do something like:
const express = require('express')
const app = express()
const router = express.Router()
// specific router handling only your conditional middlewares
router.use(bodyParser.json())
router.use(bodyParser.urlencoded({ extended: true }))
// only call this router if the url is not /stripewebhook
app.use(/^(?!\/stripewebhook)/, router)
// [...] all your app-related middlewares
Of course this may not be the solution to your root issue regarding the stripe web hook.

Pass JWT in Header

I am learning JWT with NodeJs. I am stuck at passing the JWT in header actually i do not know how to do this.
index.js file
var express = require('express'),
app = express(),
routes = require('./routes'),
bodyParser = require('body-parser'),
path = require('path'),
ejs = require('ejs'),
jwt = require('jsonwebtoken');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.post('/home',routes.loginUser);
app.get('/', function(req, res) {
res.render('index');
});
app.get('/home',function(req, res) {
jwt.verify(req.token, 'qwertyu6456asdfghj', function(err, data) {
if (err) {
res.sendStatus(403);
}
});
});
app.listen(3000,function(){
console.log("Server running at Port 3000");
});
routes/index.js file
var jwt = require('jsonwebtoken');
exports.home = function(req, res){
res.render('home',{error: false});
};
exports.loginUser = function(req, res) {
var uname = req.body.Username;
var pwd = req.body.Password;
if(uname && pwd === 'admin'){
res.render('home');
var token = jwt.sign({ user: uname }, 'qwertyuiopasdfghj');
console.log('Authentication is done successfully.....');
console.log(token);
}
response.json({
authsuccess: true,
description: 'Sending the Access Token',
token: token
});
};
when i run the application i am getting the token in console.log but
How can I pass token in header and store it in localStorage of browser?
So you want to send the token to frontend but not in the body.
The Recommended way to do so is to use cookies. You can set the token in the cookie and it can be automatically accessed in front-end and in the backend.
res.cookie('tokenKey', 'ajsbjabcjcTOKENajbdcjabdcjdc');
Using authorization headers is also a good approach, but again, in front-end, you have to fetch the token from headers and then save in localStorage or cookie, which you don't have to do in case of cookie.
res.header(field [, value]);
As #ChicoDelaBarrio told you, it depends on the client. Postman is a good place to start checking your backend. But after you have your server working, you have to start working in your client side.
If you want a complete backend example about JWT in Node.js, with Refresh token included, I recomend you this post about it: Refresh token with JWT authentication in Node.js
Probably you can reuse most of the code. In this case the header is not created with BEARER, but with JWT at the beginning, but it works the same

Using CSRF in NodeJS

I am trying to use csrf in my NodeJS application.
You can see the code below. When I run this code I am getting "TypeError: req.csrfToken is not a function" error.
I want to create csrf token for all requests and want to check csrf tokens in ajax calls. As I said I can not create csrf token, I am getting error. Also how can I check csrf token in ajax calls?
Can you help me ?
Thanks
Server Side:
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var csrf = require('csurf');
var bodyParser = require('body-parser');
/*this line commented*/
//var csrfProtection = csrf({ cookie: false });
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
var parseForm = bodyParser.urlencoded({ extended: false });
app.use(cookieParser());
/*this line added*/
app.use(csrf({ cookie: false }));
app.use(session({
genid: function (req) {
return "lkgktktgjknvfndkj-dfgjnkdfkjgn-dfgdfg";
},
name: "mySecret",
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
secret: 'thisIsASecret'
}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(function (req, res, next) {
res.locals.csrfToken = req.csrfToken();
next();
});
app.get('/', /*csrfProtection,*/ function (req, res) {
res.render('index')
});
app.post('/process', parseForm, /*csrfProtection,*/ function (req, res) {
res.send('data is being processed')
});
Index.jade
meta(name="csrf-token", content="#{csrfToken}")
block content
input(type="hidden" name="_csrf" value="#{csrfToken}")
|Favorite color: <input type="text" name="favoriteColor">
button(type="submit" id="sbmt") Submit
script(src= "/javascripts/jquery-2.2.1.js")
script.
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
var token;
if (!options.crossDomain) {
token = $('meta[name="csrf-token"]').attr('content');
if (token) {
return jqXHR.setRequestHeader('X-CSRF-Token', token);
}
}
});
$("#sbmt").click(function (e) {
e.preventDefault();
$.post(
"/process",
{
//text: text,
_csrf : $('meta[name="csrf-token"]').attr('content')
}, function (data) {
console.log(data);
});
});
You have to add:
app.use(session({ ... });
// Add this after session
app.use(csrfProtection);
You need to add this AFTER the session as stated here:
If you are setting the "cookie" option to a non-false value, then you
must use cookie-parser before this module. Otherwise, you must use a
session middleware before this module. For example: express-session
cookie-session
Calling csrf() returns a function (source). You need to use it in order to have it. What you've missed in the tutorial is:
var csrfProtection = csrf({ cookie: true })
app.get('/form', csrfProtection, function(req, res) {
// pass the csrfToken to the view
res.render('send', { csrfToken: req.csrfToken() })
})
Here, the csrfProtection is actually being called, and it adds csrfToken method to req. In the other example there is:
app.use(csrf({ cookie: true }))
Which means all routes will use the protection and therefore no post without it would be possible.
It depends on your usage - if you want to secure all routes - use it globally (app.use), otherwise use it per request (as in the first example).
If you try using it in your index route you will have it, because you've used it as middleware:
app.get('/', csrfProtection, function (req, res) {
res.render('index')
});

NodeJS JWT token verification

I'm trying to verify a signed token and extract information from it using NodeJS.
I have a token named userToken in the browser right now, it has been saved after I logged in (I use auth0 to login by the way).
I tried to verify my token here manually : http://jwt.io , it works and gives me payload data without a problem. However, I can't do the same thing with NodeJS. How can I do it?
I read the docs but I couldn't get it.
https://github.com/auth0/express-jwt
Here's my server.js
var http = require('http');
var express = require('express');
var cors = require('cors');
var app = express();
var jwt = require('express-jwt');
var dotenv = require('dotenv');
dotenv.load();
var authenticate = jwt({
secret: new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64'),
audience: process.env.AUTH0_CLIENT_ID
});
// view engine setup
var path = require('path');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'jade');
app.configure(function () {
// Request body parsing middleware should be above methodOverride
app.use(express.bodyParser());
app.use(express.urlencoded());
app.use(express.json());
app.use(cors());
app.use(app.router);
});
app.get('/', function (req, res) {
res.render('index');
});
app.get('/test', function(req,res) {
// how do I check it?
});
var port = process.env.PORT || 3001;
http.createServer(app).listen(port, function (err) {
console.log('listening in http://localhost:' + port);
});
You dont't need to implement nothing. Since you are using this express-jwt, just pass the userProperty tag to jwt:
var authenticate = jwt({
secret: new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64'),
audience: process.env.AUTH0_CLIENT_ID,
userProperty: 'payload'
});
So, you can get all of your jwt payload data using req.payload in your controllers. You can check it with console.log(req.payload).
You can see how it works here: https://github.com/auth0/express-jwt/blob/master/lib/index.js#L121
I hope it helps, and sorry about my English.
This sample should help you, it's not tested, but sure it's right way, look at source of express-jwt, it does literally same behind the scenes
app.get('/test', function(req, res) {
var jsonwebtoken = require('jsonwebtoken'); //install this, move to declarations
var loginToken = req.headers.authentication || req.body.userToken || req.headers.Bearer; //or your own, it's just headers that pass from browser to client
jsonwebtoken.verify(loginToken, new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64'), function(err, decoded) {
if(err) {
return res.status(401).send({message: 'invalid_token'});
}
//be aware of encoded data structure, simply console.log(decoded); to see what it contains
res.send(decoded); //`decoded.foo` has your value
});
});
The thing is that you must yourself encode your data, and then decode, so be aware that auth0 returns valid data structure for you (as i'm not sure otherwise)

Another express.js req.session not storing data

I have been staring at the same SO questions/answers for too long.
I am trying to set my user ID in a req.session variable
here is my app.js stack
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, cors = require('cors')
, mongoose = require('mongoose')
, User = require('./user-model')
, path = require('path')
, mysql = require('mysql');
app = express()
/**
* Middleware.
*/
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'supercalafragalistic' }));
app.locals.pretty = true;
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'jade');
...
app.get('/someRoute', routes.someRoute)
I have moved the app.router from top to bottom. Currently it is implied (I just deleted it as I stripped my code looking for error). I have exported app, included app in routes (also erased) . I added middleware. I am lost.....
here is my route stack
//routes/index.js
//requires
var User = require('../user-model')
,qs = require('querystring')
,http = require('http')
,mysql = require('mysql')
,connection = mysql.createConnection({
edited
});
/**
* Set up application.
*/
connection.connect(function(err){
if(err) console.log('failed to connect to mysql because'+ err);
else console.log('connected to mysql');
})
I save the id in the login route:
//login processing route
exports.logIn = function(req, res, next){
console.log('log in request from '+req.body.name);
User.findOne({name:req.body.name}, function(err, user, next){
if(err) return next(err);
if(!user) return res.end();
//check password
user.comparePassword(req.body.password, function(err, isMatch){
if(err) res.send('failed to find user');
console.log(""+isMatch);
if(isMatch){
console.log(user._id.toString()+' user loggd in');
//set session cookie
req.session.loggedIn = user._id.toString();
console.log('req.session.loggedIn set to :'+req.session.loggedIn );
res.send(user);
}else {
res.send('User not found try again');
}
});
});
However, in all other routes the variable is undefined:
// clock status
exports.clockStatus = function(req, res, next){
var user = req.session.loggedIn;
console.log('Status route, userID: '+user);
if(user){
I found the answer in "Cannot access req.session variables in Express/NodeJS" but the last part trails off:
In your case, you have assigned req.session.user = user; only in
/login request. It will not be available for further requests(/auth).
You have to get user information in /auth request too by session id.
(Or) Better you can use passport for authentication.
HOW? How do you "get user information in /auth request too by session id"?
Please ask for anything else you need to straighten me out.
I'm stumped. I have tried some dumb stuff already!
The variable is undefined in other routes if you don't log in first in the browser. Here is my test code:
var express = require('express');
var cors = require('cors');
app = express();
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'this is a test' }));
app.use(express.static(require('path').join(__dirname, 'public')));
app.get('/login', function(req, res) {
req.session.uid = 'user001';
res.send(req.session);
});
app.get('*', function(req, res) {
res.send(req.session);
});
app.listen(8080);
First visit http://localhost/login in the browser. Then visit other URLs(e.g., http://localhost/test) in this browser, the user id in the session is returned. So maybe there is something wrong in other parts of your code.
Test settings:
Ubuntu Desktop 13.10, 64 bit
Node 0.10.26
NPM 1.4.4
Express 3.4.8
cors 2.2.0

Categories

Resources