callback for google oauth not redirecting - node.js

My google oauth is working properly, the data is saved and all the console.logs answer everywhere but there is one problem after serializing my webpage is not redirecting to the react application
problem is in callback
Router.get(
"/callback",
passport.authenticate("google"),
(req, res, err) => {
if (err.name === "TokenError") {
res.redirect("/"); // redirect them back to the login page
}
user = req.user;
console.log("[googleRoutes.js] callback : ", user);
res.redirect("localhost:3000");//problem lies here
}
);
anthe other code is :
const passport = require("passport"),
GoogleStrategy = require("passport-google-oauth20").Strategy,
keys = require("../key"),
User = require("../User"),
UserSession = require("../UserSession");
passport.serializeUser((user, done) => {
console.log("[Serializing Google] :", user.id);
done(null, user.id);
});
passport.deserializeUser((user, done) => {
User.findById(user.id).then(user => {
console.log("[Deserializing Google] :", user.id);
done(null, user);
});
});
passport.use(
new GoogleStrategy(
{
clientID: keys.googleClientID,
clientSecret: keys.googleClientSecret,
callbackURL: "/auth/google/callback"
},
async (accessToken, refreshToken, profile, done) => {
console.log("profile :", profile.id);
const existingUser = await User.findOne({ googleId: profile.id });
if (existingUser) {
//we already have a record wih the given profile ID
console.log("user existing google");
done(null, existingUser);
} else {
//we don't have a user record with this ID, make a new record
const user = await new User();
user.username = profile.displayName;
user.googleId = profile.id;
console.log("google id is saved");
user.save().then(theuser => {
done(null, theuser);
});
}
}
)
);

Related

Passport facebook doesn't create new user and times out

I'm using passport with multiple strategies (JWT, Google and Facebook). All work fine except Facebook, when an existing user tries to login. In this case it just times out and I get a 504.
It tries to call https://api.example.com/users/facebook/callback/?code=... before I get the timeout error.
I tried the exact same logic from my Google strategy, where everything works fine, but it doesn't help. I tried different online tutorials but none of them worked either.
So what am I doing wrong?
Passport.js config - Facebook code block
function(passport) {
passport.serializeUser((user, cb) => {
cb(null, user);
});
passport.deserializeUser((user, cb) => {
cb(null, user);
});
passport.use(new FacebookStrategy({
proxy: true,
clientID: keys.facebook.clientID,
clientSecret: keys.facebook.clientSecret,
callbackURL: "https://api.example.com/users/facebook/callback",
profileFields: ['id', 'displayName', 'email']
},
async (accessToken, refreshToken, profile, done) => {
const { email, first_name } = profile._json;
try {
const oldUser = await User.findOne({ email: email });
if (oldUser) {
return done(null, oldUser);
}
} catch (err) {
console.log(err);
return done(null, false);
}
// register user
try {
const newUser = await new User({
facebook: true,
email: email,
name: first_name,
verified: true,
}).save();
done(null, newUser);
} catch (err) {
console.log(err);
return done(null, false);
}
}
))
}
User auth route
// FACEBOOK
router.get("/facebook", passport.authenticate("facebook"));
router.get("/facebook/callback", generalTooManyRequests, passport.authenticate("facebook"), (req, res) => {
const referer = req.cookies["Origin"]
let redirectURL
// login did NOT work!
if (!req.user) {
redirectURL = "https://app.example.com/login/fehler-facebook"
if (referer === "website") {
redirectURL = "https://example.com/login/?fehler-facebook"
}
res.redirect(redirectURL)
}
// login did work!
else {
redirectURL = "https://app.example.com/callback/token="
if (referer === "website") {
redirectURL = "https://example.com/callback/?token="
}
const tokenObject = utils.issueJWT(req.user);
res.redirect(redirectURL + tokenObject.token)
}
});

PassportJs Google Auth saves existing user as a new user in the database. How can I fix that?

I'm using passportJs Google Authetication. Although a user exist in database, When I login the system with this user, It creates this user again in the database as a new user. How can I fix this problem, can you help ?
Thats image of the database:
Here is my codes:
module.exports = passport.use(
new GoogleStrategy(
{
clientID: config.google.clientID,
clientSecret: config.google.clientKey,
callbackURL: "/auth/google/callback",
},
async (accessToken, refreshToken, profile, done) => {
try {
const user = await models.User.findOne({ google: { id: profile.id } });
if (user) {
done(null, user);
} else {
const newUser = new models.User({
google: profile,
isSocialAuth: true,
name: profile.name.givenName,
lastName: profile.name.familyName,
cart: { items: [] },
});
await newUser.save();
done(null, newUser);
}
} catch (error) {
done(error, null);
}
}
)
);
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
models.User.findById(id, (err, user) => done(err, user));
});
My Router:
router.get("/auth/google", passport.authenticate("google", { scope: ["profile"] }));
router.get("/auth/google/callback", passport.authenticate("google", { failureRedirect: "/login" }), async (req, res) => {
req.session.user = req.user;
req.session.isAuthenticated = true;
res.redirect("/");
});
module.exports = router;
My UserSession Middleware:
module.exports = (req, res, next) => {
if (!req.session.user) {
return next();
}
models.User.findById(req.session.user._id)
.then((user) => {
req.user = user;
next();
})
.catch((err) => {
console.log(err);
});
};
After signing in, in the Passport part,
the findOne query might have some issue. It is not able to find the user & hence it is registering again.
Replace
const user = await models.User.findOne({ google: { id: profile.id } });
to
const user = await models.User.findOne({ "google.id": profile.id });
& check if it works.

I'm trying to implement passport-local but i'm getting error

This is the error I'm getting in passport.js config. I don't understand what it means: Why passport.use is not a function?
TypeError: passport.use is not a function
This is my code:
const LocalStrategy = require('passport-local').Strategy;
const passport = require('passport');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// load user models
const User = require('../models/Users');
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: 'Email is not registered' })
}
})
.catch((err) => {
console.log(err);
})
// 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: 'Incorrect Password' })
}
})
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser( (id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
passport.js
const passport = require("passport")
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
// Local Strategy
passport.use(new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
try {
// find the user given the email
const user = await User.findOne({ "email": email });
// if not, handle it
if (!user) {
return done(null, false);
}
// check if password is correct
const isMatch = await user.isValidPassword(password);
// if not handle it
if (!isMatch) {
return done(null, false);
}
// otherwise return the user
done(null, user);
} catch (error) {
done(error, false);
}
}));

passport-local-mongoose and Google Auth, how handle mutltiple serializers with Passport.js?

how to handle provider strategy and local strategy with passport.js using passport-local-mongoose?
Here I am defining my strategies and de/serializers
// For my Local strategy
passport.serializeUser(Admin.serializeUser());
passport.deserializeUser(Admin.deserializeUser());
// For my Google strategy
passport.serializeUser((user, done) => {
done(null, user.id); //user.id is the id from Mongo
});
passport.deserializeUser((id, done) => {
User.findById(id).then(user => {
done(null, user);
});
});
passport.use('google',
new GoogleStrategy(
{
clientID: keys.googleClientID,
clientSecret: keys.googleClientSecret,
callbackURL: "/auth/google/callback",
proxy: true
},
async (accessToken, refreshToken, profile, done) => {
const existingUser = await User.findOne({ googleId: profile.id });
if (existingUser) {
done(null, existingUser);
} else {
const user = await new User({ googleId: profile.id, token: accessToken, name:profile.displayName }).save();
done(null, user);
}
}
)
);
passport.use('local', new LocalStrategy(Admin.authenticate()));
Like you see I have 2 de/serializers and this is a problem and that is not working but if I take just one serializer and one deserializer for each strategy that is working
so the question is how to handle Local and Google strategy with Passport.Js and node.js
This what I am trying to do
passport.serializeUser(function(user, done) {
if(// This is Local Strategy){
User.serializeUser();
}
else{
done(null, user);
}
});
passport.deserializeUser(function(user,id, done) {
if(// This is Local Strategy){
User.serializeUser();
}
else{
User.findById(id).then(user => {
done(null, user);
});
}
});
UPDATE :
I found a post passport.js multiple de/serialize methods with more information about multiple de/serializers and I tried this :
passport.serializeUser((user, done) => {
done(null, user.id); //user.id is the id from Mongo
});
passport.deserializeUser((id, done) => {
User.findById(id)
.then(user => {done(null, user)
// .catch((err) => done('pass'));
});
});
passport.deserializeUser((obj, done) => {
Admin.deserializeUser();
});
But the catch block mentioned in this post not working for me
From your update:
passport.serializeUser((user, done) => {
done(null, user.id); //user.id is the id from Mongo
});
passport.deserializeUser((id, done) => {
User.findById(id)
.then(user => {
done(null, user)
})
.catch((err) => done('pass')); //you should use catch like this
});
passport.deserializeUser((obj, done) => {
Admin.deserializeUser();
});
If it still does not work,
Follow my code: passport config

Failed to serialize user into session with passportjs and cookie-session

I'm trying to get authentication with Google+ OAuth. To achieve this I'm using passportjs with Google strategy (passport-google-oauth20 module) but I'm stuck in an error while passport tries to serialize the user into a session (using cookie-session).
The error comes after login in the Google site.
The code:
passport.serializeUser((user, done) => {
console.log('serialize ' + (user.id == undefined ? null : user.id));
console.log(user);
return done(null, (user.id == undefined ? null : user.id));
});
passport.deserializeUser((id, done) => {
console.log('dserialize id ' + id);
db.connect((err, client, don) => {
if (err) throw err
client.query('SELECT * FROM "AppUsers" WHERE "googleId" = $1', [id], (err, res) => {
don();
if (err) {
console.log(err.stack);
} else {
console.log(res.rows[0]);
if (res.rows[0]) {return done(null, res.rows[0]);}
else {return done(null, null);}
}
});
});
});
Edit:
async function checkGoogle(profile) {
const client = await db.connect();
try {
const { rows } = await client.query('SELECT * FROM "AppUsers" WHERE "googleId" = $1', [profile.id]);
let currentUser = rows[0];
console.log(currentUser);
if (currentUser) {
console.log('in db ' + currentUser.id);
console.log(currentUser);
return currentUser;
} else {
const { rows } = await client.query('INSERT INTO "AppUsers" ("googleId") VALUES ($1) RETURNING *', [profile.id]);
let newUser = rows[0];
console.log('not in db ' + newUser.id);
console.log(newUser);
return newUser;
}
} catch (error) {
alert(error);
} finally {
client.release();
}
}
passport.use(
new GoogleStrategy({
// options for google strategy
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret,
callbackURL: '/auth/google/redirect'
}, (accessToken, refreshToken, profile, done) => {
// check if user already exists in our own db
return done(null, checkGoogle(profile));
})
);
Output:
The error screen
Please tell me if you need more information about.
You need to wait for the checkGoogle function to return data by using async/await.
passport.use(
new GoogleStrategy({
// options for google strategy
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret,
callbackURL: '/auth/google/redirect'
}, async (accessToken, refreshToken, profile, done) => {
const user = await checkGoogle(profile);
// check if user already exists in our own db
return done(null, user);
})
);

Resources