Cannot POST with ExpressJS and CSRF - javascript

I'm newbie with node.js and express and I'm trying to protect some url's with a token. I generate the token correctly but when I post a form with this token I've got an error in my browser with this text "Cannot POST /process" where /process is the url where I send the data from my form. In my console I haven't any error. So, I don't know what is happend or what am I doing wrong :(
The code is divided in three files, main file called (index.js) where I require the second file (routes-api.js) and the html file with the form.
index.js
//Creación de un servidor con express
const express = require("express");
const app = express(); //Inicializamos express
//Accedemos a otros módulos
const morgan = require("morgan");
const bodyParser = require("body-parser");
const jwt = require("jsonwebtoken");
const cookieParser = require('cookie-parser');
//Accedemos a propiedades de configuración
const config = require("./config");
//Rutas
const routes = require("./routes");
const routesAPI = require("./routes-api");
//Settings
app.set("app-name", config.server);
app.set("port", config.port);
app.set("super-secret", config.secret);
//Middlewares
// use body parser so we can get info from POST and/or URL parameters
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(morgan("dev")); //Log request to the console
app.use(cookieParser());
app.use((req, res, next) => {
console.log("Pasamos por la segunda función!!!");
next();
});
//Routing
app.use("/api", routesAPI);
app.use(routes);
//Server
app.listen(app.get("port"), () => {
console.log("Servidor " + app.get("app-name") + " escuchando!!!");
}); //Creamos el servidor con express
route-api.js
const csrf = require('csurf');
const path = require("path");
const bodyParser = require("body-parser");
const express = require("express");
const router = express.Router();
// setup route middlewares
var csrfProtection = csrf({ cookie: true });
var parseForm = bodyParser.urlencoded({ extended: false });
router.get("/", csrfProtection, (req, res) => {
console.log("crsf: " + req.csrfToken());
res.sendFile(path.join(__dirname + '/send.html'), { csrfToken: req.csrfToken() });
});
router.post('/process', parseForm, csrfProtection, function(req, res) {
console.log("csrf: " + req.body._csrf + " color: " + req.body.favoriteColor);
res.send('data is being processed');
});
module.exports = router;
send.html
<form action="/process" method="POST">
<input type="text" name="_csrf" value="{{csrfToken}}">
Favorite color: <input type="text" name="favoriteColor">
<button type="submit">Submit</button>
</form>
What am I doing wrong to get the error "Cannot POST /process" when I send the form to the server?

Related

NodeJS response is not parsed by express or bodyparser

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
// app.use(express.urlencoded({extended:false}));
// app.use(express.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json())
router.get('/add-product', (req, res, next) => {
res.send('<form action="/product" method="POST"><input type="text" id="fname" name="fname"><br><input type="submit" value="Submit"></form>')
})
the response isn't parsed .. I tried 1k things .. Nothing works... i still receive undefined
i tried both variants **app.use(bodyParser.urlencoded({extended:true})); and app.use(express.urlencoded({extended:false})); + app.use(bodyParser.json()) and app.use(express.json());**
What's to do ? thank you in advance
you should have app.get and not router.get
See here

IF Statement is setting a session attribute in NODE js and express

I am trying to do a log in page for a Uni project and am having difficulty as when trying to redirect user based on an access level the if statement is setting the Access Role before the function and so all traffic when first logged in gets redirected to the Admin page, refreshing the page makes the code work properly as that it when the code that gets the details from the database has finished running... Any help would be great thanks!
LogInController
const session = require('express-session');
var Login = require('../models/Login');
exports.checksLogin = (req, res) => {
// Implement this method using the pupil model
console.log(req.originalUrl + "POST Received with query: ", req.body)
const {Email, Pswd} = req.body
Login.checkLogin(Email, Pswd)
if(session.AccessRole='Admin'){
res.redirect('/admin')
}
else{
}
}
Login.js (Models)
exports.checkLogin = (Email, Pswd) => {
var database = require('../dbConfig');
database.then(con => {
con.query("SELECT * FROM Pupils WHERE Email = '" + Email + "'AND Pswd= '" + Pswd + "'").then(([rows]) => {
//console.log(rows)
if(rows.length>0){
session.LoggedIn=true;
session.FirstName=rows[0].FirstName
session.LastName=rows[0].LastName
session.Email=rows[0].Email
session.CourseCode=rows[0].CourseCode
session.Pswd=rows[0].Pswd
session.AccessRole='Student'
console.log(session.Loggedin+ '1')
}
else {
con.query("SELECT * FROM Staff WHERE Email = '" + Email + "'AND Pswd= '" + Pswd + "'").then(([rows]) => {
console.log(rows)
session.LoggedIn=true;
session.staffID=rows[0].staffID
session.FirstName=rows[0].FirstName
session.LastName=rows[0].LastName
session.Email=rows[0].Email
session.Role=rows[0].Role
session.Pswd=rows[0].Pswd
if(session.Role='Admin'){
console.log(`Admin`)
session.AccessRole='Admin'
}else{
session.AccessRole='Staff'
}
})
}
})
})
}
index.js
const express = require('express');
const app = express();
const path = require('path');
const exphbs = require('express-handlebars');
var session = require('express-session');
var bodyParser = require('body-parser');
// Middlewares
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars')
app.use(express.urlencoded({extended: true}))
// Client routes
app.get('/', (req, res) => res.render('index'));
app.use('/admin', require('./routes/Admin'));
app.use('/login', require('./routes/Login'));
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true
}));
app.use(bodyParser.urlencoded({extended : true}));
app.use(bodyParser.json());
const PORT= process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server Started on port ${PORT} `));
Login.js (Routes)
const express = require('express');
const router = express.Router();
var Login_controller = require('../controllers/LoginController');
// Use the login.handlebars template
router.get('/', (req, res) => res.render("login"));
// CRUD routes
router.post("/submit-login", Login_controller.checksLogin);
module.exports = router;
Admin.js
const express = require('express');
const session = require('express-session');
const router = express.Router();
var pupils_controller = require('../controllers/PupilsController');
var staff_controller = require('../controllers/StaffController')
// Use the login.handlebars template
router.get('/', (req, res) => {
console.log(session.LoggedIn)
if(session.AccessRole=='Admin'){
res.render("admin")
}
else{
console.log(`No Entry`)
res.redirect('/')
}
});
// CRUD routes
router.post('/create-pupil', pupils_controller.createPupil);
router.post('/delete-pupil', pupils_controller.deletePupil);
router.post('/create-staff', staff_controller.createStaff)
module.exports = router;
login.handlebars
<p> Log In </p>
<form method="POST" action="/login/submit-login">
<label for="Email">Email</label><br>
<input type="text" name="Email" /><br>
<label for="Pswd">Password</label><br>
<input type="text" name="Pswd" /><br>
<input type="submit" />
</form>
Using a MYSQL database, Node js and express
Thanks
Please note that the IF statement here must have double equal sign to compare, instead of that you are doing an assignation
const session = require('express-session');
var Login = require('../models/Login');
exports.checksLogin = async (req, res) => {
// Implement this method using the pupil model
console.log(req.originalUrl + "POST Received with query: ", req.body)
const {Email, Pswd} = req.body
await Login.checkLogin(Email, Pswd)
if(session.AccessRole == 'Admin') {
res.redirect('/admin')
} else {
}
}

req.body returning undefined?

i have installed body parser through npm, required it, set it with express buti am still getting req.body undefined. If someone knows whats wrong please let me know i feel like its something stupid im missing.
This is my app.js file
const express = require('express')
const index = require('./routes/index');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
//Create the express server
const app = express();
// Use index routes file
app.use('', index);
// Use the /public folder for our assets
app.use('/public', express.static('public'));
// Use body-parser and cookie-parser
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(cookieParser);
// Set ejs as our templating engine
app.set('view engine', 'ejs');
// Catch 404 and forward to error handler
app.use(function(req, res, next) {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
// Error handler
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.status(res.statusCode || 500);
res.render('error', {error: err.message});
console.log(err.message);
});
app.listen(process.env.PORT || 3000, () => {
console.log('Application running on localhost:3000');
});
This is my route index.js file that's making the post
const express = require('express');
const router = express.Router();
const fs = require('fs');
const movie_controller = require('../controllers/movieController');
const bodyParser = require('body-parser');
const request = require('request');
router.get('/about', (req, res, error) => {
res.render('about');
});
router.get('/', movie_controller.get_index);
router.get('/currently_playing', movie_controller.get_currently_playing);
router.get('/top_rated', movie_controller.get_top_rated);
router.get('/upcoming', movie_controller.get_upcoming);
router.get('/movie_view/:id', movie_controller.get_movie);
// Post request for a search query
router.post('/search', (req, res, next) => {
console.log('Query', req.body);
// Make request for query
request('https://api.themoviedb.org/3/search/movie?api_key=&language=en-
US&query=' + req.body + '&page=1&include_adult=false', (error, response,
body) => {
//handle errors
if(error){res.render('error', {error: error.message})}
//handle body
if(response.statusCode === 200){
//place body data in a variable for later reference
let movieData = JSON.parse(body);
let movies = [];
movieData.results.forEach(movie => {
movies.push(movie);
});
// Make request for genres
request('https://api.themoviedb.org/3/genre/movie/list?
api_key=&language=en-US', (error, response, body) => {
//handle errors
if(error){res.render('error', {error: error.message})}
//handle body
if(response.statusCode === 200){
//place body in a variable for later reference
let genreData = JSON.parse(body);
let genres = [];
genreData.genres.forEach(genre => {
genres.push(genre);
});
res.render('results', {movie: movies, genres: genres });
}
})
}
})
});
module.exports = router;
This is where the form is on a header.ejs partial
<form class="form-inline my-2 my-lg-0" action="/search" method="post">
<input class="form-control mr-sm-2" type="search" placeholder="Search" name="searchQuery" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>enter code here
You should to use the bodyParser() before app.use('', index) of your router, to avoid any problem just place app.use('', index) it in the last.
// Use body-parser and cookie-parser
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(cookieParser);
// Use index routes file
app.use('', index);
Express middleware runs in the order you register them (routes included). You have registered the bodyParser and cookieParser middlewares after attaching your routes. Therefore, you will not have the parsed body or cookies by the time your route is encountered.
To fix this, make sure that any middlewares you want to run before your actual route are registered before:
const express = require('express')
const index = require('./routes/index');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
//Create the express server
const app = express();
// Use the /public folder for our assets
app.use('/public', express.static('public'));
// Use body-parser and cookie-parser
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(cookieParser);
// Use index routes file
app.use('', index);
...

Cannot GET with nodejs?

I have a simple nodejs app with some users. I want to load a specific user profile using a URL localhost/users/(username) but I'm getting this error when I try to load the URL:
Cannot GET /users/test
Here's my user.js routes file for the user page:
var express = require('express');
var router = express.Router();
var User = require('../models/user');
// GET user by username
router.get('/users/:username', function(req, res) {
var username = req.params.username;
res.send(req.params);
res.render('user');
});
module.exports = router;
I have a user.handlebars file in my views folder so it should load the file. What am I missing in my routes file? Any help would be greatly appreciated. Thanks!!
EDIT: app.js:
console.log('Starting app.js');
const fs = require('fs');
const _ = require('lodash');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const exphbs = require('express-handlebars');
const expressValidator = require('express-validator');
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const mongo = require('mongodb');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/tipcup');
var db = mongoose.connection;
const routes = require('./routes/index');
const users = require('./routes/users');
const user = require('./routes/user');
// Init App
var app = express();
// View Engine
app.set('views', path.join(__dirname, 'views'));
app.engine('handlebars', exphbs({defaultLayout: 'layout'}));
app.set('view engine', 'handlebars');
// BodyParser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));
app.use(cookieParser());
// Set Static Folder
app.use(express.static(path.join(__dirname, 'public')));
// Express Session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// Passport Init
app.use(passport.initialize());
app.use(passport.session());
// Express Validator
app.use(expressValidator ({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length){
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
};
}
}));
// Connect Flash
app.use(flash());
// Global Vars
app.use(function (req, res, next){
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
res.locals.user = req.user || null;
next();
});
app.use('/', routes);
app.use('/users', users);
app.use('/users/:username', user);
// Set Port
app.set('port', (process.env.PORT || 3000));
app.listen(app.get('port'), function(){
console.log('Server started on port '+app.get('port'));
});
Render function renders a view and sends the rendered HTML string to the client.Take a look at documentation.
But what you are trying to archive is to send data first and then render and send again. So, just delete the line with send.
router.get('/users/:username', function(req, res) {
var username = req.params.username;
res.render('user');
});
And, please, edit your question by adding your code with middleware and add your error.
Update
Take a look at the way how you define your routes for users.
You have to remove /users from defining route in users.js file

Calling node api through postman with response as enable javascript error

When calling API https://mywebsite.com/api/register through browser and it returns correct response from server as { "error": false, "message": "Hello World" }
If we hit the same request from postman then it returns with some html content as Please enable JavaScript to view the page content.
Below is node side code:
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var router = express.Router();
var cors = require('cors');
app.use(cors());
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({ limit: '50mb', "extended": false }));
router.get("/", function (req, res) {
res.json({ "error": false, "message": "Hello World" });
});
The api working through the browser but not with postman. What will be the possible errors?
If you want to separate the router files then use the following pattern otherwise use app.get()
app.js
var express = require('express'),
car = require('./routes/car'),
bus = require('./routes/bus');
var app = express();
app.use('/car', car);
app.use('/bus', bus);
app.listen(2000);
car.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('GET handler for /car route.');
});
router.post('/', function(req, res) {
res.send('POST handler for /car route.');
});
router.put('/', function(req, res) {
res.send('put handler for /car route.');
});
module.exports = router;
Try this instead:
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var router = express.Router();
var cors = require('cors');
app.use(cors());
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({ limit: '50mb', "extended": false }));
app.listen(8080);
app.get("/", function (req, res) {
res.json({ "error": false, "message": "Hello World" });
});
Replace router.get with app.get.
I test your code on my browser and it doesn't work too.

Categories