We new to node js,
We are using passport.js for authentication and session management.
Using vhost for multiple domain, front-end and back-end.
Below are 2 domain names:
example.com
admin.example.com
While doing deserializeUser it is taking an object of the first domain called
below is the snippet, this is written in app.js
if (req.get('host') == envConfig.siteurl) {
console.log('this is front-end');
var User = mysqlObj.Model.extend({
tableName: 'users'
});
passport.deserializeUser(function(sessionUser, done) {
console.log('front');
new User({
id: sessionUser.id
}).fetch().then(function(user) {
console.log(user);
done(null, user);
});
});
}
if (req.get('host') == envConfig.adminurl) {
console.log('this is back-end (admin)');
var AdminUser = mysqlObj.Model.extend({
tableName: 'admin_user'
});
passport.deserializeUser(function(sessionAdminUser, done) {
console.log('admin');
new AdminUser({
id: sessionAdminUser.id
}).fetch().then(function(user) {
console.log(user);
done(null, user);
});
});
}
Now when we login to front-end it console's 'front'
and then when we try to login to back-end it still console's 'front' instead of 'admin'
By this we understand it's calling the same object of "deserializeUser"
But our objective is based on domains and we are querying two different tables for each of the domains.
Which is failing in above case.
Please help!!!
Thanks in advance...
@Sujit50 you need to create a new instance of passport (not use the default instance) for each domain and set-up properly in each app (express app)
var passport = require('passport');
var authWeb = new passport.Passport();
var authtAdminWeb = new passport.Passport();
// do your .deserializeUser config for each passport's instance (authWeb, authAdminWeb) here...
Thanks @bjrmatos this helped us resolve the issue :+1:
@bjrmatos , if I create different instances of passport for different type of users, then I suppose I'll have to use passport.authenticate() for different passport instance for each type of user and I can't just use default instance which we get by require('passport'). Am I right? If that's the case, then what would be the good way to maintain global instances of passport instances and use them in all different routers?
if I create different instances of passport for different type of users
just in case that there is some confusion: note that in most cases you need a new instance per domain that you are handling, not per each user (that would be overkill)
if I create different instances of passport for different type of users, then I suppose I'll have to use passport.authenticate() for different passport instance for each type of user and I can't just use default instance which we get by require('passport'). Am I right?
yes, you need to use the .authenticate method of the instance that you manually created, not the default one that come in the passport export.
If that's the case, then what would be the good way to maintain global instances of passport instances and use them in all different routers?
just create a new file called authenticator.js and add some functions to create and get passport instances and then in your routes just import authenticator.js and call something like passportInstanceOfMySubdomain = authenticator.get('mysubdomain.com') to get the corresponding passport instance and then just use it normally like any passport instance passportInstanceOfMySubdomain.authenticate(... -> that is what i do currently
@bjrmatos Thanks for the quick reply. I have one more doubt, is it bad to use different instances for different kind of users. The way I know to use it for different type of users is, in passport.deserializeUser(), first look for the user model in first type of user using the _id, if not found, then check for the user model in the other type of user. So, if I'm using three type of users, it may take three database operations for a particular type, just for deserializing it. I haven't used passport much, so I don't have much idea about what better I can do, so I thought of using different instances. Can you please suggest some better way? I'd be thankful for any help.
hmm i think that you can handle your use case with the default instance of passport (seems like you don't need multiple instances for your case), you just need to add more data when you are serializing the user, something like this:
passport.serializeUser(function(user, done) {
done(null, {
id: user.id,
type: user.type
});
});
and then use the new user.type information in your deserializeUser function to conditionally select a different database or create a different query. with that, you handle all types of users with just one hit to the database
@bjrmatos , Thanks for the solution. It works for using different type of users. But this method of serializing extra info in same passport instance still doesn't solve all problems. Referring to the req.login() function code at https://github.com/jaredhanson/passport/blob/07bff37406241b0cf8db35986788d2dadbf93763/lib/http/request.js#L31 , it saves the info of logged in user in property field set at line property = this._passport.instance._userProperty || 'user';. So for a particular instance, it'll save the info in req.user(req[property] to be exact). So, if I use a single instance of passport, then only one type of user will be logged in per session. If another type of user logs in, then it'll be replaced. Its not an issue for same type of user, because only one user of one type should be logged in at one time. But it makes a problem for different type of user. Also, the isAuthenticated() method does return (this[property]) ? true : false;. I can write my own isAuthenticated() method, but the problem is in req.login(). Old user info will just be replaced by new user in the information stored in session. If I use multiple instances, then I can just set userProperty differently for different instances during initialization of each instance. So, now, should I be using multiple instances, or there is still a better way?
Edit: I tried using multiple instances. Got the same problem as, https://github.com/jaredhanson/passport/issues/286 , https://stackoverflow.com/questions/25896753/passportjs-using-multiple-passports-within-express-application , https://stackoverflow.com/questions/35392317/how-to-use-two-separate-passport-instances-in-a-single-express-server-file . But seems like there is no proper solution. Can you suggest some workaround, because I'm unable to find the solution anywhere.
Hello guys. Sorry for posting in old conversations, but could you please help me with the issue I'm having? It's really similar to what you've written here.
I want to have 2 models: Librarian and User. Therefore, you can see in /config how did I do that. But, it's giving me errors, and the session isn't starting for Librarians. Could you take a look?
how to apply session-ing for every pages i have, for eg. i have multiple pages like, /user/login, /user/register, /projects, /profiles, /datasources/projects etc... all i could do is followed some tutorial and created git clone. right now i could do is creating session-id for login and register page and destroy the session in logout page. My question is how to apply the same for all pages??? I m new to nodejs as well as javascript, Please bear with me.
@LostInCode404
Could you please provide a code snippet? I am not exactly sure where to create new instances and how to import them into other files.
Hi @bjrmatos , i want to make 2 types of users one as User(
//jshint esversion:6
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const session = require("express-session");
const GoogleStrategy = require('passport-google-oauth20').Strategy; // google added
const findOrCreate = require("mongoose-findorcreate"); // google added
const app = express();
app.set("view engine" , "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
app.use(session({
secret: "ThisisaNewSecret",
resave: false,
saveUnitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb://localhost:27017/userDB", {useUnifiedTopology: true , useNewUrlParser: true});
mongoose.set("useCreateIndex" , true);
const recruiterSchema = new mongoose.Schema({
id: String,
Company: String,
Recruiter_name: String,
Recruiter_Pos: String,
Recruiter_email: String,
Company_email: String,
Recruiter_Phno: String,
Country: String,
City: String,
Experience: String,
Level: String
});
const projectSchema = new mongoose.Schema({
Name: String,
Desc: String,
link: String
});
const studentSchema = new mongoose.Schema({
email: String,
password: String,
googleId: String,
first_name: String,
last_name: String,
highest_Quali: String,
course: String,
Specialization: String,
College: String,
course_type: String,
Grad_Year: String,
projects: [projectSchema],
Skills: [String]
});
studentSchema.plugin(passportLocalMongoose); // for Student
recruiterSchema.plugin(passportLocalMongoose); //for Recruiter
studentSchema.plugin(findOrCreate); // google added
const User = mongoose.model("User", studentSchema);
const project = mongoose.model("project" , projectSchema);
const Recruiter = mongoose.model("recruiter", recruiterSchema);
passport.use(User.createStrategy()); // Student
passport.use(Recruiter.createStrategy()); //Recruiter
passport.serializeUser(function(user, done) { //student // works for all the strategies // google added
done(null, user.id);
});
passport.deserializeUser(function(id, done) { //Student // works for all the strategies // google added
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.deserializeUser(function(id, done) { //Recruiter // works for all the strategies // google added
Recruiter.findById(id, function(err, user) {
done(err, user);
});
});
// passport.serializeUser(function(user, done) {
// done(null, user);
// });
// passport.deserializeUser(function(user, done) {
// if(user!=null)
// done(null,user);
// });
let TempObj = {
name: ""
}
// google added
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo" //changed
},
function(accessToken, refreshToken, profile, cb) {
TempObj.name = profile.displayName;
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.get("/", function(req, res){
res.render("home");
});
app.get("/auth/google", /* "/auth/google" is the First to be invoked path and it is basically a passport / //google added
passport.authenticate("google", { scope: ['profile'] })); / plugin for authenticating the user using /
/ google strategy at the Lines : 61-74 and is demanding for the profile containing all the info about the user /
app.get("/auth/google/secrets",
passport.authenticate("google", { failureRedirect: "/login" }), //authenticate locally // google added
function(req, res) { / "/auth/google/secrets" is the Link where one is redirected by google when /
// Done Finally / it is authenticated by the google serves */
res.render("Student_login", {user: TempObj});
});
app.get("/Student_edit", function(req, res){
if(req.isAuthenticated()){
res.render("Student_edit", {user: TempObj});
}else{
res.redirect("/register");
}
});
app.get("/login", function(req, res){
res.render("login");
});
app.get("/register", function(req, res){
res.render("register");
});
app.get("/logout" , function(req, res){
req.logout();
res.redirect("/");
});
app.post("/Student_edit", function(req, res){
console.log(req.body);
let x = req.body.skillwala;
let y = x.split(",");
console.log(y);
});
app.post("/student_register", function(req, res){
TempObj.name = req.body.username;
User.register({username: req.body.username}, req.body.password , function(err , user){
if(err){
console.log(err + " at Student register route" );
res.redirect("/register");
}else{
passport.authenticate("local")(req, res, function(){
res.redirect("/Student_edit");
});
}
});
});
app.post("/recruiter_register", function(req, res){
TempObj.name = req.body.username;
Recruiter.register({username: req.body.username}, req.body.password, function(err, recruiter){
if(err){
console.log(err + " at Recruiter register Route");
res.redirect("/register");
}else{
passport.authenticate("local")(req, res, function(){
res.render("Recruiter_edit", {user: TempObj});
});
}
});
});
app.post("/student_login", function(req, res){
const user = new User({ // add More entries here
username: req.body.username0,
password: req.body.password
});
TempObj.name = req.body.username;
req.login(user, function(err){
if(err){
console.log(err);
res.redirect("/login");
}else{
passport.authenticate("local")(req, res, function(){
res.render("Student_login" , {user: TempObj});
});
}
});
});
app.post("/recruiter_login", function(req, res){
const recruiter = new Recruiter({
username: req.body.username,
password: req.body.password
});
TempObj.name = req.body.username;
req.login(recruiter, function(err){
if(err){
console.log(err);
}else{
passport.authenticate("local")(req, res, function(){
res.render("Recruiter_login", {user: TempObj});
});
}
});
});
app.listen(3000, function(){
console.log("The server is Running Properly at Port 3000");
});
@Sujit50 you need to create a new instance of passport (not use the default instance) for each domain and set-up properly in each app (express app)
var passport = require('passport'); var authWeb = new passport.Passport(); var authtAdminWeb = new passport.Passport(); // do your .deserializeUser config for each passport's instance (authWeb, authAdminWeb) here...
the problem persist!! :(
Thanks Man..! it Worked ..!
On Fri, Apr 16, 2021 at 6:38 AM Christopher Duran @.*>
wrote:
@Sujit50 https://github.com/Sujit50 you need to create a new instance
of passport (not use the default instance) for each domain and set-up
properly in each app (express app)var passport = require('passport');var authWeb = new passport.Passport();var authtAdminWeb = new passport.Passport();
// do your .deserializeUser config for each passport's instance (authWeb, authAdminWeb) here...the problem persist!! :(
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jaredhanson/passport/issues/450#issuecomment-820837128,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AO67RDNU4ETRNQLNIUTHETLTI6EYZANCNFSM4BXTNP4A
.
Most helpful comment
@Sujit50 you need to create a new instance of passport (not use the default instance) for each domain and set-up properly in each app (express app)