app.use(express.cookieSession());
...
res.cookie('username', userName, { httpOnly: false});
console.log(res.cookie);
Logs this text:
[Function]
Which is not something that I have seen before. I am a little bit confused about how to set and get cookies in express.
res.cookie is a function. You are using it to set the cookie in
res.cookie('username', userName, { httpOnly: false});
So your console.log is right.
To see the cookie after you set it you'll need to refresh your browser and then outputting req.cookies or req.signedCookies will show you the contents of the cookie that was set.
Take a look at the last line of the cookie section in express guide
Cookies in Express can be read from from req.cookies.
i.e
app.get('/foo', function(req, res){
console.log(req.cookies);
res.send(200);
});
Also, don't forget to include the cookie parser middleware.
Related
I´ve a problem by saving something in the session above a NodeJs Script. If I start the script and making a post login like this:
app.post('/login', function(req, res) {
sess = req.session;
sess.key = "SecureKEy";
console.log(sess);
});
I got as rusult that what I want:
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
key: 'SecureKEy' }
But if I reload the page with this code the session.key is empty. Just like it´s not saved.
app.get('/', function(req, res) {
sess = req.session;
console.log(sess);
res.sendFile(__dirname+'/wwwroot/index.html');
});
My configuration for the express-session is this:
const session = require('express-session');
app.use(session({
secret: 'importent',
resave: true,
saveUninitialized: true
}));
I´ve rewrite the code like this:
app.post('/login', function(req, res) {
console.log("Before: ");
console.log(sess);
sess = req.session;
sess.key = "SecureKEy";
req.session.save();
console.log("After: ");
console.log(sess);
});
With that it work correctly. But if I would resend the logged in page with res.send the session would be automaticly saved? Is that correct?
express-session auto-save edge cases?
The express-session save(...) method is certainly not triggered for some express response transport methods. It seems to trigger consistently for the frequently encountered ones such as response.send(...), response.json(...) etc.
But same is not the case for the special case transport method such as the express.response.end() method - from my observation at least; and also response.sendFile(...) according to the OP and response.redirect(...) according to posts elsewhere.
To avoid unforeseen issue, pay close attention when applying express-session to requests where special case response transport methods were used. The express-session save(...) method may have to be called directly to persist changes made during those requests. Even then, there is no guarantee that persistence would take place.
For example, there are occasions where setting values to null and/or calling the session.destroy(...) and/or session.regenerate(...) methods have no effect. Those destructed session data basically resurface on the next page refresh. Not even calling the save(...) method or setting the unset option to 'destroy' can remedy that situation.
The express-session readme should include these edge case scenarios in one of its Note sections at the top of the page. It would curb some of the headwinds surrounding its auto-save feature.
My philosophy to this type of thing is: when a package is too quirky for a use-case, either find a more suited package or just source your own solution if possible. Workarounds tend to warp application logic thereby making it error prone and difficult to maintain over time.
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
I'm trying to set a cookie in the express framework, but it isn't going through, and for the life of me I can't figure out why. The relevant code looks like this:
module.exports = function(app) {
return function(req, res, next) {
if (req.cookies.user_token) {
req.session.cookie.httpOnly = false
res.cookie('user_token', req.cookies.user_token, { domain: 'www.example.com', httpOnly: false, path: '/', maxAge: 900000 });
}
return res.redirect('https://www.example.com/index.jsp?other_stuff=value');
}
}
I can see the request going out, and that cookie is NOT getting set. I've stepped through with a debugger, and I know for certain that code is getting hit.
I found this question:
How to set cookie in node js using express framework?
Based on that, I tried calling var express = require('express'); app.use(express.cookieParser()); earlier in the code, but it didn't seem to make any difference.
Anybody have any ideas where I'm going wrong here?
If the redirected domain (say, www.example.com) is (as indicated in the comments) different from the domain that is trying to set the cookie (say, www.foo.io), then the cookie will not be honored by the browser.
I'm trying to set up a basic session system in node. Here's what I've got so far:
app.js:
app.use(express.cookieParser('stackoverflow'));
app.use(express.session());
I'm setting the session data in ajax.js:
addClassToCart: function(req, res) {
req.session.cart = req.body.classId;
console.log(req.session.cart);
}
This logs the correct information. However, when I try to retrieve that information elsewhere (same file, different function):
console.log(req.session.cart);
I get undefined. I feel like I'm missing something incredibly basic. Various tutorials for this are either awful or require me to add in even more packages (something I'm trying to avoid).
More data from my debugging:
This works with non-AJAX requests
The session is set before it's logged.
As it turns out, the issue wasn't with Express' session (as the other answers seem to think). Rather, it was a misunderstanding on my part. I changed addClassToCart to the following:
addClassToCart: function(req, res) {
req.session.cart = req.body.classId;
console.log(req.session.cart);
res.send('class added');
}
Adding res.send() fixed the problem.
As noted in the answer to a related SO question, this can also occur if you're using fetch to get data from your server but you don't pass in the credentials option:
fetch('/addclasstocart', {
method: 'POST',
credentials: 'same-origin' // <- this is mandatory to deal with cookies
})
Cookies won't be passed to the server unless you include this option which means the request's session object will be reset with each new call.
I don't know about basic session store, but redis only took me a few minutes to setup:
app.use(express.session({
store: new RedisStore({
host: cfg.redis.host,
db: cfg.redis.db
}),
secret: 'poopy pants'
}));
On a mac:
brew install redis
app.use(express.session({
secret: "my secret",
store: new RedisStore,
cookie: { secure: false, maxAge:86400000 }
}));
Not sure the problem is in session age, but it just to be safe, I'd suggest you to specify maxAge.
so I basically want to use sessions to store the users name and check to see if the user logged in or not. If not, the page will redirect to the login page.
I am using Node.js,express,and couchDB.
Here is how i set up my session so far
var MemoryStore = require('connect').session.MemoryStore;
app.use(express.cookieParser());
app.use(express.session({
secret: "keyboard cat",
store: new MemoryStore({
reapInterval: 60000 * 10
})
}));
To store something in the session, i use the following code right?
req.session = {user:name);
So the session variable seems to work on my login page. I successfully store the user's name into the session However, when I try to access the session variable on another page, it gives me the error
Cannot read property 'user' of undefined
all i'm doing is:
if (req.session.user){
Why is this error happening? are sessions not global to the whole app? Or am I missing something entirely here.
Thanks in advance!
If you're doing app.use(app.router) before the lines that set up the cookie and session handling, try moving it to after them. That fixed the same problem for me.
I was trying to solve the exact same problem for he last few hour.
Try initializing your server like that:
var app = express.createServer(
express.cookieParser(),
express.session({ secret: "crazysecretstuff"})
);
That should work.
I had same issue of getting undefined for session variable which I knew was set ok.
In my case it turned out to be caused by cross origin request, I had forgotten the withCredentials header on the request.
So for example in my client side Angular app I needed to do this:
var config = { withCredentials: true };
return $http.get(appConfig.apiUrl + '/orders', config);
and in Express this:
res.header('Access-Control-Allow-Credentials', true);
the sessionSecret in the configuration (config.json?) should be non-empty:
sessionSecret: "something other than an empty string",