How to save data in expressjs/session NodeJS - javascript

I have 3 files : app.js, index.js(routes), Users.js(controller)
Once my user is loggedIn (verification done between POST information and DB) i want to save data in a session using expressjs/session.
Here is the declaration of my session in the app.js :
var session = require('express-session');
app.use(session({
resave: true,
saveUninitialized: true,
secret: 'trolololo'
}));
Here are my routes :
router.post('/login', function(req, res, next) {
Users.login(req, res);
});
router.get('/getSessionInfos', function(req,res,next){
console.log(req.session);
});
And here is the controller for the login :
login : function(req, res){
var formEmail = req.body.email;
var formPassword = req.body.password;
User.findOne({ where: {email: formEmail} }).then(function(user) {
if(user){
if (user.password == formPassword){
console.log('User connected');
req.session.email = formEmail;
req.session.password = formPassword;
console.log(req.session);
res.status(200).send('User Authentified');
}else{
res.status(401).send('Invalid Password');
}
}else{
res.status(401).send('Username');
}
});
},
The Login works I get the 200 status and my console.log in the login function displays a function with my infos. But when i try fetching my session from the /getSessionInfos URL it is empty... Please send help

I know you did not ask this, but i will state it either way, sessions are not recommended in node any more, json web tokens are pretty much the at the throne.In essence it's a signed piece of data in JSON format. Because it's signed the recipient can verify its authenticity. Because it's JSON it weights very little.
In very simple terms, JWT are cool because you don't need to keep session data on the server in order to authenticate the user.
The user calls authentication service, usually sending username and
password.
The authentication service responds with a signed JWT, which says who
the user is.
The user requests access to a secured service sending the token back.
Security layer checks the signature on the token and if it's genuine
the access is granted.
You can use jwt-simple in npm.

Your Code seems correct only some changes
app.use(session({
secret : 'yourSecret',
resave : false,
saveUninitialized : false,
}));
Not forget to login first as you are storing the session value over there and then it will surely display the object with the email and password key .
Let me know if You face any problem.

Related

isAuthenticated() returns false after successful redirect

From what I can conclude after leaving the backend port:5000 and redirecting to port:3000 (my frontend's homepage) the authentication session stops.
What I am doing:
clicking a sign in to google button, login with good account, redirect to my front end homepage where a fetch request runs and gets the logged in user profile information.
I am running a sign in with google oAuth with passport.js. Mongoose saves the session and user profile info. req.isAuthenticated() should equal true on all routes until logged out. instead Everything works until the very last point where I res.redirect to the front end home page.
app.get(
"/auth/google",
passport.authenticate("google", { scope: ["profile", "email"] })
);
app.get(
"/auth/google/login",
passport.authenticate("google", { failureRedirect: "/new" }),
(req, res) => {
console.log(` Authentication Status: ${req.isAuthenticated()}`); // READS AS TRUE
console.log(` User? : ${req.user}`); /// SHOWS USER INFO
console.log("end of user status before redirect.");
res.redirect("http://localhost:3000/");
}
);
THE PROBLEM:
On the last function from what I can tell everything works as it is supposed to right up until the res.redirect. unless I put in the command req.logout() It should be able to keep track of my session and on the backend req.isAuthenticated should equal true. Instead in other routes where I have conditionals setup req.isAuthenticated is reading false.
// quick fetch request I run on front end to show user as logged in and profile info.
app.get("/getuser", (req, res) => {
console.log("user CHECK :", req.user); // READS UNDEFINED HERE
console.log(`is authenticated:`, req.isAuthenticated()); // READS FALSE HERE
if (req.isAuthenticated()) {
const user = req.user;
console.log("user:", req.user);
res.json({ user: user, isAuthenticated: true });
} else {
const user = false;
console.log("user:", req.user);
res.json({ user: false, isAuthenticated: false });
}
});
It gets stranger...
My browser receives the connect.sid cookie and my database saves the user and session.
from chrome browser cookies on localhost:
screenshot of saved account created from session in my database
I have checked quite a few Stack Overflow threads already on this. All of them did not seem to help me.
My incident had everything to do with ports not the session. My react app runs on port 3000 by setting up a proxy in my package.json file using the syntax "proxy":"http://localhost:5000" I was able take all my routes and translate them over to my express routes and then return its authorized redirect url.

How to Request User Data after Logged In, Node.JS

Hello guys I'm new to Node so please bear with me.
Anyway I am currently working on authentication for my new Node app. So far I was capable of getting everything basic working (login, register, logout). I am now entering the settings page of my user profile but I cannot access {{username}} or {{email}} for example, it either stays blank or throws back an error.
I was wondering how I can make the username, email and other info stay in the session or able to access it once my user is logged in, and how I can add more information to the session later (this is important as I will need to do it).
Here is my code:
Registration (not including verification)
var newUser = new User({
username: username,
email:email,
password: password
});
User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
req.flash('success_msg', 'You are registered and can now login');
Login:
router.post('/login',
passport.authenticate('local', {successRedirect:'/', failureRedirect:'/users/login',failureFlash: true}),
function(req, res) {
res.redirect('/');
});
I'm not sure exactly what code I need to show but if you guys need to see anything else to help me please let me know.
I'm using Node.JS with express, passport and handlebars.
Thank you!
I was wondering how I can make the username, email and other info stay
in the session or able to access it once my user is logged in, and how
I can add more information to the session later (this is important as
I will need to do it).
There is a pretty good NPM module for this use case :
https://github.com/expressjs/session
I have made quite good experiences with it.
Just install it via NPM and then :
var session = require('express-session')
This is how you use it:
// Use the session middleware
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
// Access the session as req.session
app.get('/', function(req, res, next) {
if (req.session.views) {
req.session.views++
res.setHeader('Content-Type', 'text/html')
res.write('<p>views: ' + req.session.views + '</p>')
res.write('<p>expires in: ' + (req.session.cookie.maxAge / 1000) + 's</p>')
res.end()
} else {
req.session.views = 1
res.end('welcome to the session demo. refresh!')
}
})
As i am getting from your description is that you have problem regarding sessions.
for this you can visit https://www.npmjs.com/package/session-storage to Include session-storage into your project it will help you better.

Passport ensureAuthenticated

I want to implement a login with Passport.js and Github Strategy. Here is the code I use:
...
/* Ensure Auth function */
function ensureAuthenticated(req, res, next){
if (req.isAuthenticated()) return next()
else res.redirect('/');
}
/* Some modules */
global.passport = require('passport');
global.GithubStrategy = require('passport-github2').Strategy;
global.util = require('util');
global.session = require('express-session');
global.bodyParser = require('body-parser');
global.methodOverride = require('method-override');
global.partials = require('express-partials');
global.request = require('request');
/* Passport */
passport.serializeUser(function(user, done){
done(null, user);
});
passport.deserializeUser(function(obj, done){
done(null, obj);
});
passport.use(new GithubStrategy({
clientID: config.githubID,
clientSecret: config.githubSecret,
callbackURL: config.githubURL
},
function(accessToken, refreshToken, profile, done){
process.nextTick(function(){
return done(null, profile);
});
}
));
app.use(partials());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(session({secret: 'keyboard cat', resave: false, saveUninitialized: false}));
app.use(passport.initialize());
app.use(passport.session());
/* Controllers */
app.get('/auth/github', passport.authenticate('github', {scope: ['user:email']}), function(req, res){});
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/' }), function(req, res){
res.redirect('/dashboard');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
I search a lot in Passport.js docs, but I can't find answers for this questions:
Why, in my case, the session doesn't save the authentification? For example, if I set the ensureAuthenticated middleware on a route, it always redirect me to /, where is the login form.
Why I can't access user info from req.user to see user infos?
Why the logout route doesn't work?
Foreword/Preamble
I had the same issue with the Local Strategy. I don't have much information on the architecture of your system, however my system used the following:
PassportJS (w/ Local Strategy)
ExpressJS handling sessions & routing (w/ a Redis MemoryStore)
NodeJS server
AngularJS 2 frontend
Things to checkout
CORS played a major role with this issue.
I used the cors library to alleviate the issues I had there. In particular, I made the following change to the configuration:
let cors_config = {
origin: "http://localhost:8080",
credentials: true
};
This configures your CORS settings to include the Access-Control-Allow-Credentials: true header in the preflight requests.
Make sure your memory store & session is configured correctly
Start off by not having a specified memory store (the default is the LocalStore) and work from there onwards. I see you're not using one now, so just read on anyway.
server.use(session({
secret: "secret_c0de",
resave: false,
saveUninitialized: false//,
//store: new redis_store(redis_settings)
}));
Check to see if, when you're authenticating, that afterwards your session cookie is returned after authenticating. It should contain a key-value with a key of 'connect.sid', your session ID.
If you're not getting a session cookie, then you know that your session might not be configured correctly, in which case you should:
Check the load order of your 'use' calls
Try and identify any errors or issues with your session handling code
If you're receiving your cookie, but the isAuthenticated() check is failing in subsequent requests, this usually hints at your MemoryStore not working.
If you're initially using a LocalStore, this doesn't require much configuration, and thus again, hints to an issue with your session configuration
If you're using a store like Redis, try and listen to the Redis events (mainly 'connect' and 'error') and log the output to the console so you can see if it's working at all.
Thing's I noticed in your code
Check your serialization functions, you're serializing the entire user object.
This is more of an optimization, but have noticed people have had more success just serializing the user's ID and deserializing it.
passport.serializeUser(function(user, done){
done(null, user.id);
});
passport.deserializeUser(function(obj, done){
User.findById(obj, function(err, user){
if(err){/*code to handle error with not finding user*/}
done(null, user);
});
});
You should require the cookie-parser since sessions use a session cookie.
To answer your questions
Why, in my case, the session doesn't save the authentification?
Session creation is broken in your application, so you should try and debug this. As mentioned above, you should check if the session ID is being returned in a session cookie after your authentication request and move on from there.
Why I can't access user info from req.user to see user infos?
The user is injected after a successful deserialization attempt from Passport. In your case, the session is never created in the first place, never serialized into your MemoryStore, and thus can never be deserialized (since it doesn't exist).
Why the logout route doesn't work?
req.logout() will only work on a successful session being created.
Judging by the other code and info you provided, I assume that's what you're referring to.
Hope you find some valuable information here, feel free to comment if you'd like to chat about something in particular! :)
The best source to understand and implent the code for passport based authentication was here. check it once
https://www.coursera.org/learn/server-side-development/lecture/Clovu/passport

MEAN stack facebook login

I am trying to deploy an application that uses passport facebook strategy. I've been testing my app on localhost first and then tried to deploy it to AWS.
Everything seemed working fine on my local machine, but when i deployed i tried logging in with multiple facebook accounts.
I saved the received variables in an api call and retrieved those via angular
However, my first authenticated user, everything seems working fine, but when the second user authenticates it will override his variables like username, profile image etc.
I know why it is doing this. But i don't immediatly have a solution in mind.
Here is my server side code when i authenticate
app.get('/login/facebook',
passport.authenticate('facebook'));
app.get('/login/facebook/return',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
UserID = req.user.id;
UserDisplayName = req.user.displayName;
UserProfileImage = req.user._json.picture.data.url;
console.log(req.user._json.picture.data.url)
var User = UserID + UserDisplayName;
var ProfilePicture = UserProfileImage
res.json({name: User , url: ProfilePicture});
});
app.get('/profileInfo', function(req, res){
var User = UserID + UserDisplayName;
var ProfilePicture = UserProfileImage
res.json({name: User , url: ProfilePicture});
});
How do you store your users?
From your code i quess that you save your user's id in UserID variable but when next user logs in it will get overwritten.
I'm only quessing since i can't see your whole code but try something like this:
var users = {};
app.get('/login/facebook/return',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
// save user to users object
users[req.user.id] = {
displayName: req.user.displayName,
profileImage: req.user._json.picture.data.url
}
res.redirect('/');
});
// you need to use some kind of sessions or cookies to know which user this is
// for simplicity let's assume you get profile by user's id /profileInfo/:id
app.get('/profileInfo/:id', function(req, res) {
res.json(users[req.params.id]);
});

Link Twitter Account with Passportjs after local user auth is completed with passportjs

I just want to link twitter account after there is still user.
Firstly i have a router.js like that
// GET Registration Page
router.get('/signup', function(req, res){
res.render('register',{noty: req.flash('message')});
});
// Handle Registration POST
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/connect_twitter',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Twitter Auth*/
router.get('/login/twitter', passport.authenticate('twitter'));
router.get('/login/twitter/return',
passport.authenticate('twitter', { failureRedirect: '/' }),
function(req, res) {
res.redirect('/home');
});
if its success, i redirected "/connect_twitter" with req.user != null
, that is current user. In the "/connect_twitter" a redirect twitter with a button.
When twitter return user's tokens, i use this strategy
passport.use(new TwitterStrategy({
consumerKey: config.twitter.consumer_key,
consumerSecret: config.twitter.consumer_secret,
callbackURL: config.tw_callback
},
function(token, tokenSecret, profile, cb) {
// In this example, the user's Twitter profile is supplied as the user
// record. In a production-quality application, the Twitter profile should
console.log(profile);
findOrCreateUser = function(){
// find a user in Mongo with provided username
User.findOne({'tw_user_id': profile.id}, function(err, user) {
// In case of any error, return using the done method
if (err){
return cb(err);
}
// already exists
if (user) {
user.tw_token = token;
user.tw_token_secret = tokenSecret;
user.save(function(err){
if (err) {
throw err;
}
console.log("User Updating successfull !");
})
return cb(null, user);
} else {
// create the user
var newUser = new User();
// set the user's local credentials
newUser.password = createHash(token);
newUser.username = profile.username;
newUser.email = null;
newUser.tw_token = token;
newUser.tw_user_id = profile.id;
newUser.tw_token_secret = tokenSecret;
// save the user
newUser.save(function(err) {
if (err){
console.log('Error in Saving user: '+err);
throw err;
}
console.log('User Registration succesful');
return cb(null, newUser);
});
}
});
};
process.nextTick(findOrCreateUser);
}));
The problem is how to access current_user or anything about the current user in this function function(token, tokenSecret, profile, cb)?
As i think, If i access that, i linked current user with these tokens.
Or
Is there better (any) way to link twitter with the current user ?
Thanks in advance..
In the passportjs docs
Association in Verify Callback
One downside to the approach described above is that it requires two instances of the same strategy and supporting routes.
To avoid this, set the strategy's passReqToCallback option to true. With this option enabled, req will be passed as the first argument to the verify callback.
passport.use(new TwitterStrategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: "http://www.example.com/auth/twitter/callback",
passReqToCallback: true
},
function(req, token, tokenSecret, profile, done) {
if (!req.user) {
// Not logged-in. Authenticate based on Twitter account.
} else {
// Logged in. Associate Twitter account with user. Preserve the login
// state by supplying the existing user after association.
// return done(null, req.user);
}
}
));
With req passed as an argument, the verify callback can use the state of the request to tailor the authentication process, handling both authentication and authorization using a single strategy instance and set of routes. For example, if a user is already logged in, the newly "connected" account can be associated. Any additional application-specific properties set on req, including req.session, can be used as well.
By the way, you can handle with the current user and its data to link any social strategy including Twitter.
You can do that in 2 ways:
Instead of trying to get req.user inside Twitter Strategy, you can get user email fetched from twitter response and match it with user with same email inside database. Normally, you cannot get email directly from Twitter API, you need to fill request form here to get elevated access. After request accepted, you will be able to get email from Twitter API.
After twitter login, you can save user twitter profile information inside a temp table and redirect a page like /user/do_login?twitter_profile_id=<user_twitter_profile_id_fetched_from_twitter_response>. When you redirect to /user/do_login you will be able to access req.user and also you will have user profile id. In this action, you can grab user profile info from temp table and merge it with req.user. By the way, I assume that, you are using stored session.

Categories