passport.js .register() function goes in infinite loop - javascript

while submitting the post request it does not redirect me to the failureRedirect route, nor to the SuccessRedirect one, instead, the web page enters into an endless loop. Why is this happening.
It has two files
app.js:
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const ejsmate = require('ejs-mate');
const session = require('express-session');
const flash= require('connect-flash');
const methodOverride = require('method-override');
const passport= require('passport');
const LocalStrategy= require('passport-local');
const User= require('./models/user');
const ExpressError = require('./Utilities/ExpressError');
const campgroundRoutes=require('./Routes/campgrounds');
const reviewRoutes=require('./Routes/review');
const userRoutes=require('./Routes/User');
mongoose.connect('mongodb://localhost:27017/yelp-camp');
const db = mongoose.connection;
db.on('error', console.error.bind(console, "connection error:"));
db.once('open', () => {
console.log("open connection");
});
const app = express();
app.engine('ejs', ejsmate)
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')))
const sessionConfig={
secret:'thisshouldbeabettersecret',
resave: false,
saveUninitialized: true,
cookie:
{
httpOnly:true,
expires:Date.now+1000*60*60*24*7,
maxAge:1000*60*60*24*7
}
}
app.use(session(sessionConfig))
app.use(flash())
app.use(passport.initialize())
app.use(passport.session())
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser()) //deserializeUser
app.use((req, res, next) => {
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
next();
})
app.use('/',userRoutes)
app.use('/campgrounds',campgroundRoutes);
app.use('/campgrounds/:id/reviews',reviewRoutes)
app.get('/', (req, res) => {
console.log('hi on server ');
res.render('home')
});
app.all('*', (req, res, next) => {
next(new ExpressError('Page Not Found', 404));
})
app.use((err, req, res, next) => {
// { const {statusCode=500,message="SomThing went wrong "} = err;
// res.status(statusCode).send(message)
if (!err.message) err.message = "Problem Occurs Man"
res.render('Error', { err })
next();
})
app.listen(3000, () => {
console.log('listening on port 3000');
});
User.js:
const express=require('express');
const router=express.Router();
const catchAsync=require('../Utilities/catchAsync')
const User = require('../models/user');
const passport = require('passport');
// const LocalStrategy= require('passpi')
router.get('/register', (req, res) => {
res.render('users/register')
});
router.post('/register', catchAsync( async (req, res) => {
try {
const {usermail,username,userpassword}=req.body;
console.log(req.body);
const user= new User({usermail,username});
console.log(req.body);
const registerdUser= await User.register(user,userpassword);
console.log(req.body);
console.log(registerdUser);
req.flash('success','Welcome to YelpCamp');
req.redirect('/campgrounds')
} catch (err) {
req.flash('error', err.message);
res.redirect('/register')
}
}));
router.get('/login', (req, res) => {
res.render('users/login')
});
router.post('/login',passport.authenticate('local',{failureFlash: true,failureRedirect:'/login'}),(req,res) => {
req.flash('success', 'Successfully logged in!');
res.redirect('/campgrounds')
});
module.exports = router;
I have searched everywhere and tried all the available possible solutions but nothing is solving this.

Related

Node express-session w/ passport v0.6.0 'Login sessions require session support.'

Passport is being used to log in via Discord in order to access a Dashboard. Main problem is the logout though, worked before passport v.0.6.0, but now it doesn't. req.logout(); now needs a callback function (see here) to work, but when I now access /logout
on the website I get Error: Login sessions require session support. Did you forget to use 'express-session' middleware?
settings.json
{
"website": {
"support": "https://discord.gg/xxxxxxx",
"domain": "http://localhost:5991"
},
"config": {
"port": 5991,
"callback": "http://localhost:5991/callback",
"clientID": "botId",
"secret": "OAuth2 Secret"
}
}
index.js
const express = require('express');
const url = require('url');
const path = require('path');
const ejs = require('ejs');
const passport = require('passport');
const bodyParser = require('body-parser');
const Strategy = require('passport-discord').Strategy;
const settings = require('./settings.json');
const logger = require('silly-logger');
const favicon = require('serve-favicon');
module.exports = client => {
// website config backend
const app = express();
const session = require('express-session');
const MemoryStore = require("memorystore")(session);
// middleware
app.use(session({
secret: `superdupersecret`,
store: new MemoryStore({ checkPeriod: 86400000 }),
resave: false,
saveUninitialized: false,
}));
app.use(favicon(path.join(__dirname, 'public/assets', 'favicon.ico')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
app.use(express.json());
app.use(express.urlencoded({
extended: true,
}));
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "./views"));
// loading public
app.use('/public', express.static(__dirname + '/public'));
app.use(passport.initialize());
app.use(passport.session());
// initialize discord login
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((obj, done) => done(null, obj));
passport.use(new Strategy({
clientID: settings.config.clientID,
clientSecret: settings.config.secret,
callbackURL: settings.config.callback,
scope: ["identify", "guilds", "guilds.join"],
},
(accessToken, refreshToken, profile, done) => {
process.nextTick(()=>done(null, profile));
},
));
app.get("/login", (req, res, next) => {
if (req.session.backURL) {
// eslint-disable-next-line no-self-assign
req.session.backURL = req.session.backURL;
} else if (req.headers.referer) {
const parsed = url.parse(req.headers.referer);
if (parsed.hostname == app.locals.domain) {
req.session.backURL = parsed.path;
}
} else {
req.session.backURL = "/";
}
next();
}, passport.authenticate("discord", { prompt: null }));
app.get("/callback", passport.authenticate("discord", { failureRedirect: "/" }), async (req, res) => {
res.redirect("/dashboard");
});
app.get("/logout", (req, res, next) => {
req.session.destroy(() => {
req.logout(function(err) {
if (err) { return next(err); }
res.redirect("/");
});
});
});
const http = require('http').createServer(app);
http.listen(settings.config.port, () => {
logger.success(`Website is online on port ${settings.config.port}, ${settings.website.domain}`);
});
};
EDIT:
I found two ways that end the session:
app.get("/logout", (req, res, next) => {
req.logout(function(err) {
if (err) { return next(err); }
res.redirect("/");
});
});
app.get("/logout", (req, res, next) => {
req.session.destroy((err) => {
if (err) { return next(err); }
res.redirect("/");
});
});

login authorization problem, does not pass the token

I am trying to make a login system with authorization, unfortunately the token is not transferred.
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const urlencodedParser = bodyParser.urlencoded({ extended: false });
const mysql = require('mysql');
const validator = require('validator');
const jwt = require('jsonwebtoken');
require('dotenv').config().ACCESS_TOKEN;
const ACCESS_TOKEN = process.env.ACCESS_TOKEN;
const app = express();
app.use(express.json());
const publicDirectoryPath = path.join(__dirname, '../public');
console.log(publicDirectoryPath);
app.use(express.static(publicDirectoryPath));
function generateAccessToken(username) {
return jwt.sign(username, ACCESS_TOKEN, { expiresIn: '1800s' });
}
app.post('/login', urlencodedParser, (req, res) => {
res.get(req.body.username + req.body.password);
const token = generateAccessToken({ username: req.body.username });
res.json(token);
});
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization']
const token = authHeader && authHeader.split(' ')[1]
console.log(token)
if (token == null) return res.sendStatus(401)
jwt.verify(token, ACCESS_TOKEN, (err, user) => {
console.log(err)
if (err) return res.sendStatus(403)
req.user = user
next()
})
}
app.get('/admin', authenticateToken, (req, res) => {
res.send("admin panel");
})
const port = 3000;
app.listen(port, () => {
console.log(`Server run: http://localhost:${port}`);
})
wants him to be redirected to the admin panel after clicking the login button. However, I am stuck at this stage and do not know what to do next:
enter image description here
You should pass the token to the next route
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const urlencodedParser = bodyParser.urlencoded({ extended: false });
const mysql = require('mysql');
const validator = require('validator');
const jwt = require('jsonwebtoken');
require('dotenv').config().ACCESS_TOKEN;
const ACCESS_TOKEN = process.env.ACCESS_TOKEN;
const app = express();
app.use(express.json());
const publicDirectoryPath = path.join(__dirname, '../public');
console.log(publicDirectoryPath);
app.use(express.static(publicDirectoryPath));
function generateAccessToken(username) {
return jwt.sign(username, 'ACCESS_TOKEN', { expiresIn: '1800s' });
}
app.post('/login', urlencodedParser, (req, res) => {
res.get(req.body.username + req.body.password);
const token = generateAccessToken({ username: req.body.username });
res.redirect(`/admin?token=${token}`);
});
function authenticateToken(req, res, next) {
token = req.query.token;
if (token == null) return res.sendStatus(401);
jwt.verify(token, 'ACCESS_TOKEN', (err, user) => {
console.log(err);
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
app.get('/admin', authenticateToken, (req, res) => {
res.send('admin panel');
});
const port = 3000;
app.listen(port, () => {
console.log(`Server run: http://localhost:${port}`);
});

Problem with nodejs static route and files

In my project I have a report hat is reachable with index.html
But this is private and I want to protect / limit access with my node app. for this I use
app.use('/allure', express.static(path.join(__alluredir , 'allure-report/')));
Then I use for bugging purpose
app.all('/allure/*', function(req, res, next) {
console.log("catched allure query");
next(); // allow the next route to run
});
But the index.html is still reachable with localhost:8080/allure/index.hmtl and also just with localhost:8080/allure/ without an console output. This confuse a lot. Anybody has an idea how to hinder access the index.html without logged in? (Is use passport)
my whole app.js file is:
const express = require('express');
const app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
var bodyParser = require('body-parser');
const fs = require('fs');
const path = require('path');
var favicon = require('serve-favicon')
const { allureGenerator } = require('./ops/copyalluredata');
app.set('socketio', io);
//app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json({ type: 'application/json' }));
app.use(bodyParser.urlencoded({
parameterLimit: 100000,
limit: '50mb',
extended: true
}));
var appDir = path.dirname(require.main.filename);
global.__basedir = appDir;
global.__alluredir = process.env.REPORT_DIR_ENV;
fs.readFile(path.join(appDir, '/config.xml'), (err, data) => {
if (err) throw err;
myConfigData = JSON.parse(data);
process.env.BROWSERSTACK_USERNAME = myConfigData.browserstackid;
process.env.BROWSERSTACK_ACCESS_KEY = myConfigData.browserstackkey;
process.env.BROWSERSTACK_DISPLAY_RESOLUTION="1600x1200";
console.log('config gelesen');
});
//Diese Funktion schreibt die benötigten Dateien in den allure Modul Ordner damit das Logo verwendet wird.
allureGenerator();
// Passport Config
require(path.join(appDir, '/config/passport'))(passport);
// DB Config
var db = '';
if (process.env.NODE_ENV == 'home') {
db = require(path.join(appDir, '/config/keys')).mongoURI;
console.log('keys');
}else{
db = require(path.join(appDir, '/config/keys_local')).mongoURI;
console.log('keys_local');
}
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
app.use('/allure', express.static(path.join(__alluredir , 'allure-report/')));
app.use(express.static(appDir));
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.set('views', path.join(appDir, '/views'));
app.use(
session({
secret: 'secret',
resave: true,
saveUninitialized: true
})
);
app.use(favicon(path.join(__dirname, 'css', 'fvicon.ico')))
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
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');
next();
});
// Routes
app.use('/', require('./routes/index.js'));
app.use('/users', require('./routes/users.js'));
app.use('/cases', require('./routes/cases.js'));
app.use('/tcafe', require('./routes/tcafe.js'));
app.use('/imgtest', require('./routes/imgtest.js'));
app.use('/rapitest', require('./routes/restapitest.js'));
io.on('connection', function(socket){
console.log('a user connected');
});
app.all('/allure/*', function(req, res, next) {
console.log("catched allure query");
next(); // allow the next route to run
});
app.use((req, res, next) => {
next({
status: 404,
message: 'Not Found',
});
});
app.use((err, req, res, next) => {
if (err.status === 404) {
return res.status(400).render('404',{ layout: 'system.ejs' });
}
if (err.status === 500) {
return res.status(500).render('500');
}
next();
});
const PORT = process.env.PORT || 8080;
http.listen(PORT, console.log(`Server started on port ${PORT}`));
You can use something like this Or just use somemiddleware-
app.use('/allure', function(req,res,next){
if(<authenticate check>){ // some kind of authenticate check
return express.static(path.join(__dirname, 'allure'));
} else {
<Any error you want to show>
}
});
OR
app.use('/allure',<Auth Middlewarae> , express.static(path.join(__dirname, 'allure')));

Username entries all come out as 'null' in mongodb nodejs

I'm getting started in node.js and trying to create a user authentication system for my web application. I am watching a tutorial on YouTube and have followed every step through. When it comes to actually registering my user. the username entry in the collecting comes out as null. I'm not sure why this is happening, and I'm a rookie to javascript and node js. I am using passport, express and mongodb modules.
this is the video i am watching 'https://www.youtube.com/watch?v=m2ZzRZemc98'
If anyone knows how to fix my issue, please respond
Thanks
This is my main app.js
var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");
const MongoClient = require("mongodb").MongoClient;
const passport = require("passport");
const Strategy = require("passport-local").Strategy;
const session = require("express-session");
const flash = require("connect-flash");
const authUtils = require("./utils/auth");
const hbs = require("hbs");
var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");
const authRouter = require("./routes/auth");
var app = express();
//Connet to MongoDB database
MongoClient.connect("mongodb://localhost", (err, client) => {
if (err) {
throw err;
}
const db = client.db("user-profiles");
const users = db.collection("users");
app.locals.users = users;
});
//Passport streategy
passport.use(
new Strategy((username, passport, done) => {
app.locals.users.findOne({ username }, (err, user) => {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
if (user.password != authUtils.hashPassword(password)) {
return done(null, false);
}
return done(null, user);
});
})
);
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
done(null, { id });
});
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "hbs");
hbs.registerPartials(path.join(__dirname, "views/partials"));
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(
session({
secret: "session secret",
resave: false,
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use((req, res, next) => {
res.locals.loggedIn = req.isAuthenticated();
next();
});
app.use("/", indexRouter);
app.use("/users", usersRouter);
app.use("/auth", authRouter);
// 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 my auth.js
const router = express.Router();
const authUtils = require("../utils/auth");
const passport = require("passport");
router.get("/login", (req, res, next) => {
const messages = req.flash();
res.render("login", { messages });
});
router.post(
"/login",
passport.authenticate("local", {
failureRedirect: "/auth/login",
failureFlash: "Wrong username or password"
}),
(req, res, next) => {
res.redirect("/users");
}
);
router.get("/register", (req, res, next) => {
const messages = req.flash();
res.render("register", { messages });
});
router.post("/register", (req, res, next) => {
const registrationParams = req.body;
const users = req.app.locals.users;
const payload = {
username: registrationParams.username,
password: authUtils.hashPassword(registrationParams.password)
};
users.insertOne(payload, err => {
if (err) {
req.flash("error", "User account already exists");
} else {
req.flash("success", "User account was registered succesfully");
}
res.redirect("/auth/register");
});
});
router.get("/logout", (req, res, next) => {
req.session.destroy();
res.redirect("/");
});
module.exports = router;
I fixed my error, it was a mistake i made in the handlebars file, i put the input name as none the class of form-control and then named it again. Obviously the js looked at the first name and not the second name

Nodejs router order

I'm using:
express 4.14
node 7.0+
session 1.14+
I created Nodejs project with webstorm:
app.js
var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var user = require('./routes/user');
var app = express();
var check = function() {
!req.session.status ? res.redirect('/user/login') : next();
}
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({secret: "inline", resave: false, saveUninitialized: true, status: false}));
app.use('/', check, require('./routes/index'));
app.use('/user', require('./routes/user'));
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
user.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/login', function(req, res, next) {
res.render('login');
});
module.exports = router;
When I request to localhost:3000, the page prompt me that "too many redirects', now the url is localhost:3000/user/login?
What's my problem?
fix:
var check = function(req, res, next) {
!req.session.status ? res.redirect('/user/login') : next();
}
But I'll write more beautiful solution for You, hope You'll get in idea:
app.js:
app.use(require('./routes'));
routes folder:
routes/
|- index.js
|- common/
|- auth.js
|- root/
|- index.js
|- posts.js
|- backend/
|- index.js
|- posts.js
...
1) routes/index.js :
const
express = require('express'),
router = express.Router();
// guarded routes
function guardFn(req, res, next) {
let authenticated = req.session && req.session.authenticated === true;
authenticated ? next() : res.redirect('/auth');
}
router.use('/backend', guardFn, require('./backend'));
// public routes
router.use('/auth', require('./common/auth'); // for auth purposes
router.use('/', require('./root')); // for routes that starts from /, try not to rewrite /backend, /auth
module.exports = router;
2) routes/common/auth :
const
express = require('express'),
router = express.Router();
mongoose = require('mongoose'),
User = mongoose.model('user');
router.get('/', (req, res) => {
res.render('common/auth');
});
router.post('/', (req, res) => {
User
.findOne({
username: req.body.username,
password: req.body.password
})
.exec((err, user) => {
if(err) {
console.error(err);
return res.status(500).send('System error! Try again later');
}
if(!user) return res.redirect('back');
req.session.user = user._id;
req.session.authenticated = true;
res.redirect('/backend');
});
});
function logout(req, res, next) {
delete req.session.user;
req.session.authenticated = false;
next();
}
router.delete('/auth', logout, (req, res) => res.send({success: true}));
router.get('/auth/destroy', logout, res => res.redirect('/auth'));
module.exports = router;
3) routes/root/index.js :
const
express = require('express'),
router = express.Router();
router.get('/', (req, res) => {
res.render('site/welcome');
});
module.exports = router;
4) routes/root/posts.js :
const
express = require('express'),
router = express.Router(),
mongoose = require('mongoose'),
Post = mongoose.model('post');
router.get('/', (req, res) => {
Post
.find()
.skip((req.query.page-1)*10)
.limit(10)
.exec((err, posts) => {
res.render('site/posts/list', {posts});
});
});
router.get('/:id', (req, res) => {
Post
.findById(req.params.id)
.exec((err, post) => {
if(err) {
console.error(err);
return res.status(500).send('System error! Try again later');
}
res.render('site/posts/show', {post});
});
});
module.exports = router;
5) routes/backend/index.js :
const
express = require('express'),
router = express.Router();
router.get('/', (req, res) => {
res.render('backend/dashboard');
});
module.exports = router;
6) routes/backend/posts.js :
const
_ = require('lodash'),
express = require('express'),
router = express.Router(),
mongoose = require('mongoose'),
Post = mongoose.model('post');
router.get('/', (req, res) => {
Post
.find()
.skip((req.query.page-1)*50)
.limit(50)
.exec((err, posts) => {
res.render('backend/posts/list', {posts});
});
});
router.get('/:id', (req, res) => {
Post
.findById(req.params.id)
.exec((err, post) => {
if(err) {
console.error(err);
return res.status(500).send('System error! Try again later');
}
res.render('backend/posts/show', {post});
});
});
function updatePost(id, data, callback) {
Post
.findById(_id)
.exec((err, post) => {
if(err) return callback(err);
if(!post) return callback('not found');
post = _.extend(post, data);
post.save(() => callback(null, post));
});
}
router.put('/:id', (req, res) => {
updatePost(req.params.id, req.body, (err, post) => {
if(err) return res.status(500).send({success: false, err});
res.send({success: true, post});
});
});
router.post('/:id', (req, res) => {
updatePost(req.params.id, req.body, (err, post) => {
if(err) return res.status(500).send(err);
res.redirect('/backend/posts');
});
});
function createPost(data, callback) {
let post = new Post();
post = _.extend(post, req.body);
post.save((err) => callback(err, post));
}
router.post('/', (req, res) => {
createPost(req.body, (err, post) => {
if(req.xhr) {
if(err) return res.status(500).send({success: false, err});
return res.send({success: true, post});
}
if(err) return res.status(500).send(err);
res.redirect('/backend/posts');
});
});
module.exports = router;
As I understand it, app.use('/', ...) will match all requests which is why your check method is being called for all requests.
More good info here.
From Express docs:
A route will match any path that follows its path immediately with a
“/”.
For example: app.use("/apple", ...) will match “/apple”,
“/apple/images”, “/apple/images/news”, and so on.
I would suggest refactoring to:
var check = function(req, res, next) {
if (!req.session.status && req.path != '/user/login') {
res.redirect('/user/login');
}
else {
next();
}
}
app.use(check);
app.use('/', index);
app.use('/user', users);
So check will execute for all requests but only redirect if the request session is falsey and request path doesn't match /user/login
Keep in mind your code will fail if req.session is not set...

Categories

Resources