req.user is undefined in Sean.js - node.js

I'm working on a project using Sean.js and recently I tried to add a middleware to secure my api routes. I followed the "article" example using the server.policy.js and when I try to use the req.user variable it says that is undefined. I started to investigate the problem and it comes that is something to do with passport.js. I have no more than 2 months working on this and I'm not very familiar with all of this.
On the user.server.config.js is where Serelize and Deserialize the sessions:
module.exports = function(app, db) {
// Serialize sessions
passport.serializeUser(function(user, done) {
var userData = {
id: user.id,
firstName: user.firstName,
lastName: user.lastName,
displayName: user.displayName,
username: user.username,
email: user.email,
profileImageURL: user.profileImageURL,
roles: user.roles,
additionalProvidersData: user.additionalProvidersData
};
done(null, userData);
});
// Deserialize sessions
passport.deserializeUser(function(user, done) {
done(null, user);
});
// Initialize strategies
config.utils.getGlobbedPaths(path.join(__dirname, './strategies/**/*.js')).forEach(function(strategy) {
require(path.resolve(strategy))(config);
});
// Add passport's middleware
app.use(passport.initialize());
app.use(passport.session());
};
Is here the problem or should modify something else?. I believe that has something to with this because it also I have the problem that when I reload the session ends and I have to log in again.

Like the commnet above. Sean.js use Redis to store sessions, So you need to intall it first and then run it and the session will be available on req.user

Related

Why won't my express-session persist?

I'm currently working on a MERN stack application that will utilize a login/sign-up form that is linked to my Mongo database. I have successfully been able to create a user, hash the user's password, and then store this user into the database, as well as log the user in by checking their credentials from the database.
When attempting to employ a solution that's industry standard, I decided to work with Passport and Express-session to implement authentication and sessions for each user when they log in. Once a user is created/logged in, passport correctly stores their information into req.user, and a session is created and logged with req.session. Below is the console log of req.user followed by req.session :
user with id xxx serialized
email: ...
password: ...
isAuthenticated: true
Session {
path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {user: xxx } }
This all displays right after I log-in, and to my knowledge this means that a session has been created and my user has been serialized properly. However, when I go to a new page on the webapp, I lose my session-- req.user becomes undefined, and req.sessionId changes each time the page does -- which leads me to believe that a new session with an empty user is created each time I switch pages (I am running a fetch method in my NavBar in React that triggers each time the Component mounts). Google Chrome also does not accurately log the cookies even when they are created as evidenced by the console logs.
My question is : why won't my session persist when I switch pages? My goal is to keep track of this session data to pass to my React frontend to render specific content. Is there a better way to go about this? Below is my middleware ordering:
app.use(session({
secret: 'test',
saveUninitialized: false,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
Here are the methods I am calling in my router file:
router.get('/',function(req, res){
console.log(req.user);
console.log(req.session);
});
router.post('/login',passport.authenticate('local'), function(req,res)
{
console.log(req.user);
console.log(req.isAuthenticated());
console.log(req.session);
});
passport.serializeUser(function(user, done) {
console.log("user with id " + user._id + " serialized");
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
console.log("deserializing user with id " + id + " ");
User.findById(id, function(err, user) {
done(err, user);
});
});
Here is my api fetch call from my front end:
componentDidMount(){
var current_user = "";
fetch("http://localhost:3001/users/", {
method: "get",
headers: {
'Accept':'application/json',
'Content-Type': 'application/json'
}
})
.then( (response)=> response.json())
.then( (response)=> {
if(response.user!==current_user){
current_user = response.user;
this.setState({
user: current_user
}), ()=> console.log(response);
}
})
}
I am also aware that currently the fetch method will not properly work: the goal is for that skeleton to work properly and have it return the correct id. What is logging improperly is the session and the req.user before I can even get the chance to pass it to my front end. Any and all help would be appreciated.

Google Oauth giving code redeemed error

Hi i am working on a project where a user logs in via google account.(localhost)
I have implemented the google signup.
As soon as I log in from my account I am getting the below error.
TokenError: Code was already redeemed.
at Strategy.OAuth2Strategy.parseErrorResponse (c:\Projects\Internship_rideshare\node_modules\passport-google-oauth\node_modules\passport-oauth\node_modules\passport-oauth2\lib\strategy.js:298:12)
at Strategy.OAuth2Strategy._createOAuthError (c:\Projects\Internship_rideshare\node_modules\passport-google-oauth\node_modules\passport-oauth\node_modules\passport-oauth2\lib\strategy.js:345:16)
at c:\Projects\Internship_rideshare\node_modules\passport-google-oauth\node_modules\passport-oauth\node_modules\passport-oauth2\lib\strategy.js:171:43
at c:\Projects\Internship_rideshare\node_modules\passport-google-oauth\node_modules\passport-oauth\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:176:18
at passBackControl (c:\Projects\Internship_rideshare\node_modules\passport-google-oauth\node_modules\passport-oauth\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:123:9)
at IncomingMessage.<anonymous> (c:\Projects\Internship_rideshare\node_modules\passport-google-oauth\node_modules\passport-oauth\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:142:7)
at IncomingMessage.emit (events.js:129:20)
at _stream_readable.js:908:16
at process._tickCallback (node.js:355:11)
My code is as follows(snippet for google login):-
passport.use(new GoogleStrategy(google, function(req, accessToken, refreshToken, profile, done) {
if (req.user) {
User.findOne({ google: profile.id }, function(err, existingUser) {
if (existingUser) {
console.log('There is already a Google+ account that belongs to you. Sign in with that account or delete it, then link it with your current account.' );
done(err);
} else {
User.findById(req.user.id, function(err, user) {
user.google = profile.id;
user.tokens.push({ kind: 'google', accessToken: accessToken });
user.profile.displayName = user.profile.displayName || profile.displayName;
user.profile.gender = user.profile.gender || profile._json.gender;
//user.profile.picture = user.profile.picture || 'https://graph.facebook.com/' + profile.id + '/picture?type=large';
user.save(function(err) {
console.log('Google account has been linked.');
done(err, user);
});
});
}
});
} else {
User.findOne({ google: profile.id }, function(err, existingUser) {
if (existingUser) return done(null, existingUser);
User.findOne({ email: profile._json.email }, function(err, existingEmailUser) {
if (existingEmailUser) {
console.log('There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' );
done(err);
} else {
var user = new User();
user.email = profile._json.email;
user.google = profile.id;
user.tokens.push({ kind: 'google', accessToken: accessToken });
user.profile.displayName = profile.displayName;
user.profile.gender = profile._json.gender;
//user.profile.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large';
user.profile.location = (profile._json.location) ? profile._json.location.name : '';
user.save(function(err) {
done(err, user);
});
}
});
});
}
}));
I am stuck on it.Please help me out..thanks
The problem is not in your "snippet", look at the routes. It should be absolute path on redirect for google.
router.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '#/signIn' }),
function(req, res) {
// absolute path
res.redirect('http://localhost:8888/#/home');
});
It's known issue, follow this link to other workarounds
https://github.com/jaredhanson/passport-google-oauth/issues/82
I have come across this issue. The exact problem is your route.
app.get('/auth/google/callback', passport.authenticate('google'), (req, res) => {
res.send('get the data');
});
At this point app had got user permission and google send a code to this url. Now what passport does here it took that code and made a request to google for user details and got it from google. Now we have to do something with this details otherwise you will get the error that you have got.
Now we can use serialiseUser and deserialiseUser of passport to save details in cookie and edit one line of above code to go at some url like that.
app.get('/auth/google/callback', passport.authenticate('google'), (req, res) => {
res.redirect('/servey'); // just a url to go somewhere
});
I also had the same problem since few days. What I figured out is, you just need to complete the process. Until now you have only checked whether the user is present in the database or not. If not then you save the user to the database.
However, after this, when the google tries to redirect the user, the code that google+ API sent is already used or say it is no longer available. So when you check the user in your database, you need to serialize the user i.e store the code into your browser in a cookie so that when google redirects the user, it know who the user is. This can be done by adding the code given below.
//add this in current snippet
passport.serializeUser(function(user,done){
done(null,user.id);
});
To use this cookie, you need to deserialize the user. To deserialize, use the code given below.
//add this in current snippet
passport.deserializeUser(function(id,done){
User.findById(id).then(function(user){
done(null, user);
});
});
Also, you are required to start a cookie session and you can do this by adding the below code in your main app.js file.
const cookieSession = require('cookie-session');
app.use(cookieSession({
maxAge: 24*60*60*1000, // age of cookie, the value is always given in milliseconds
keys:[keys.session.cookiekey]
}));
//initialize passport
app.use(passport.initialize());
app.use(passport.session());
Note that you need to require the cookie-session package. Install it using
npm install cookie-session
Also, you require to write absolute URI in the callbackURL property in your google strategy.
I had the same problem.
Reseting client secret from google console solved the problem.

node.js what is User in passport.js

I'm trying to make Node.js auth through steam API. I've installed passport-steam
passport.use(new SteamStrategy({
returnURL: 'http://localhost:3000/auth/steam/return',
realm: 'http://localhost:3000/',
apiKey: 'your steam API key'
},
function(identifier, profile, done) {
User.findByOpenID({ openId: identifier }, function (err, user) {
return done(err, user);
});
}
));
What is User in function?
User here is a mongoose user model.
You can read about mongoose in the docs. Mongoose is an ORM for a MongoDB database.
Passport in fact can use any store you would like and the User model there is just an example of how you can get the user and call done callback.

NodeJS Passport local strategy inform client user is authed

I have implemented Passport with passport-local and MongoDB and it is working nicely.
However this is a pure client-side single-loading app and so node is not responsible for the rendering of html. So currently I show a loading a spinner on app load and make a separate call to an api to determine if the user is logged in to conditionally render some stuff:
router.get('/me', function (req, res) {
res.send(req.isAuthenticated() ? {} || 401);
});
Since passport already authenticates my routes and calls deserializeUser this seems pointless - I need a way to pass an extra piece of info (in the cookie?) stating that the user is authed, I am guessing in deserializeUser?
server.use(session({secret: settings.sessionSecret}));
server.use(passport.initialize());
server.use(passport.session());
....
passport.use(new LocalStrategy(
localOpts,
function(email, password, done) {
User.findOne({
email: email,
activated: true
}, function (err, user) {
....
});
}
));
passport.serializeUser(function (user, done) {
done(null, user._id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
Note that the two cookies that get created when sign in is successful:
express:sess
express:sess.sig
When it detects the presence of these cookies it seems to just call deserializeUser hence why I think I could possibly communicate to the client the user is authed there, or otherwise on sign in inside passport.use middleware?
It turns out that I can simply add a middleware after the passport.session. I was concerned that req.isAuthenticated would fire off another query to the db but it doesn't:
server.use(function(req, res, next) {
res.cookie('isAuthenticated', req.isAuthenticated());
next();
});

understanding passportjs authenticate method

I am having an hard time understanding how passportjs authentication method works, in particular with the http-bearer strategy.
So I have two routes, one for registration and one for accessing user's profile, which goes through passportjs middleware. Have a look at the following code:
exports.register = function(req, res){
User.schema.statics.generateUserToken(function(t){
var user = new User({
token: t,
name: 'john doe',
});
user.save(function(e){
res.json(user)
});
});
};
My authentication strategy is as follow:
var mongoose = require('mongoose'),
passport = require('passport'),
BearerStrategy = require('passport-http-bearer').Strategy;
passport.use(new BearerStrategy(
function(token, done) {
User.findOne({ token: token }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
return done(null, user, { scope: 'read' });
});
}
));
as you can see, when a user requests the registration, my server returns him his object, with its token that should be locally saved.
Then, in a protected route, I added the passportjs middleware, like this:
app.get('/me', passport.authenticate('bearer', { session: false }), routes.me);
where I obviously get an unauthorized error. Why is this' where does passport.authenticate get the token from my client?! This is really confusing for me and is driving me mad. Any help?
Also, is this the right way of doing token authorization? Or do I also need some more details like timestamp, expires, etc.?
could you please refer http-bearer's sample code: https://github.com/jaredhanson/passport-http-bearer/blob/master/examples/bearer/app.js to refactor your codebase. I think here is very clearly definition.

Resources