I have installed express-session yet i'm getting Error: Login sessions require session support. Did you forget to use express-session middleware?
the passport.authenticate doesn't works because of this
index.js
const ejs = require("ejs");
const url = require("url");
const session = require("express-session");
const cookieParser = require('cookie-parser')
const flash = require('connect-flash');
const toastr = require('express-toastr');
const Profile = require('./models/Profile.js');
const passport = require("passport");
const { customAlphabet } = require('nanoid');
const express = require("express"),
path = require('path')
const app = express();
const port = 3000;
const { Notyf } = require('notyf')
const { connect } = require('mongoose');
const LocalStrategy = require('passport-local');
const MemoryStore = require("memorystore")(session);
const methodOverride = require('method-override')
connect(process.env.mongodb);
const initializePassport = require('./utils/passport-config.js')
initializePassport(
passport,
email => Profile.find({ email_id: email }),
id => Profile.find({ user_id: email })
)
var bodyParser = require('body-parser');
app.use(cookieParser());
app.use(
session({
store: new MemoryStore({ checkPeriod: 86400000 }),
secret: "##%#&^$^$%#$^$&%#$%##$%$^%&$%^#$%##$%#E%#%#$FEErfgr3g#%GT%536c53cc6%5%tv%4y4hrgrggrgrgf4n",
resave: false,
saveUninitialized: false,
}),
);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(toastr());
app.use('/assets', express.static(path.join(__dirname, 'assets')))
app.use('/scripts', express.static(path.join(__dirname, 'node_modules')))
app.set('views', './views');
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
}),
);
const checkAuth = (req, res, next) => {
try {
if (req.isAuthenticated()) return next();
req.session.backURL = req.url;
res.redirect("/login");
} catch (e) {
console.log(e)
}
};
app.get('/', async function(req, res){
res.render('index.ejs', { url: req.url })
});
app.get('/login', async function(req, res){
if (req.session.backURL) {
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 = "/";
}
res.render('login.ejs', { url: req.url })
});
app.get('/signup', async function(req, res){
res.render('signup.ejs', { url: req.url })
});
app.get('/newshop', async function(req, res){
res.render('shopcreate.ejs', { url: req.url })
});
app.get('/profile', async function(req, res){
res.render('profile.ejs', { url: req.url })
});
app.get('/settings', async function(req, res){
res.render('settings.ejs', { url: req.url })
});
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login',
}), async (
err,
req,
res,
next,
) => {
try {
await console.log(req)
if (req.session.backURL) {
const backURL = req.session.backURL;
req.session.backURL = null;
res.redirect(backURL);
} else {
res.redirect('/');
}
} catch(e) {
console.log(e)
}
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
passport-config.js -
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
console.log(email)
const user = getUserByEmail(email)
if (user == null) {
return done(null, false, { message: 'User not found' })
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user)
} else {
return done(null, false, { message: 'Password incorrect' })
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => {
return done(null, getUserById(id))
})
}
module.exports = initialize
Related
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("/");
});
});
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}`);
});
when I pass name: req.user.name to my ejs file it gives me undefined, Can you help me with that please. let me know if you need more information if you need. I have tried a lot of ways but non of then have worked. thanks for the help.
Error:
Cannot read property 'name' of undefined when i call it in index.js
app.js
const express = require("express");
const expressLayouts = require('express-ejs-layouts');
const mongoose = require("mongoose");
const app = express();
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
const PORT = process.env.PORT || 3000;
const nodemailer = require("nodemailer");
const bodyParser = require("body-parser");
var exphbs = require('express-handlebars');
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
app.get("/home", function(req, res) {
res.sendFile(__dirname + "/index.html")
})
app.get("/login", function(req, res) {
res.sendFile(__dirname + "/login.ejs")
})
app.get("/signup", function(req, res) {
res.sendFile(__dirname + "/register.html")
})
app.get("/payment", function(req, res) {
res.sendFile(__dirname + "/payment.html")
})
app.get("/companyInfo", function(req, res) {
res.sendFile(__dirname + "/companyInfo.html")
})
app.get("/FAQ", function(req, res) {
res.sendFile(__dirname + "/Faq.html")
})
app.get("/contactUs", function(req, res) {
res.sendFile(__dirname + "/contactUs.html")
})
app.post("/contactUs", function(req, res) {
const output = `
<h1>You have a new feedback</h1>
<ul>
<h3>Full Name: ${req.body.name}</h3>
<h3>Full Email: ${req.body.email}</h3>
<h3>Order Number: ${req.body.orderNumber}</h3>
</ul>
<h1>The Subject</h3>
<h3>${req.body.subject}</h1>
`;
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: "sziacustomer#gmail.com",
pass: "Sziaszia12"
}
});
var mailOptions = {
from: req.body.email,
to: 'TEAMSZIA#GMAIL.COM',
subject: 'Costumers Email',
html: output
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
res.sendFile(__dirname + ("/failed.html"), { msg: "email sent" });
} else {
console.log('Email sent: ' + info.response);
res.sendFile(__dirname + ("/success.html"), { msg: "email sent" });
}
});
});
//bodyparser
app.use(express.urlencoded({ extended: false }))
const db = require("./config/keys").mongoURI;
require('./config/passport')(passport);
// Express session
app.use(
session({
secret: 'secret',
resave: true,
saveUninitialized: true
})
);
// Passport middleware
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();
});
//connect mangodb using mongoose
mongoose.connect(db, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log("mongoo bd connected"))
.catch(() => console.log(err));
//ejs
app.use(expressLayouts);
app.set('view engine', 'ejs');
app.use("/", require("./routes/index"));
app.use("/dashboard", require("./routes/index"));
app.use("/users", require("./routes/users"))
app.listen(PORT, console.log(`we are live on ${PORT}`));
*
index.js*
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const bcrypt = require('bcryptjs');
const User = require('../models/User');
const users = require("./users");
const LocalStrategy = require('passport-local').Strategy;
const { ensureAuthenticated } = require("../config/auth")
router.get("/", users, (req, res) =>
res.render("welcome", {
login: req.isAuthenticated(),
name: req.user.name //undefined
}))
user.js
const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const User = require("../models/User");
const passport = require("passport")
router.get("/login", (req, res) => res.render("login"));
router.get("/register", (req, res) => res.render("register"));
router.post('/register', (req, res) => {
const { name, email, password, password2 } = req.body;
let errors = [];
if (!name || !email || !password || !password2) {
errors.push({ msg: 'Please enter all fields' });
}
if (password != password2) {
errors.push({ msg: 'Passwords do not match' });
}
if (password.length < 6) {
errors.push({ msg: 'Password must be at least 6 characters' });
}
if (errors.length > 0) {
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
User.findOne({ email: email }).then(user => {
if (user) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
name,
email,
password,
password2
});
} else {
const newUser = new User({
name,
email,
password
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => {
req.flash(
'success_msg',
'You are now registered and can log in'
);
res.redirect('/users/login');
})
.catch(err => console.log(err));
});
});
}
});
}
});
// Login
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/users/login',
failureFlash: true,
})(req, res, next);
});
// Logout
router.get('/logout', (req, res) => {
req.logout();
req.flash('success_msg', 'You are logged out');
res.redirect('/users/login');
});
module.exports = router;
passport.js
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
// Load User model
const User = require('../models/User');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
// Match user
User.findOne({
email: email
}).then(user => {
if (!user) {
return done(null, false, { message: 'That email is not registered' });
}
// Match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Password incorrect' });
}
});
});
})
);
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
}
auth.js
module.exports = {
ensureAuthenticated: function(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
req.flash('error_msg', 'Please log in to view that resource');
res.redirect('/users/login');
},
forwardAuthenticated: function(req, res, next) {
if (!req.isAuthenticated()) {
return next();
}
res.redirect('/');
}
}
i'm fairly new to express js i want to do a login app so far i did the register part but in login app i want to do the comparaison between the password in database and the password provided by the user and compare it with bcrypt since i'm using it to crypt password , but its not doing the comparaison , what i'm missing here
router
const express = require('express')
const router = express.Router()
const bcrypt = require('bcrypt');
const User = require('../models/user')
const jwt = require('jsonwebtoken')
router.get('/login', function (req, res) {
res.render('login')
})
router.get('/', function (req, res) {
res.render('home')
})
router.get('/register', function (req, res) {
res.render('register')
})
router.post('/register', async function(req,res){
User.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
return User.create({
username: req.body.name,
password: req.body.password,
email: req.body.email,
createdAt: Date.now()
}).then(function (users) {
res.send(users);
}).catch((err)=>{
console.log(err)
})
})
router.post('/login', function(req,res){
User.findOne({
where:{
username:req.body.name
}
})
.then(user=>{
if(user){
if(bcrypt.compareSync(req.body.password,user.password)){
let token = jwt.sign(user.dataValues,secretKey,{
expiresIn:1440
})
res.send(token)
}
else {
res.status(400).json({
error:'error exissts'
})
}
}
})
.catch(err=>{
res.status(400).json({err:err})
})
})
module.exports = router
models
const sequelize = require('../database/db.js')
const Sequelize = require('sequelize');
const User = sequelize.define('authentication',{
username: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING
// allowNull defaults to true
} ,
email: {
type: Sequelize.STRING
// allowNull defaults to true
},
created_at: {
field: 'createdAt',
type: Sequelize.DATE,
},
updated_at: {
field: 'updatedAt',
type: Sequelize.DATE,
},
}, {
freezeTableName: true
},
{
notNull: { args: true, msg: "You must enter a name" }
},
)
module.exports = User
index
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const path = require('path');
// const passport = require('passport');
// const passportJWT = require('passport-jwt');
// Database
const db = require('./database/db');
// Test DB
db.authenticate()
.then(() => console.log('Database connected...'))
.catch(err => console.log('Error: ' + err))
const app = express();
// Handlebars
app.engine('handlebars', exphbs({ defaultLayout: 'main' }));
app.set('view engine', 'handlebars');
// Body Parser
app.use(bodyParser.urlencoded({ extended: false }));
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// Importing files
const routes = require("./routes/route");
app.use("/", routes);
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
index.js
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const path = require('path');
// const passport = require('passport');
// const passportJWT = require('passport-jwt');
// Database
const db = require('./database/db');
// Test DB
db.authenticate()
.then(() => console.log('Database connected...'))
.catch(err => console.log('Error: ' + err))
const app = express();
// Handlebars
app.engine('handlebars', exphbs({ defaultLayout: 'main' }));
app.set('view engine', 'handlebars');
// Body Parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
// Importing files
const routes = require("./routes/route");
app.use("/", routes);
const PORT = process.env.PORT || 4500;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
route.js
const express = require('express')
const router = express.Router()
const bcrypt = require('bcrypt');
const User = require('../models/user')
const jwt = require('jsonwebtoken')
const uuid = require('uuidv4').default;
const secretKey = '321'
router.get('/login', function (req, res) {
res.render('login')
})
router.get('/', function (req, res) {
res.render('home')
})
router.get('/register', function (req, res) {
res.render('register')
})
router.post('/register', function(req,res){
User.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
return User.create({
id: uuid(),
username: req.body.name,
password: req.body.password,
email: req.body.email,
createdAt: Date.now()
}).then(function (users) {
res.send(users);
}).catch((err)=>{
console.log(err)
})
})
router.post('/login', function(req,res){
User.findOne({
where:{
username:req.body.name
}
})
.then(user=>{
if(user){
if(bcrypt.compareSync(req.body.password,user.password)){
let token = jwt.sign(user.dataValues,secretKey,{
expiresIn:1440
})
res.send(token)
}
else {
res.status(400).json({
error:'error exissts'
})
}
}
})
.catch(err=>{
res.status(400).json({err:err})
})
})
module.exports = router
just add app.use(bodyParser.json()) in index.js and define secretKey also add id in user model for primary key and the code working properly
I have been browsing the forum but I am unable to find the error in my code , it always results in false and I am not able to solve it , Please help me...
Is there any other way to authenticate user instead of passport so that I can use it.I am adding more sentences as it is not allowing me to post my query,Sorry..
const http = require("http"),
hostname = "127.0.0.1",
port = 3000,
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
express = require("express"),
passport = require("passport"),
localStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"),
User = require("./models/user");
app = express();
mongoose.connect("mongodb://localhost/drive", { useNewUrlParser: true });
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(passport.initialize());
app.use(passport.session());
app.use(
require("express-session")({
secret: "Beta tumse na ho payega",
resave: false,
saveUninitialized: false
})
);
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(bodyParser.urlencoded({ extended: true }));
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/plain");
});
app.get("/", function(req, res) {
res.render("index");
});
app.get("/register", function(req, res) {
res.send("hello");
});
app.get("/login", function(req, res) {
res.render("login");
});
app.post(
"/login",
passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}),
function(req, res) {}
);
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
console.log("Not logged");
res.redirect("/login");
}
}
app.get("/secret", isLoggedIn, function(req, res) {
res.send("You are logged in");
});
app.post("/register", function(req, res) {
if (req.body.password === req.body.cpassword) {
User.register(
new User({ username: req.body.username }),
req.body.password,
function(err, user) {
if (err) console.log(err);
else
passport.authenticate("local")(req, res, function() {
res.send("signed up");
});
}
);
} else res.send("Password Mismatch");
});
//DRIVE SCHEMA
//var driveSchema = mongoose.Schema({
// title: String,
// created: { type: Date, default: Date.now }
//});
app.listen(port, hostname, function() {
console.log("Server is running at " + hostname + "/" + port);
});
//./models/user.js file
const mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
I have used passport and jwt library, to authenticate and maintain session for the user. There is no need to maintain user session on server side.
apis/apis.js : This file has all apis end points. /login url will authenticate user using passport and send a token to the client using jwt
const passport = require('passport')
const expRoute = require('express').Router();
let exporter = process.exporter;
expRoute.post('/login', (req, res, next) => {
passport.authenticate(
'local',
{
// successRedirect: '/',
// failureRedirect: '/login',
successFlash: 'Welcome!',
failureFlash: 'Invalid username or password.'
},
(err, user, info) => {
if (err) {
return res.status(500).json(err)
}
else if (user) {
return res.status(200).json({
token: exporter.generateToken(user)
})
}
else {
return res.status(400).json(info)
}
}
)(req, res, next);
})
expRoute.get('/view', exporter.authenticateToken, (req, res) => {
let param = req.finalTokenExtractedData
if (param && exporter.isObjectValid(param, 'tokenId', true, true)) {
let condition = {
_id: param.tokenId
}
let options = {
_id: 0,
password: 0,
__v: 0
}
process.USER.findOne(condition, options) // mongo find
.then((data) => {
res.status(200).json({
result: data,
msg: 'success'
})
})
.catch((mongoErr) => {
exporter.logNow(`USER mongo Error: ${mongoErr}`)
res.status(400).json({
msg: 'user not found'
})
})
}
else {
res.status(404).json({
msg: 'invalid token'
})
}
})
module.exports = expRoute
common/env.js: This file will initialise all connections such mongo, require few files will be used as global
process.CONFIG = require('../configs/config.json')
process.exporter = require("../lib/exporter.js")
process.dbInit = (globalName, mongoUrl, collectionName) => {
require("../models/db-init.js")(mongoUrl, collectionName)
.then((modelObj) => {
process[globalName] = modelObj // will be used as global
})
.catch((dbInitErr) => {
process.exporter.logNow(`dbInit Error: ${dbInitErr}`)
process.exit()
});
}
lib/exporter.js: This file has exporter class which consist of all major functions like mongo connection, authenticateToken, verifyPassword, etc.
const fs = require('fs'),
redis = require("redis"),
path = require("path"),
mongoose = require('mongoose'); mongoose.set('useCreateIndex', true);
const Schema = mongoose.Schema;
var bcrypt = require('bcryptjs')
var jwt = require('jsonwebtoken')
class Exporter {
mongoConnection(mongoURI, schemaObj) {
return new Promise(async (resolve, reject) => {
if (!mongoURI || typeof mongoURI == 'undefined' || mongoURI.length < 1)
return reject('invalid mongo connection url');
return resolve(mongoose.createConnection(mongoURI, { useNewUrlParser: true }))
})
}
createMongoSchema(schemaObj) {
return (new Schema(schemaObj));
}
createMongoModel(mongoDB, collectionName, newSchema) {
if (newSchema)
return mongoDB.model(collectionName, newSchema)
return mongoDB.model(collectionName)
}
authenticateToken(req, res, next) {
const bearerHeader = req.header('authorization')
if (typeof bearerHeader != 'undefined') {
const bearer = bearerHeader.split(' ')
const bearerToken = bearer[1]
jwt.verify(bearerToken, process.CONFIG.jwt.token.activated, (err, data) => {
if (err)
res.status(400).json({
msg: "Invalid token or please try to login again"
})
else {
process.exporter.getSingleHashKeysValuesFromRedis('expired_token', bearerToken)
.then((redisTokendata) => {
if (redisTokendata)
res.status(400).json({
msg: "token expired"
})
else {
req.finalTokenExtractedData = data
// if (req.originalUrl.trim() == process.logoutURL.trim())
req.jwtToken = {
token: bearerToken,
secret: process.CONFIG.jwt.token.activated
}
next()
}
})
.catch((redisTokenError) => {
process.exporter.logNow(`redis token error: ${redisTokenError}`)
res.status(400).json({
msg: "Some went wrong while checking token. Please try later."
})
})
}
})
}
else
res.status(400).json({
msg: "invalid token"
})
}
generateToken(data) {
let expiry = new Date();
// expiry.setDate(expiry.getDate() + 7)
expiry.setMinutes(expiry.getMinutes() + 5)
return jwt.sign({
tokenId: data._id,
exp: parseInt(expiry.getTime() / 1000),
}, process.CONFIG.jwt.token.activated)
}
createPassword(password) {
return new Promise((resolve, reject) => {
if (typeof password == 'undefined' && password == '')
return reject('password empty')
bcrypt.hash(password, 10, async (bErr, hash) => {
if (bErr)
reject(bErr)
else
resolve(hash)
})
})
}
verifyPassword(enteredPassword, savePassword) {
return bcrypt.compareSync(enteredPassword, savePassword)
}
}
module.exports = (new Exporter());
index.js: This is file which you will execute node index.js.
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const passport = require('passport');
require('./common/env')
require('./configs/passport')
const app = express()
const cors = require('cors')
app.use(cors());
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
app.use(passport.initialize())
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
let apis = require('./apis/api')
app.use('/user', apis)
/**
* 404 Handler
*/
app.use((req, res, next)=>{
return res.status(404).send("Endpoint "+req.url +" not found");
})
/**
* if any error or exception occurred then write into a JS file so that app can be restarted
*/
process.on('uncaughtException', (err) => {
console.error(err.stack);
});
app.listen(3000, function(server) {
console.log("App listening at 3000");
});
When index.js file has been executed successfully and listening to a port 3000, then use this URL http://localhost:3000/user/login for authentication, it will accept your username and password, then authenticate using passport and send a token to the client as response. The token can contain user data in encrypted form and have expiry time.
Reference link: https://github.com/arjun-707/login-logout-jwt-nodejs
You need the express-session module.
server.js
// Require a possible config.js file with your configuration variables
const Config = require('./models/config.js');
// If the config module is formed as a class
const config = new Config();
const express = new('express');
const app = express();
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const uuid = require('uuid/v4');
const mongoose = require('mongoose');
// Require your custom passport local strategy file
const passport = require('./models/sessions');
mongoose.connect('mongodb://localhost:27017/your_db_name', {
useNewUrlParser: true
});
// Set the session options
app.use(session({
// Use UUIDs for session IDs
genid: (req) => {
return uuid()
},
// If you want to store the session in MongoDB using mongoose
// Require your personal mon
store: new MongoStore({
mongooseConnection: mongoose.connection
}),
// Define the session secret in env variable or in config file
secret: process.env.SESSION_SECRET || config.sessionSecretKey,
resave: false,
saveUninitialized: true
}));
// Initialize the passport module
app.use(passport.initialize());
// Tell to passport to use session
app.use(passport.session());
./models/session.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt-nodejs');
// Your custom MongoDB connection module
const db = require('./db');
// Configure passport.js to use the local strategy
passport.use(new LocalStrategy({
usernameField: 'username'
},
(username, password, done) => {
db.User.find({
username: username // But it could use email as well
}).then(res => {
const user = JSON.parse(JSON.stringify(res[0]));
if (!user) {
return done(null, false, {
message: 'Invalid credentials.\n'
});
}
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false, {
message: 'Invalid credentials.\n'
});
}
return done(null, user);
}).catch(error => done(error));
}
));
// Tell passport how to serialize the user
passport.serializeUser((user, done) => {
done(null, user._id);
});
// Tell passport how to deserialize the user
passport.deserializeUser((id, done) => {
db.User.find({
_id: id
}).then(res => {
const response = typeof res !== undefined && res.length != 0 ? JSON.parse(JSON.stringify(res[0])) : null;
done(null, response)
}).catch(error => done(error, false))
});
// Export passport for external usage
module.exports = passport;
./models/db.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const uuid = require('uuid/v4');
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/your_db_name', {
useNewUrlParser: true
});
// Define the models container
let models = {};
// Prepare your user schema
const userSchema = Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
// Assign the user schema
models.User = mongoose.model('User', userSchema);
// Export for external usage
module.exports = models;
/*
In that way you can wrap in "models" all schemas:
const newSchema = Schema({
name: String
});
models.Newschema = mongoose.model('Newschema', newSchema);
module.exports = models;
And use it externally like:
const db = require('./models/db');
db.User.find({}).then(docs => {}).catch(err => {});
db.Newschema.find({}).then(docs => {}).catch(err => {});
Etc....
*/
./models/config.js
class Config {
constructor() {
this.sessionSecretKey = "my-awesome-secretkey";
/* And other configurations */
}
}
module.exports = Config;
/*
Externally use like:
const Config = require('./models/config');
const config = new Config();
let sessionSecretKey = config.sessionSecretKey;
*/
Then you can use the req.isAuthenticated() after the login:
// POST the username and password to '/login' router
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if (info) {
return res.send(info.message)
}
if (err) {
return next(err);
}
if (!user) {
return res.sendStatus(404); // Is a shortcut
// OR -> res.status(404).end();
// OR -> res.status(404).send('Not found'); as you like
}
req.login(user, (err) => {
if (err) return next(err);
// Store the user object retrieved from MongoDB in `req.session`
req.session.user = user;
return res.sendStatus(200); // Is a shortcut
// OR -> res.status(200).end();
// OR -> res.status(200).send('OK'); as you like
})
})(req, res, next);
});
// The logout logic
app.get('/logout', verifySession, function (req, res) {
req.session.destroy(function (err) {
req.logout();
res.redirect('/');
});
});
// Verify the session to protect private routers
function verifySession(req, res, next) {
if (req.isAuthenticated()) {
next();
} else {
// Forbidden
res.redirect('/');
// OR -> res.sendStatus(403);
// OR -> res.status(403).end();
// OR -> res.status(403).send('Forbidden'); as you like
}
}
Of course you have to run npm install with all the dependencies required defined in package.json file or manually instal with npm i express-session#latest --s for all the dependencies required: npm i module-name#latest --s.
Don't forget the
const server = app.listen(config.port || 3000, () => {
console.log(`Server running on ${server.address().port} port.`);
});
At the end of server.js file. I hope that it will be useful for you.