Using CSURF in Express app with session package without using body-parser - node.js

I am trying to use CSURF package in Express App without using Body-Parser package. Body-Parser isn't needed in Express App because we can use app.use(express.json())to handle request.body instead of Body-Parser so I am trying to figure out a way to use CSURF without having Body-Parser in my app.
I have installed CSURF and following the instructions online without using Body-Parser but I got errors saying that the CSRF key is missing. My front-end is a login form and I have used EJS in order to send the CSRF Token from the server to the front-end.
Front-end:
<form id="login-form">
<div class="input-group form-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-user"></i></span>
</div>
**<input type="hidden" id="_csrf" name="_csrf" value= "<%= csrfToken %>" > **
<input type="text" class="form-control" id="username" placeholder="username">
</div>
<div class="input-group form-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-key"></i></span>
</div>
<input type="password" class="form-control" id="password" placeholder="password">
</div>
<div class="form-group">
<input type="submit" value="Login" class="btn float-right login_btn">
</div>
</form>
<script>
const form = document.querySelector('#login-form');
form.addEventListener('submit', (event) => {
event.preventDefault();
const username = form.elements.username.value;
const password = form.elements.password.value;
const csrf = form.elements._csrf.value
fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password,csrf }),
})
</script>
Back-end:
router.post('/login', (req, res, next) => {
console.log(req.body.csrf);
if (!req.body.csrf) {
// Return an error if the CSRF token is missing
return res.send({ message: 'CSRF token missing' });
}
// Check if the CSRF token in the request body matches the one in the session
if (req.body.csrf !== req.csrfToken()) {
// Return an error if the CSRF token is invalid
return res.send({ message: 'CSRF token invalid' });
} else {
// Authenticate the user using the local strategy
passport.authenticate('local', (error, user, info) => {
if (error) {
return next(error);
}
if (!user) {
return res.send({ success: false, message: 'Invalid username or password' });
}
req.login(user, (error) => {
if (error) {
return next(error);
}
req.session.loggedIn = true;
res.send({ success: true, message: 'Login success, redirecting you to homepage in 3 seconds' });
return;
});
})
(req, res, next);
}
});
router.get('/login', (req, res) => {
console.log(req.csrfToken());
res.render('login', { csrfToken: req.csrfToken() });
});
App:
app.use(express.json());
express.urlencoded({ extended: true });
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.use(
session({
store: new MSSQLStore(DBconfig, options),
secret: process.env.SESSION_KEY,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000 * 60 * 60 * 24, // 24 hours
secure: true
}
}));
app.use(csurf({ }));
app.use(function (req, res, next) {
res.locals.csrfToken = req.csrfToken();
next();
})
require('./routes/lib/passport.js');
app.use(passport.initialize());
app.use(passport.session());
app.use('/login', loginRouter); //define login route

Related

How do I fix this problem creating an Image object in MongoDB using ExpressJs, NodeJs, Handlebars, and Multer?

I am trying to build a website that allows a user to add a collectors item to the website. It has a form that requires certain fields to be filled out (I chose Funko Pop's). I have got everything working for the exception of having the image uploaded to the index.hbs page and into the MongoDB database.
Can anyone help? I think I am very close, but my terminal is throwing a Mongoose validator error (I'll show this at the end of the post)
The image seems to be sent to my "uploads" folder successfully, it just seems that there is some miscommunication happening with MongoDB because mongoose isn't happy.
Would anyone know what the issue is? And know how to fix it?
Thank you all for the help!
Here is my code:
Collection.js Controller/Route:
const express = require('express')
const router = express.Router()
const Collection = require('../models/collection')
const globalAuthFunction = require('./authenticationFunction')
const multer = require('multer')
// storage for multer
const storage = multer.diskStorage({
destination: function(err, file, callback){
callback(null, './public/uploads')
},
filename: function(req, file, callback){
callback(null, Date.now() + file.originalname)
}
})
const upload = multer({
storage: storage
})
router.get('/', (req, res) => {
Collection.find((err, collections) => {
if (err) {
console.log(err);
}
else {
res.render('collections/index', {
title: 'Collections',
collections: collections,
user: req.user
})
}
})
})
router.get('/create', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.find((err, collections) => {
if(err){
console.log(err)
}
else{
res.render('collections/create', {
title: 'Add Employer',
collections: collections,
user: req.user,
})
}
})
})
router.post('/create', upload.single('image'), globalAuthFunction.isAuthenticated, (req, res) => {
Collection.create(req.body, (err, newCollection) => {
if (err) {
console.log(err)
}
else {
res.redirect('/collections')
}
})
})
router.get('/edit/:_id', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.findById(req.params._id, (err, collection) => {
if(err){
console.log(err)
}
else{
res.render('collections/edit', {
title: 'Funko Pop Details',
collection: collection,
user: req.user,
image: req.file.filename
})
}
})
})
router.post('/edit/:_id', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.findByIdAndUpdate({ _id: req.params._id}, req.body, null, (err, collection) =>{
if(err){
console.log(err)
}else{
res.redirect('/collections')
}
})
})
router.get('/delete/:_id', globalAuthFunction.isAuthenticated, (req, res) => {
Collection.deleteOne({ _id: req.params._id}, (err) => {
if(err){
console.log(err)
}
else{
res.redirect('/collections')
}
})
})
module.exports = router
My create.hbs:
<h1>Add a Funko Pop to Your Collection</h1>
<form method="post" enctype="multipart/form-data">
<fieldset>
<label for="character" class="col-2">Character: *</label>
<input name="character" id="character" required />
</fieldset>
<fieldset>
<label for="mediaTitle" class="col-2">Move or Television Name: *</label>
<input name="mediaTitle" id="mediaTitle" required />
</fieldset>
<fieldset>
<label for="category" class="col-2">Category: *</label>
<input name="category" id="category" required />
</fieldset>
<fieldset>
<label for="popNumber" class="col-2">Funko Pop Number: *</label>
<input name="popNumber" id="popNumber" required />
</fieldset>
<fieldset>
<label for="specialtySticker" class="col-2">Specialty Sticker: </label>
<input name="specialtySticker" id="specialtySticker" placeholder="N/A if there is no sticker"/>
</fieldset>
<fieldset>
<label for="price" class="col-2">Price: *</label>
<input name="price" id="price" required />
</fieldset>
<fieldset>
<label for="releaseYear" class="col-2">Funko Pop Release Year: *</label>
<input name="releaseYear" id="releaseYear" required />
</fieldset>
<fieldset>
<label for="image" class="col-2">Upload Image:</label>
<input type="file" name="image" id="image" value="image"/>
</fieldset>
<button class="btn btn-primary offset-2">Save</button>
</form>
My index.hbs:
<h1>Funko Pop Collection</h1>
{{#if user}}
<a class="btn btn-secondary" href="/collections/create">Add a Funko Pop</a>
{{/if}}
<section class="row">
{{#each collections}}
<div class="card col-2 m-2">
<div class="card-body text-center h-100">
<img src="{{this.image}}"/>
<h5 class="card-title">{{this.character}}</h5>
<p>Funko Pop Title: {{this.mediaTitle}}</p>
<p>Category: {{this.category}}</p>
<p>Pop Number: {{this.popNumber}}</p>
<p>Specialty Sticker: {{this.specialtySticker}}</p>
<p>Value: ${{this.price}}</p>
<p>Year:{{this.releaseYear}}</p>
{{#if ../user}}
<div>
Edit
Delete
</div>
{{/if}}
</div>
</div>
{{/each}}
</section>
My app.js:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./controllers/index');
var usersRouter = require('./controllers/users');
const collections = require('./controllers/collections')
const auth = require('./controllers/auth')
const passport = require('passport')
const session = require('express-session')
const multer = require('multer')
var app = express();
// database connection to MongoDB
if (process.env.NODE_ENV !== 'production'){
require('dotenv').config()
}
app.use(session ({
secret: process.env.PASSPORT_SECRET,
resave: true,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
const User = require('./models/user')
passport.use(User.createStrategy())
// let passport read/write user data to/from session vars
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser())
const google = require('passport-google-oauth20').Strategy
passport.use(new google({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_CALLBACK_URL
},
(accessToken, refreshToken, profile, done) => {
User.findOrCreate({ oauthId: profile.id}, {
username: profile.displayName,
oauthProvider: 'Google',
created: Date.now()
}, (err, user) => {
return done(err, user)
})
}
))
const mongoose = require('mongoose');
const { access } = require('fs');
mongoose.connect(process.env.DATABASE_URL)
.then(
(res) => {
console.log('Connected to MongoDB')
}
).catch(() => {
console.log('Cannot connect to MongoDB')
})
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/collections', collections)
app.use('/auth', auth)
app.use('/', indexRouter);
app.use('/users', usersRouter);
// 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;
This is what my terminal is showing when I try and create a new Funko Pop Object in MongoDB:
It is saying there is an incorrect path or something. The image is uploading correctly to my "uploads" folder, it just seems to be having an issue with the database connection.
I thought it may be that the image type in my model was wrong, so I switched it to "Buffer" instead of "String", but it still showed me the same exact error. I have watched several tutorials, but they have set it up completely different than mine.
They seem to be using a something like this in there "post" function in there controllers:
let connection = new Connection({
title: request.body.title,
img: request.file.filename
}
I do not know enough about handlebars, MongoDB or Multer to be able to diagnose the issues that is happening. Any help would be greatly appreciated.
Thank you!
since you are using multer, change it from request.file.filename to request.file.path

localhost redirected you too many times in NodeJS and Express-session

i am following the tutorial on youtube the code is working fine on his computer but not running on my system.
i am getting error.
"This page isn't working at the momentlocalhost redirected you too many times.
To fix this issue, try clearing your cookies."
the '/' page is working fine when i have try to jump on /home page it doesn't work can anyone help where is the mistake actually? i have followed the tutorial and rewrite the code 5 times unfortunately every time i am getting the same error which is unexpected
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const TWO_HOUR = 1000 * 60 * 60 * 2
const {
PORT = 3000,
NODE_ENV = 'development',
SESS_NAME = 'sid',
SESS_SECRET = 'SADFSDF#*9SDF',
SESS_LIFETIME = TWO_HOUR
} = process.env
const IN_PROD = NODE_ENV === 'production'
const users = [
{id: 1, name: 'Asad', email: 'asad_gmail.com', password: '123'},
{id: 2, name: 'Abdullah', email: 'abdullah_gmail.com', password: '123'},
{id: 3, name: 'Shehroz', email: 'shehroz_gmail.com', password: '123'}
]
const app = express();
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(session({
name: SESS_NAME,
resave: false,
saveUninitialized: false,
secret: SESS_SECRET,
cookie:{
maxAge: SESS_LIFETIME,
sameSite: true,
secure: IN_PROD
}
}))
const redirectLogin = (req, res, next) => {
if(!req.session.userId){
res.redirect('/login')
} else{
next()
}
}
const redirectHome = (req, res, next) => {
if(!req.session.userId){
res.redirect('/home')
} else{
next()
}
}
app.get('/', (req, res) => {
const {userId} = req.session
//const userId = 1
res.send(`
<h1>Welcome!</h1>
${userId ? `
<a href='/home'>home</a>
<form method='post' action='/logout'>
<button>Logout</button>
</form>
` : `
<a href='/login'>Login</a>
<a href='/register'>Register</a>
`}
`)
})
app.get('/home', redirectLogin, (req, res) => {
res.send(`
<h1>Home</h1>
<a href='/'>Main</a>
<ul>
<li>Name:</li>
<li>Email:</li>
</ul>
`)
})
app.get('/login', redirectHome, (req, res) => {
res.send(`
<h1>Login</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='email' required />
<input type='password' name='password' placeholder='password' required />
<input type='submit' />
</form>
<a href='/register'>Register</a>
`)
})
app.get('/register', redirectHome, (req, res) => {
res.send(`
<h1>Register</h1>
<form method='post' action='/register'>
<input type='text' name='name' placeholder='name' required />
<input type='email' name='email' placeholder='email' required />
<input type='password' name='password' placeholder='password' required />
<input type='submit' />
</form>
<a href='/login'>Login</a>
`)
})
app.post('/login', redirectHome, (req, res) => {
const {email, password } = req.body
if(email && password) {
const user = users.find(user => user.email === email && user.password === password)
if(user) {
req.session.userId = user.id
return res.redirect('/home')
}
}
res.redirect('/login')
})
app.post('/register', redirectHome, (req, res) => {
const {name, email, password } = req.body
if(name && email && password) {
const exists = users.some(
user => user.email === email
)
if(!exists) {
const user = {
id: users.length + 1,
name,
email,
password
}
users.push(user)
req.session.userId = user.id
return res.redirect('/home')
}
}
res.redirect('/register')
})
app.post('/logout', redirectLogin, (req, res) => {
req.session.destroy(err => {
if(err){
return res.redirect('/home')
}
res.clearCookie(SESS_NAME)
res.redirect('/login')
})
})
app.listen(PORT, () => console.log(
`http://localhost:${PORT}`
))
// npm run dev
It is because there is a loop redirection path. If you try consolelog("Textsomething") at redirectHome and redirectLogin if statement, you will find a redirect loop.
One solution is to modify the logic of the redirection function, you can delete the exclamation point in the redirectHome if statement because it requires a user ID before the / home page can be accessed, etc.

Express server communicating with React App

I am trying to redirect to my React App after authenticating the login.
But its not working, don't know why.
React App at port 3000
Server at port 3001
I am routing to server on login submit -> server authenticate using passport -> it should redirect to React App route '/secured'. Instead it is showing GET http://localhost:3001/secured 404 (Not Found)
It is routing to the server address. How to resolve this?
Authentication is working fine. I have checked it all using postman.
EXPRESS SERVER
//middleware
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(cors({
origin: 'http://localhost:3000', //location of frontend app (react app here)
credentials: true,
}))
app.use(expressSession({
secret: 'secret',
resave: true,
saveUninitialized: true,
}))
app.use(cookieParser('secret'))
app.use(passport.initialize())
app.use(passport.session())
require('./models/passport-config')(passport)
// routes
app.get('/', (req, res) => {
res.send('Home route')
})
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err) }
if (!user) { return res.redirect('/') }
req.logIn(user, (err) => {
if (err) { return next(err) }
return res.redirect('/secured')
})
})(req, res, next)
})
app.post('/register', (req, res) => {
console.log(req.body)
})
app.get('/user', (req, res) => {
res.send(req.user)
})
// server init
app.listen(3001, () => {
console.log('serving at http://localhost:3001...')
})
"REACT APP - App.js
import './App.css';
import Register from './components/Register';
import Login from './components/Login';
import {BrowserRouter, Route} from 'react-router-dom'
function App() {
return (
<div className="App">
<BrowserRouter>
<div>
<Route exact path="/" component={Login} />
<Route path="/secured" component={Register} />
</div>
</BrowserRouter>
</div>
);
}
export default App;
REACT APP - Login.js
import React, { Component } from 'react'
import "./login.css"
import axios from 'axios'
class Login extends Component {
constructor(props) {
super(props)
this.state = {
username: null,
password: null,
}
}
handleChange = (event) => {
event.preventDefault()
this.setState({
...this.state,
[event.target.name]: event.target.value,
})
}
handleSubmit = (event) => {
event.preventDefault()
axios({
method: "post",
data: this.state,
withCredentials: true,
url: 'http://localhost:3001/login'
})
// .then(this.getData())
}
getData = () => {
axios({
method: "get",
data: this.state,
withCredentials: true,
url: 'http://localhost:3001/user'
}).then(res => {
this.setState({
username: res.data['0'].username,
email: res.data['0'].email,
password: null
});
})
}
render() {
return (
<div >
<div>
<form id='login' onSubmit={this.handleSubmit}>
<div>
<h3>Login</h3>
</div>
<div >
<div >
<input onChange={this.handleChange} id="icon_prefix" type="text" name='username' />
<label htmlFor="icon_prefix">Username</label>
</div>
</div>
<div>
<div >
<input onChange={this.handleChange} id="icon_prefix" type="password" name='password' />
<label htmlFor="icon_prefix2">Password</label>
</div>
</div>
<div >
<div >
<input type='submit' />
</div>
</div>
</form>
<div>
Already a member? Register here
</div>
</div>
</div>
)
}
}
export default Login
Inside your handleSubmit function in your <Login /> component, you should add the .then() callback, check the response for error/success and then either show an error to the user in the UI or use React Router History to push or replace the current route.
Another option would maybe be to store a state variable in your <Login /> component, like this.state.isAuthenticated which you could then check in your render() method and choose to return a React Router Redirect like:
render() {
if (this.state.isAuthenticated) {
return <Redirect to="/somewhere/else" />
}
return (
<div>
...
</div>
)
}

NodeJS csrf protection gives ForbiddenError invalid csrf token only on one POST request form

I have been unsuccessfully trying to find a solution on Google for the past several hours for the following issue:
I have csurf set up and working well. It works for POST requests related to signing up/in users. I am trying to create a form in the user profile, that updates the user's data, but when I hit submit, I get ForbiddenError: invalid csrf token.
On further testing, the csrt token is created on the profile page, but for some reason, it is invalid.
(I have only recently picked up programming, I'm willing to provide additional information if I have missed something.)
Tools used:
Node.js v10.16.3
Express v4.17.1
ejs v2.7.1
csurf v1.10.0
Express session v1.16.2
Passport v^0.4.0
cookie-parser 1.4.4
body-parser v1.19.0
My app.js
let express = require("express"),
app = express(),
bodyParser = require("body-parser"),
cookieParser = require('cookie-parser'),
session = require("express-session"),
mongoose = require("mongoose"),
passport = require("passport"),
flash = require('connect-flash'),
validator = require('express-validator'),
LocalStrategy = require("passport-local"),
csrf = require('csurf'),
csrfProtection = csrf({ cookie: true }),
MongoStore = require('connect-mongo')(session);
let indexRoutes = require('./routes/index');
let userRoutes = require('./routes/user');
let User = require("./models/user");
// APP CONFIGURATION
mongoose.connect("mongodb://localhost:27017/azax", { useNewUrlParser: true, useUnifiedTopology: true, }).then(() => {
console.log("Connected to MongoDB");
}).catch((error) => {
console.log("Something is wrong...");
});
require('./config/passport');
// View engine setup
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/public"));
// Initial setup
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(validator());
// Session setup
app.use(cookieParser());
app.use(session({
secret: 'somesecretforbytox',
resave: false,
saveUninitialized: false
}));
app.use(flash());
// Initialize passport
app.use(passport.initialize());
app.use(passport.session());
app.use(csrf());
// CSRF
app.use(function (req, res, next) {
var token = req.csrfToken();
res.cookie('XSRF-TOKEN', token);
res.locals.csrfToken = token;
next();
});
app.use(function (req, res, next) {
res.locals.currentUser = req.user;
res.locals.session = req.session;
next();
});
// ======================
// Connect to route files
// ======================
app.use('/user', userRoutes);
app.use(indexRoutes);
app.listen(3033, function () {
console.log("Listening at port 3033...");
});
My passport.js:
let passport = require('passport');
let User = require('../models/user');
let LocalStrategy = require('passport-local').Strategy;
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function (req, email, password, done) {
req.checkBody('username', 'Invalid username').notEmpty();
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty().isLength({ min: 4 });
let errors = req.validationErrors();
if (errors) {
let messages = [];
errors.forEach(function (error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({ 'email': email }, function (err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, { message: 'Вече има акаунт с този имейл.' })
}
let username = req.body.username;
let newUser = new User();
newUser.username = username;
newUser.email = email;
newUser.password = newUser.encryptPassword(password);
newUser.country = 'България';
newUser.save(function (err, result) {
if (err) {
return done(err);
}
return done(null, newUser);
});
});
}));
passport.use('local-signin', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function (req, email, password, done) {
// req.checkBody('username', 'Invalid username').notEmpty();
req.checkBody('email', 'Invalid email').notEmpty();
req.checkBody('password', 'Invalid password').notEmpty();
let errors = req.validationErrors();
if (errors) {
let messages = [];
errors.forEach(function (error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({ 'email': email }, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { message: 'Акаунтът не е намерен.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Грешна парола.' });
}
return done(null, user);
});
}));
HTML...:
<form action="/user/profile" method="POST" class="form-validate form-horizontal" enctype="multipart/form-data">
<fieldset>
<legend>Edit address</legend>
<!-- email -->
<div class="control-group">
<div class="control-label">
<label id="jform_email1-lbl" for="jform_email" class="hasPopover required" title="" data-content="Enter new email address." data-original-title="Email Address">
Email<span class="star"> *</span></label>
</div>
<div class="controls">
<input type="email" name="email" class="validate-email required" id="jform_email" value="<%= (typeof currentUser.email != 'undefined' ? currentUser.email : '') %>" size="30" autocomplete="email" required aria-required="true">
</div>
</div>
<!-- name -->
<div class="control-group">
<div class="control-label">
<label id="jform_fname-lbl" for="jform_fname" class="hasPopover required" title="" data-content="Enter new name." data-original-title="Name">
Name<span class="star"> *</span></label>
</div>
<div class="controls">
<input type="text" name="firstName" id="jform_fname" value="<%= (typeof currentUser.firstName != 'undefined' ? currentUser.firstName : '') %>" class="required" size="30" required aria-required="true">
</div>
</div>
</fieldset>
<div class="form-actions">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit" class="btn btn-primary validate">
<span>Save</span>
</button>
<a class="btn" href="/" title="Cancel">Cancel</a>
</div>
</form>
user.js:
let express = require('express'),
router = express.Router(),
csrf = require('csurf'),
csrfProtection = csrf(),
passport = require('passport');
router.use(csrfProtection);
let User = require("../models/user");
// user profile
router.get("/profile", isLoggedIn, csrfProtection, function (req, res) {
res.render("user/profile", { csrfToken: req.csrfToken(), currentUser: req.user });
});
router.post('/profile', (req, res) => {
updateRecord(req, res);
res.redirect('/profile');
});
// update user data
function updateRecord(req, res) {
User.findOne({ _id: req.user.id }, (err, doc) => {
doc.name = req.body.name;
doc.save(function (err, doc) {
});
});
}
router.get("/profile/edit", isLoggedIn, csrfProtection, function (req, res) {
res.render("user/edit", { csrfToken: req.csrfToken(), currentUser: req.user });
});
// sign up form works with csrf
// signup form
router.get("/signup", csrfProtection, function (req, res) {
let messages = req.flash('error');
res.render("user/signup", { csrfToken: req.csrfToken(), messages: messages, hasErrors: messages.length > 0 });
});
// ... more routes
module.exports = router;
// middleware
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/user/login');
}
What worked for me was adding the below hidden field to every form:
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
and sending the token to every get request to the template page displaying the form.
{csrfToken: req.csrfToken()}
like
router.get('/user/login',function(req,res){
res.render('pages/login', {csrfToken: req.csrfToken()});
})
this fixed the error in whole app.

how to create session using node.js?

I want to create session for my pages, when give a url like http://localhost:3000/pages/profile it will goes to that page without logged in. What should i do now to fix this problem.
node.js
module.exports = function(app, express, passport){
var router = express.Router();
passport.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password'},
function(username, password, done) {
User.findOne({ name : username}, function(err, user) {
if (!user){
return done(null, false,{message: 'Incorrect username' });
}
if(user){
var validPassword = user.comparePassword(password);
if(!validPassword){
return done(null, false,{message: 'Incorrect password' });
}
}
return done(null, user);
});
}
));
router.post('/pages/auth/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (user === false) {
console.log("login error ");
return res.json({
success:false,
message: info.message,
});
} else {
console.log("login success");
return res.json({
success:true,
//message: 'Login Success',
});
}
})(req, res, next);
});
}
controller
function LoginController($http, $location, Auth, $rootScope)
{
var vm = this;
vm.submitPost = function(userData){
$http({
url: 'http://localhost:7200/api/pages/auth/login',
method: 'POST',
data: userData
}).then(function(res) {
if(res.data.success){
$location.path('/pages/profile');
} else {
vm.message=res.data.message;
$location.path('/pages/auth/login');
}
}, function(error) {
console.log(error);
alert(error.data);
});
};
}
login.html
<form name="loginForm">
<div class="alertmessage" >{{vm.message}}</div>
<md-input-container flex md-no-float>
<input ng-model="vm.form.username" placeholder="Username" translate
translate-attr-placeholder="LOGIN.USERNAME" name="username" required="true">
<div ng-messages="loginForm.username.$error" ng-show="loginForm.username.$touched">
<div ng-message="required">This field is required</div>
</div>
</md-input-container>
<md-input-container flex md-no-float>
<input ng-model="vm.form.password" type="password" placeholder="Password" translate
translate-attr-placeholder="LOGIN.PASSWORD" name="password" required="true">
<div ng-messages="loginForm.password.$error" ng-show="loginForm.password.$touched">
<div ng-message="required">This field is required</div>
</div>
</md-input-container>
<div class="remember-forgot-password" layout="row" layout-sm="column"
layout-align="space-between center">
<md-checkbox class="remember-me" ng-model="data.cb1" aria-label="Remember Me">
<span translate="LOGIN.REMEMBER_ME">Remember Me</span>
</md-checkbox>
<a ui-sref="app.pages_auth_forgot-password" class="forgot-password md-accent-color"
translate="LOGIN.FORGOT_PASSWORD">Forgot Password?</a>
</div>
<md-button class="md-raised md-accent" aria-label="LOG IN" translate="LOGIN.LOG_IN"
translate-attr-aria-label="LOGIN.LOG_IN"
ng-click="vm.submitPost(vm.form);">
LOG IN
</md-button>
</form>
I have a Node.js project with sessions and in my index.js I have the following:
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
app.use(session({
secret: config('session_secret'),
store: new MongoStore({ mongooseConnection: mongoose.connection }),
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
If you don't use MongoDB you can drop the "store" element. Then it uses the default store which is MemoryStore.
To prevent non-authenticated users accessing a page you can do this:
router.get('/secure-page', isLoggedIn, function(req, res) {
res.json({secure: "page"});
});
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated()) {
return next();
}
else {
// redirect to login page.
res.redirect('/login');
}
}
One way is storage values the session with express session, and then interceptade each route with middleware as verify if user is logged or not, somelike this...
Middleware autentic:
module.exports = function(req, res, next) {
if(!req.session.user) {
return res.redirect('/');
}
return next();
};
req.session.user is a variable create in session in login controller for storage username.
And intercept the route, verifying with user is logged:
...
app.get('pages/profile', autentic, controller.function);
...
If user is not logged will redirect to home page.
But, I suggest you to use passport.js:
Passport is authentication middleware for Node.js. Extremely flexible
and modular, Passport can be unobtrusively dropped in to any
Express-based web application. A comprehensive set of strategies
support authentication using a username and password, Facebook,
Twitter, and more.
See the docs for learn how to use and search here in the stack overflow too.

Resources