I'm learning about backend and I have a problem with csurf protection in my express nodejs project. When I submit in add-admin form is working find, but add-product form and edit-product form I receive the error
invalid csrf token
403
ForbiddenError: invalid csrf token
this is my app.js
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var expressHbs = require('express-handlebars');
var mongoose = require('mongoose');
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
var MongoStore = require('connect-mongo')(session);
var indexRouter = require('./routes/index');
var userRouter = require('./routes/user');
var adminRouter = require('./routes/admin');
const Product = require('./models/product');
var app = express();
mongoose.connect('mongodb://localhost:27017/project3', {useNewUrlParser: true, useUnifiedTopology: true});
require('./config/passport')(passport);
// view engine setup
app.engine('.hbs',expressHbs({defaultLayout:'layout', extname:'.hbs', runtimeOptions: {
allowProtoPropertiesByDefault: true,
allowProtoMethodsByDefault: true
}}));
app.set('view engine', '.hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(session({
secret:'mysupersecret',
resave: false,
saveUninitialized: false,
store: new MongoStore({mongooseConnection: mongoose.connection}),
cookie: {maxAge: 30*60*24*60*1000}
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use('/static',express.static('public'));
app.use(function(req,res,next){
res.locals.login = req.isAuthenticated();
res.locals.session = req.session;
next();
});
//routes
app.use('/admin', adminRouter);
app.use('/user', userRouter);
app.use('/', indexRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
My admin.js
var express = require('express');
var router = express.Router();
var csrf = require('csurf');
var multer = require('multer');
var mongoose = require('mongoose');
var async = require('async');
var {check, validationResult} = require('express-validator');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var csrfProtection = csrf();
router.use(csrfProtection);
mongoose.connect('mongodb://localhost:27017/project3', {useNewUrlParser: true, useUnifiedTopology: true});
var Product = require('../models/product');
var User = require("../models/user");
// add-product page
router.get("/add-product",csrfProtection,
function(req,res,next) {
var messages = req.flash('error');
res.render('admin/add-product', {
csrfToken: req.csrfToken(),
messages: messages,
hasErrors: messages.length>0,
});
});
//edit-product page
router.get("/edit-product/:id", csrfProtection,function(req,res,next){
Product.findById(req.params.id, function(err, data){
if(err) {
throw err;
} else {
res.render("admin/edit-product", {
csrfToken: req.csrfToken(),
editedProduct:data,
});
}
});
});
//delete a product
router.get("/delete-product/:id", function(req,res,next){
Product.deleteOne({_id: req.params.id}, function(err){
if(err) {
throw err;
} else {
res.redirect("../list-product");
}
});
});
//list admin
router.get('/list-admin', function(req,res,next){
User.find({rule: 2}, function(err,admin){
if(err) {
throw err;
}
else {
res.render('admin/list-admin', {
csrfToken: req.csrfToken(),
admin: admin
});
}
});
});
// add account admin
router.get('/add-admin', function(req,res, next) {
var messages = req.flash('error');
res.render('admin/add-admin', {
csrfToken: req.csrfToken(),
messages: messages,
hasErrors: messages.length>0
});
});
module.exports = router;
my add-user.hbs
<div class="row">
<div class="col-sm-6 col-md-4 col-md-offset-4 col-sm-offet-3">
<form action="/admin/add-product" method="post" id='checkout-form' enctype="multipart/form-data">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label for="name">Tên sản phẩm</label>
<input type="text" id="name" name="name" class="form-control" required>
</div>
</div>
</div>
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<button type="submit" class="btn btn-success">Thêm sản phẩm</button>
</form>
</div>
</div>
edit-product.hbs
<div class="row">
<div class="col-sm-6 col-md-4 col-md-offset-4 col-sm-offet-3">
<form action="../edit" method="post" id='edit-form' enctype="multipart/form-data" >
<div class="row">
<input type="hidden" name="IDChar" value={{editedProduct._id}}>>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Tên sản phẩm</label>
<input type="text" id="name" value="{{editedProduct.name}}" class="form-control" required>
</div>
</div>
<hr>
</div>
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<button type="submit" class="btn btn-success">Thay đổi</button>
</form>
</div>
</div>
add-admin.hbs
<div class="row">
<div class="col-md-4 col-md-offset-4">
<h3>Thêm tài khoản admin</h3>
{{#if hasErrors}}
<div class="alert alert-danger">
{{#each messages}}
<p>{{this}}</p>
{{/each}}
</div>
{{/if}}
<form action="/admin/add-admin" method='post'>
<div class="form-group">
<label for="email">Email</label>
<input type="text" id ="email" name = "email" class="form-control">
</div>
<div class="form-group">
<label for="password">Mật khẩu</label>
<input type="password" id="password" name="password" class="form-control">
</div>
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<button type="submit"class="btn btn-primary">Thêm tài khoản Admin</button>
</form>
</div>
</div>
i searched in google and document of csurf but i can't find resolve. Please help me, thank you for watching.
Related
I need to log the username from the file register.ejs to my console
i have checked the code soo many times and i couldn't get the solution the is error.. plz help me out
this is my /register file:
<!-- Makes POST request to /register route -->
<form action="/register" method="POST">
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" name="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-dark">Register</button>
</form>
</div>
</div>
</div>
This is my app.js file:
const express = require("express");
var bodyParser = require("body-parser");
const app = express();
var urlencodedParser = bodyParser.urlencoded({ extended: true });
app.set("view engine", "ejs");
app.use(express.static("publica"));
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/userDB", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const userSchema = new mongoose.Schema({
email: String,
password: String,
});
const User = mongoose.model("User", userSchema);
app.get("/", (req, res) => {
res.render("home");
});
app.get("/login", (req, res) => {
res.render("login");
});
app.get("/register", (req, res) => {
res.render("register");
});
app.post("/register", function (req, res) {
console.log(req.body.username);
});
app.listen(3000, () => {
console.log("All Good Bruh!!!");
});
im trying to log the username from /register page but im getting this error:
Cannot read property 'username' of undefined
Please help me out
add app.use(bodyParser.urlencoded({ extended: true }));
some where up
id and cost are integers and cannot be NULL.
I am getting this error:
'Error: ER_BAD_FIELD_ERROR: Unknown column 'undefined' in 'field list''
var sql = "INSERT INTO Paintings(`painting_id`,`painting_title`,`img`,`cost`) VALUES("+id+",'"+title+"','"+img+"',"+cost+")";
This is my html form
<form action="/post" method="POST">
<div class="form-group">
<label>Painting id </label>
<input type="text" name="painting_id" id="painting_id" >
</div>
<div class="form-group">
<label>Painting Title</label>
<input type="text" name="painting_title" id="painting_title" >
</div>
<div class="form-group">
<label>Image </label>
<input type="src" name="img" id="img">
</div>
<div class="form-group">
<label>Cost </label>
<input type="text" name="cost" id="cost">
</div>
<br/>
<input type="submit" value="create painting"/>
</form>
This is my server side code
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
var mysql = require('mysql');
var session = require("express-session");
app.use(express.static(__dirname + '/public'));
app.set("view engine", "ejs");
var urlencodedParser= bodyParser.urlencoded({extended: false});
app.use(express.json());
//======SQL CONNECTION========
var connection = mysql.createConnection({
host: 'localhost',
user: 'admin',
password: 'admin',
database: 'artdb'
});
connection.connect(function(err){
if(err){
throw(err);
}
console.log("Connected to database");
})
app.get('/admin/painting',function(req,res){
connection.query(`select * from Paintings`,(err,result,fields)=>{
if(err){
return console.log(err);
}
res.render("painting",{page_title:"Customers - Node.js",userData: result});
});
});
app.get('/painting/add', function(req,res,next){
res.render('add_painting');
})
app.post('/post', function (req,res,next){
var id= req.body.painting_id;
var title = req.body.painting_title;
var img = req.body.img;
var cost = req.body.cost;
var sql = "INSERT INTO Paintings(`painting_id`,`painting_title`,`img`,`cost`) VALUES("+id+",'"+title+"','"+img+"',"+cost+")";
connection.query(sql,function(err,result){
if(err) throw(err);
console.log("Data Inserted");
res.redirect('/admin/painting');
});
});
app.listen(1100, ()=> {
console.log("Server is running");
})
You need to use urlencoded body parser in your express app
app.use(bodyParser.urlencoded({ extended: false }))
just declaring
var urlencodedParser= bodyParser.urlencoded({extended: false});
doesn't actually apply it to your app
im currently trying to save some data from Bootstrap input fields into my mongoDB database but i always get the error insertMovie:1 POST http://localhost:3000/insertMovie 404 (Not Found). I tried to change the Routes but i cant find my mistake. My Schema is in a file called movie.js.
I Feel like i dont really get the Route thing of express, im very new at this.
<div class="container">
<div class="row">
<div class="col">
<form method="post" action="/insertMovie">
<h1 class="text-center pt-5">Neuen Film anlegen</h1>
<div class="form-group">
<label>Titel</label>
<input
type="text"
class="form-control"
placeholder="Titel eingeben"
name="title"
/>
</div>
<div class="form-group">
<label>Beschreibung</label>
<input
type="text"
class="form-control"
placeholder="Beschreibung eingeben"
name="description"
/>
</div>
<div class="form-group">
<label>Startdatum</label>
<input
type="text"
class="form-control"
placeholder="Startdatum eingeben"
name="start"
/>
</div>
<div class="form-group">
<label>Aktuell laufend</label>
<input
type="text"
class="form-control"
placeholder="Beschreibung eingeben"
name="currentlyRunning"
/>
</div>
<input id="submit" type="submit" class="btn btn-primary" />
</form>
</div>
</div>
</div>
movies.js
const express = require("express");
const router = express.Router();
const Movie = require("../models/movie");
router.get("/", async (req, res) => {
try {
const movies = await Movie.find();
res.json(movies);
} catch (err) {
res.json({ message: err });
}
});
router.post("/insertMovie", async (req, res) => {
const movie = new Movie({
title: req.body.title,
description: req.body.description,
start: req.body.start
});
try {
const savedMovie = await movie.save();
res.json(savedMovie);
} catch (err) {
res.json({ message: err });
}
});
module.exports = router;
app.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const mongoose = require("mongoose");
const cors = require("cors");
require("dotenv/config");
//Middlewares
app.use(bodyParser.json());
app.use(cors());
//Import Routes
const moviesRoute = require("./routes/movies");
app.use("/movies", moviesRoute);
// include a static file serving middleware
app.use(express.static(__dirname + "/"));
// Get all Data
app.get("/data", function(req, res) {
res.sendfile("index.html");
});
// Insert new Movie
app.get("/insertMovie", function(req, res) {
res.sendfile(__dirname + "/insert.html");
});
mongoose.connect("mongodb://localhost:27017/testDB", { useNewUrlParser: true });
app.listen(3000);
The issue here is with your movie routes. With the way you set it up, your endpoint is actually:
localhost:3000/movies/insertMovie
but you are using:
localhost:3000/insertMovie
I am using the express-fileupload module. I have also written some jquery to try and make this work. What I see most of the time is the case where the image is sent to the database gotten back for display. But, in my case, once I attach the image to the input element, I want the image to be displayed through an img tag, before final form submission. I look forward to hearing from anyone. Thank you.
//app.js
var express = require('express');
var path = require('path');
var mongoose = require('mongoose');
require('dotenv').config();
var bodyParser = require('body-parser');
var session = require('express-session');
var expressValidator = require('express-validator');
var fileUpload = require('express-fileupload');
//Connect to db
mongoose.connect(process.env.MONGO_URL, { useNewUrlParser: true });
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('connected to mongoDB');
});
//Init app
var app = express();
//View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
//Set public folder
app.use(express.static(path.join(__dirname, 'public')));
//Set global errors variable
app.locals.errors = null;
// Express FileUpload middleware
app.use(fileUpload());
//Body Parser Middleware
//
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
//express session middleware
app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true,
// cookie: { secure: true }
}));
//express-validator middleware
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
};
}
}));
//Express messages middleware
app.use(require('connect-flash')());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
//set routes
var pages = require('./routes/pages');
var adminPages = require('./routes/admin_pages');
var adminCategories = require('./routes/admin_categories');
var adminProducts = require('./routes/admin_products');
app.use('/admin', pages);
app.use('/admin/pages', adminPages);
app.use('/admin/categories', adminCategories);
app.use('/admin/Products', adminProducts);
var port = 3000 || process.env.PORT;
app.listen(port, function() {
console.log('Server started on port ' + port);
});
//add_products.js
router.get('/add-product', function (req, res) {
var title = "";
var desc = "";
var price = "";
Category.find(function(err, categories) {
res.render('admin/add_product', {
title: title,
desc: desc,
categories: categories,
price: price
});
});
});
//add_product.ejs
<%- include('../_layouts/adminheader') %>
<h2 class="page-title">Add a product</h2>
Back to all products
<br><br>
<form method="post" action="/admin/products/add-product" enctype="multipart/form-data">
<div class="form-group">
<label for="">Title</label>
<input type="text" class="form-control" name="title" value="<%= title %>" placeholder="Title">
</div>
<div class="form-group">
<label for="">Description</label>
<textarea class="form-control" name="desc" cols="30" rows="10" placeholder="Description"><%= desc %></textarea>
</div>
<div class="form-group">
<label for="">Category</label>
<select name="category" class="form-control">
<% categories.forEach(function(cat) { %>
<option value="<%= cat.slug %>">
<%= cat.title %>
</option>
<% }); %>
</select>
</div>
<div class="form-group">
<label for="">Price</label>
<input type="text" class="form-control" name="price" value="<%= price %>" placeholder="Price">
</div>
<div class="form-group">
<label for="">Image</label>
<input type="file" class="form-control" name="image" id="img">
<img src="#" id="imgPreview" alt="" />
</div>
<button class="btn btn-default">Submit</button>
</form>
<script>
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$("#imgPreview").attr('src', e.target.result).width(100).height(100);
}
reader.readAsDataURL(input.files[0]);
}
}
$("#img").change(function () {
readURL(this);
});
</script>
<%- include('../_layouts/adminfooter') %>
I'm a newbie so be kind. I've been trying to learn passport via an online tutorial (this one, github here) and as far as I can tell I've recreated the code verbatim but I'm getting an error that the localhost didn't send any data. My full code is here. I'm pasting some code below but I'm honestly unsure which piece of code to post since I don't know where the error is occurring.
Here's the server app:
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var exphbs = require('express-handlebars');
var expressValidator = require('express-validator');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongo = require('mongodb');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/loginapp');
var db = mongoose.connection;
var routes = require('./routes/index');
var users = require('./routes/users');
//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');
//body parser 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 middleware
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
//passport init
app.use(passport.initialize());
app.use(passport.session());
//validator middleware-- this code is straight from the validator github page
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 middleware
app.use(flash());
//global variables for flash messages
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);
//set port
app.set('port', (process.env.PORT || 3000));
app.listen(app.get('port'), function() {
console.log('Server started on port ' + app.get('port'));
});
Here's the form:
<h2 class="page-header">Register</h2>
<form method="post" action="/users/register">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" placeholder="Name" name="name">
</div>
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" placeholder="Username" name="username">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" placeholder="Email" name="email">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" placeholder="Password" name="password">
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" class="form-control" placeholder="Password" name="password2">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
And here's the user js:
var express = require('express');
var router = express.Router();
//register
router.get('/register', function(req, res) {
res.render('register');
});
//login
router.get('/login', function(req, res) {
res.render('login');
});
//register user
router.post('/register', function(req, res) {
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
});
module.exports = router;
First things first: you are actually not doing anything on the post('/register'..)
You should save your model and return it if successful, something like this:
var schema = new mongoose.Schema({ name: 'string', email: 'string' });
var User = mongoose.model('User', schema);
//register user
router.post('/register', function(req, res) {
var name = req.body.name;
var email = req.body.email;
var user = new User({ name: name, email: email});
user.save(function (err) {
if (err) throw err;
res.send(user);
});
});
Of course you would define your model on a separate folder and import it to where it fits.