I know there are lots of questions similar to this, I checked the questions asked before and none of the answers did solve my problem. I m developing a simple authentication node.js app for now (the front end is react-native, the database is MongoDB). I m using following packages for this:
- passport-local-mongoose
- express-session
- passport-local
- passport
So here is the 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 cors = require('cors');
var passport = require('passport');
var user = require('./models/user');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var cookieParser = require('cookie-parser')
var app = express();
app.use(cookieParser('keyboard cat'));
var corsOptions = {
origin: '*',
credentials: true };
app.use(cors(corsOptions))
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
//auth settings
app.use(require("express-session")({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(user.createStrategy());
passport.serializeUser(user.serializeUser());
passport.deserializeUser(user.deserializeUser());
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;
Here is the user model:
var mongoose=require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');
var userShema = new mongoose.Schema({
username : String,
password : String
})
userShema.plugin(passportLocalMongoose);
var user= mongoose.model("User",userShema);
module.exports = user;
Here is my route file
var express = require('express');
var router = express.Router();
var user= require("../models/user");
const passport = require('passport');
var isLoggedIn =require('../session');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.post('/login', function(req, res, next) {
passport.authenticate('local' ,function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.send("-1"); }
req.logIn(user, function(err) {
if (err) { return next(err); }
req.session.save(() => res.send("Başarılı"));
});
})(req, res, next);
});
router.post('/signUp', async function(req, res, next) {
try{
console.log('registering user');
user.register(new user({username: req.body.username}), req.body.password, function(err) {
if (err) {
console.log('error while user register!', err);
return next(err);
}
console.log('user registered!');
res.redirect('/');
});
}
catch(e){
console.log(e);
res.status(503).send("-1")
}
});
router.get('/logOut', function(req,res,next){
req.logOut();
res.send("1");
})
router.get('/home',isLoggedIn,function(req,res,next){
res.send("Success");
})
module.exports = router;
And finally here is the session.js
const passport = require('passport');
var isLoggedIn =(req,res,next) =>{
if(req.isAuthenticated()){
return next();
}
res.status(403).send("Something went wrong")
}
module.exports = isLoggedIn;
The problem is here, after authentication (which works fine), React native goes to the home page and I wanna take some information as the user logged in.For this i m using isLoggedIn function which uses req.isAuthenticated() and returns always false.
The most common answers that I've tried and didn't work are
- Make sure session-passport.init-passport.session lines in the correct order (which already is in my app)
- Issue related clients get-post call (in my react-native app -> axios.post(BaseURL+url,data,{ withCredentials: true }) , also in server app -> var corsOptions = { origin: '*', credentials: true }; app.use(cors(corsOptions)))
- Some say if you are working with https you have to set {secure:true} ( which I m not)
- One said "After authenticating, passport.js requires you to reroute/redirect"otherwise the session is not created, but lots of people also having problems with redirect. I did try it didn't solve the issue.
- One said don't use express-session, use client-sessions (i did try that, didn't work)
- Some people suggest to change serialize and deserialize functions ( i tried other codes that I found on the internet, none of them worked) but the problem is my deserialize function never runs(i think this function works after isAuthenticated() and checks the user info on the req but my req does not have that info. Basically, I can log in to the app but it doesn't save my session in request.)
- A person suggests that " express-session tries to delay the redirect, but some browsers don't wait for the whole response before directing. So you need to manually save before redirecting." and it solved almost everyone's problem but me. (In my code as you can see req.session.save(() => res.send("Başarılı")); )
- Also, another person said putting delay also works the issue ( i tried, it didn't)
So if anybody has another solution besides these, please share. I am open to all suggestions.