express-session doesn't pass a variable from one router to another - express

I have this session middleware:
app.use(session({
secret: "tarek",
resave: true,
saveUninitialized: true,
}));
and in this router i stored a variable this way:
app.post('/login', async(req, res)=>{
const {email, password} = req.body;
try {
const user = await User.findOne({email: email})
if (!user) {
res.json({message: "Can't find an account with this e-mail!"})
}else if(user && (await bcrypt.compare(password, user.pass))){
const token = jwt.sign({
email,
}, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE,
});
req.session.token = token;
console.log(req.session.token)
res.json({token: token, id: user.name + user.lastname + user._id})
}else{
res.json({message: "Invalid password"}).status(400)
}
} catch (err) {
console.log(err.message)
res.json({message: "Error while trying to log in please try again later"})
}
})
and ofc when i console.log the req.session.token it works fine
but when i pass it to another router like this:
app.get('/isUSerAuth', verify.verifyjwt, async(req, res)=>{
console.log(req.session.token)
const token = req.session.token
res.status(200).json({auth: true, token: token, message: "you are authenticated!"})
})
so it says that the req.session.token is undefined

Related

Why do i get the Error cannot post /login using express and passportjs?

When i make a post request containing the user data to log in, i get the response: Cannot post /login.
What is really weird about this is that you can see trough logging that the request get processed.
I was using postman and a html form to test and both didnt worked.
When i have a failure in the passport.js file it gets logged.
.
Thats my server.js file (shortened):
const express = require("express");
const cors = require("cors");
const flash = require("express-flash");
const passport = require("passport");
const session = require("express-session");
//app configuration
const app = express();
require("dotenv").config();
const initializePassport = require("./config/passport-config");
initializePassport(
passport,
require('./models/User')
)
app.use(
session({
secret: "Janniks whatsapp Klon",
resave: false,
saveUninitialized: false,
})
);
app.use(passport.initialize());
app.use(passport.session());
//For accepting post from data
const UserRouter = require("./api/User");
app.use(flash());
app.use(express.json());
app.use(bodyarser.urlencoded({ extended: true }));
app.use(
cors() //{ origin: "http://localhost:3000", origin: "http://localhost:3000" }
);
app.use("/user", UserRouter);
app.post('/login', passport.authenticate('local', {
sucessRedirect: 'http://localhost:3000/login',
failureRedirect: 'http://localhost:3000/login',
failureFlash: true
}),
)
and thats my passport-config.js file
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
//Password handle
function initialize(passport, User){
const authenticateUser = async(emailORnumber, password, done)=>{
//Find user with email or phone number
let user;
if(emailORnumber.includes('#')){
user = await User.findOne({ email: emailORnumber})
}else{
user = await User.findOne({ number: emailORnumber })
}
if(!user){
//User not found, error
console.log('User not found')
return done(null, false, { message: 'Falsches passwort oder falsche Handynummer' })
}
//Check if password is correct
try{
console.log('Checking password')
const isMatch= await bcrypt.compare(password, user.password);
if(!isMatch){
return done(null, false, { message: 'Falsches passwort'})
}else{
//If credentials are correct, return the user object
console.log('correct') //gets logged
return done(null, user)
}
}
catch(err){
console.log(err)
return done(err)
}
}
passport.use(new LocalStrategy({ usernameField: 'emailORnumber'}, authenticateUser)),
//Serialize user to store
passport.serializeUser((user, done)=>{
console.log('Serializing user') //gets logged
done(null, user.id)
})
//Deserialize user from store
passport.deserializeUser((id, done)=>{
console.log('Serializing user') //dont gets logged but there is no interaction
User.findById(id, (err, user)=>{
return done(err, user);
});
});
}
module.exports = initialize;
Thanks for all awnsers that can be provided!

Getting error in MERN stack Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I am new to MERN. I was using this code below . I followed a youtube tutorial and it was working fine for me for 4 to 5 days but now suddenly it has stopped working. I didn't change anything. I am not able to login, logout or even fetch data. My postman is giving positive results using these api but it won't work on my code. I want to remind you guys again, it was working fine for 4 to 5 days.
const User = require("../model/user");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const signup = async (req, res, next) => {
const { fname, lname, email, password, role, phone } = req.body;
let existingUser;
try {
existingUser = await User.findOne({ email: email });
} catch (err) {
console.log(err);
}
if (existingUser) {
return res.status(400).json({ message: "user already exists" });
}
const hashedPassword = bcrypt.hashSync(password);
const user = new User({
fname,
lname,
email,
password: hashedPassword,
phone,
role,
});
try {
await user.save();
} catch (err) {
console.log(err);
}
return res.status(201).json({ message: user });
};
const login = async (req, res, next) => {
const { email, password } = req.body;
let existingUser;
try {
existingUser = await User.findOne({ email: email });
} catch (err) {
console.log(err);
}
if (!existingUser) {
return res
.status(400)
.json({ message: "user doesn't exist. Please signup" });
}
const isPasswordCorrect = bcrypt.compareSync(password, existingUser.password);
if (!isPasswordCorrect) {
return res.status(401).json({ message: "invalid email or password" });
}
const token = jwt.sign({ id: existingUser._id }, "change1122", {
expiresIn: "1h",
});
res.cookie(String(existingUser._id), token, {
path: "/",
expires: new Date(Date.now() + 1000 * 3600),
httpOnly: true,
sameSite: "lax",
});
return res
.status(200)
.json({ message: "user logged in sucessfully", user: existingUser, token });
};
const verifyToken = (req, res, next) => {
const cookies = req.headers.cookie;
const token = cookies.split("=")[1];
if (!token) {
res.status(404).json({ message: "no token found" });
}
jwt.verify(String(token), "change1122", (err, user) => {
if (err) {
return res.status(404).json({ message: "invalid token" });
}
req.id = user.id;
});
next();
};
const getUser = async (req, res, next) => {
const id = req.id;
let user;
try {
user = await User.findById(id, "-password");
} catch (err) {
console.log(err);
}
if (!user) {
res.status(404).json({ message: "user not found with the id" });
}
return res.status(200).json({ user });
};
const logout = async (req, res, next) => {
const cookies = req.headers.cookie;
console.log(cookies);
const token = cookies.split("=")[1];
if (!token) {
res.status(404).json({ message: "no token found" });
}
const user = req.id;
res.clearCookie(`${user}`);
req.cookies[`${user}`] = "";
return res.status(200).json({ message: "successfully logged out" });
};
exports.signup = signup;
exports.login = login;
exports.verifyToken = verifyToken;
exports.getUser = getUser;
exports.logout = logout;
Here is the error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:372:5) at ServerResponse.setHeader (node:_http_outgoing:576:11)
at ServerResponse.header (E:\Reacct\pos\server\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (E:\Reacct\pos\server\node_modules\express\lib\response.js:174:12)
at ServerResponse.json (E:\Reacct\pos\server\node_modules\express\lib\response.js:278:15)
at getUser (E:\Reacct\pos\server\controller\user-controller.js:86:25)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
I think i have an issue with cookies or token, I am new so i don't understand it properly.

Passport local strategy is never get called

I know this question was asked many times in stack over flow. I tried every accepted answers but can't my local strategy into function. Here is my code
var express = require('express');
var app = express();
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.set('trust proxy', 1); // trust first proxy
app.use(session({
secret: '564sdf4as564f56a7s765s4afjkgadxjkbadksj',
resave: true,
saveUninitialized: true,
cookie: { secure: true }
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy({
usernameField:'userName',
passwordField:'password',
passReqToCallback : true
},function(request, userName, password, done) {
console.log(request);
UserAccount.findOne({'userName': userName} , function(err, user) {
if (err) return done(err);
if (!user) return done(null, false, 'Incorrect username.' );
user.verifyPassword(password, function(err, isMatch) {
if (isMatch) {
return done(null, user);
} else {
return done(null, false, 'Incorrect password.');
}
});
});
}));
passport.serializeUser(function(user, done) {
console.log('Serialize user called');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log('Deserialize user called');
UserAccount.findById(id, function(err, user) {
done(err, user);
});
});
Then I created a router like
var router = express.Router();
require('./controllers/user')(router,passport);
app.use('/api',router);
Then in my user controller I created signIn function like
app.post('/signIn',function (request,response,next){
var variables = request.body;
console.log(variables);
passport.authenticate('local', function(error, user, info) {
console.log(user);
if (error) { console.log(error); return next(err); }
if (!user) { return response.redirect('/login'); }
response.logIn(user, function(err) {
if (err) { return next(err); }
return response.redirect('/users/' + user.username);
});
})(request, response, next);
});
Then I send a request from "Postman"
{
"userName":"karthik#abc.com",
"password":"qwerty"
}
My mongodb userName and password fields are same.
In my db there is an account with this user name and password. But every time it return 'user' as 'false' inside authenticate. I tried to console my request inside local strategy but it never gets called. I don't understand What I done wrong here? Can some one help to solve this? Thank you very much.
You should name local strategy and use it in authenticate.
Use like this passport.use('local-strategy',new LocalStrategy({});
and like passport.authenticate('local-strategy');

ExpressJS - JWT and Passport Implementation

I'm currently trying to learn JWT and Passport for ExpressJS while trying them out but I can't seem to grasp the idea of how Passport works.
Here's what I have done initially in my ExpressJS application.
/api/login POST API
Accepts username and password
/api/login then creates a JWT with the username and password as the payload
The token is then responded to the client
I think my /api/login API simulates the general idea of JWT of hard authenticate once and respond with token.
/api/test GET API on the other hand
Only authenticated users can access
Simply returns "Hello World!"
What is the problem/s?
My code doesn't seem to validate the token (I tried putting the token in Authenticate header.
Where in my request should I include the token returned from /api/login when requesting to /api/test?
Now to my actual code:
app.js
var express = require("express");
var bodyParser = require("body-parser");
var jwt = require("jsonwebtoken");
var passport = require("passport");
var LocalStrategy = require('passport-local').Strategy;
var mySecret = "mySecret";
var app = express();
var port = process.env.PORT || 3000;
app.use(bodyParser.json());
passport.use(new LocalStrategy(
function (token, done) {
var credentials = jwt.verify(token, mySecret);
if (credentials.username == "test" && credentials.password == "test") {
return done(null, credentials);
} else {
return done(null, false);
}
}
));
app.use(passport.initialize());
app.post("/api/login", function (request, response) {
var user = {
"username": request.body.username,
"password": request.body.password
};
response.send(jwt.sign(user, "mySecret"));
});
app.get("/api/test", passport.authenticate("local", {
"session": false
}), function (request, response) {
response.send("Hello World!");
});
app.listen(port, function () {
console.log("Listening on port: " + port);
});
You need to configure jwtStratagy also to authenticate the user.
here is working example: -
const express = require("express");
const bodyParser = require("body-parser");
const jwt = require("jsonwebtoken");
console.log(jwt.verify);
const passport = require("passport"),
LocalStrategy = require("passport-local").Strategy;
const cors = require("cors");
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(passport.initialize());
var secret = '11210646';
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
passport.use(new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
},
function(req, username, password, done) {
console.log('ohh', username, password);
let err = null;
if (err) { return done(err); }
if (username != 'abhi') {
return done(null, false, { message: 'Incorrect username.' });
}
if (password != 'pass') {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, username);
}
));
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
console.log(err, user, info);
if (err) { return next(err); }
if (!user) { res.send({ "status": info.message }); }
res.send({ "status": user });
})(req, res, next);
});
var opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: secret,
issuer: 'jonu',
audience: 'jonu bhai',
passReqToCallback: false
};
app.post('/me2', function(req, res, next) {
passport.authenticate('jwt', { session: false }, function(err,user, info) {
if (err) { return next(err); }
if (!user) { res.send({ "status": info.message }); }
res.send({ "status": user });
})(req, res, next);
});
//jwt
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
let err = null;
if (err) {
return done(err, false);
}
if (jwt_payload) {
return done(null, jwt_payload);
}
else {
return done(null, false);
// or you could create a new account
}
}));
app.post('/signup', (req, res) => {
let token = jwt.sign({
user: {
id: "idididid",
name: "Abhishek Singh",
username: "abhishek11210646"
}
},
secret, {
algorithm: 'HS256',
expiresIn: '5h',
issuer: 'jonu',
audience: 'jonu bhai'
});
res.send({ "token": token });
});
app.get('/', (req, res) => {
res.send({ "status": "Up and Running..." });
});
app.listen(8080, () => {
console.log('server running');
});

Implement Remember Me functionality in Express + PassportJS + Redis app

I'm trying to build authentication system with ExpressJS and PassportJS. For session store I use Redis. I wanna use Remember Me. Every time when the user signs in and has marked "remember me" check-box, it should automatically sign in by next visit on site. I have downloaded an example app form Github https://github.com/jaredhanson/passport-remember-me and change for my using.
var express = require('express')
, passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, mongodb = require('mongodb')
, mongoose = require('mongoose')
, bcrypt = require('bcrypt')
, SALT_WORK_FACTOR = 10
, RedisStore = require('connect-redis')(express);
mongoose.connect('localhost', 'test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback() {
console.log('Connected to DB');
});
// User Schema
var userSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true},
accessToken: { type: String } // Used for Remember Me
});
// Bcrypt middleware
userSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if(err) return next(err);
bcrypt.hash(user.password, salt, function(err, hash) {
if(err) return next(err);
user.password = hash;
next();
});
});
});
// Password verification
userSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if(err) return cb(err);
cb(null, isMatch);
});
};
// Remember Me implementation helper method
userSchema.methods.generateRandomToken = function () {
var user = this,
chars = "_!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
token = new Date().getTime() + '_';
for ( var x = 0; x < 16; x++ ) {
var i = Math.floor( Math.random() * 62 );
token += chars.charAt( i );
}
return token;
};
// Seed a user
var User = mongoose.model('User', userSchema);
var usr = new User({ username: 'bob', email: 'bob#example.com', password: 'secret' });
usr.save(function(err) {
if(err) {
console.log(err);
} else {
console.log('user: ' + usr.username + " saved.");
}
});
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
//
// Both serializer and deserializer edited for Remember Me functionality
passport.serializeUser(function(user, done) {
var createAccessToken = function () {
var token = user.generateRandomToken();
User.findOne( { accessToken: token }, function (err, existingUser) {
if (err) { return done( err ); }
if (existingUser) {
createAccessToken(); // Run the function again - the token has to be unique!
} else {
user.set('accessToken', token);
user.save( function (err) {
if (err) return done(err);
return done(null, user.get('accessToken'));
})
}
});
};
if ( user._id ) {
createAccessToken();
}
});
passport.deserializeUser(function(token, done) {
User.findOne( {accessToken: token } , function (err, user) {
done(err, user);
});
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object. In the real world, this would query a database;
// however, in this example we are using a baked-in set of users.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
user.comparePassword(password, function(err, isMatch) {
if (err) return done(err);
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
var app = express();
// configure Express
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs-locals'));
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({
store: new RedisStore({ host: '127.0.0.1', port: 6379, prefix: 'chs-sess' }),
secret: '4Md97L1bL4r42SPn7076j1FwZvAiqube',
maxAge: new Date(Date.now() + 3600000)
}));
// Remember Me middleware
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.rememberme ) {
req.session.cookie.maxAge = 2592000000; // 30*24*60*60*1000 Rememeber 'me' for 30 days
} else {
req.session.cookie.expires = false;
}
}
next();
});
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(__dirname + '/../../public'));
});
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/account', ensureAuthenticated, function(req, res){
res.render('account', { user: req.user });
});
app.get('/login', function(req, res){
res.render('login', { user: req.user, message: req.session.messages });
});
// POST /login
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
//
// curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login
//
/***** This version has a problem with flash messages
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
*/
// POST /login
// This is an alternative implementation that uses a custom callback to
// acheive the same functionality.
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
req.session.messages = [info.message];
return res.redirect('/login')
}
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/');
});
})(req, res, next);
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
app.listen(3000, function() {
console.log('Express server listening on port 3000');
});
// Simple route middleware to ensure user is authenticated.
// Use this route middleware on any resource that needs to be protected. If
// the request is authenticated (typically via a persistent login session),
// the request will proceed. Otherwise, the user will be redirected to the
// login page.
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login')
}
My app doesn't work with Remember Me, every time when I close the browser, I have to sign-in again. I don't know, what I have done wrong.
My second question is, how doe Remember Me works as usual? I have some idea but not exactly sure.