how to generate cookie using node js , I am using express-session node plugin to generate the cookie .please tell me where I am doing wrong
install express-session plugin
app.js
const session = require('express-session');
app.use(session({
secret: 'asdassadsazz',
resave: true,
saveUninitialized: true,
//cookie: { secure: true }
}));
app.use(passport.initialize());
app.use(passport.session());
passport.js
passport.serializeUser(function(id, done) {
console.log('ddd');
// console.log(user);
done(null, id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
controller.js
register: async (req, res, next) => {
console.log(req.body);
try {
const result = await db.User.create({
email: req.body.email,
password: req.body.password
})
console.log(result.id);
req.login(result.id,function () {
res.json({message:"Registration successfully"});
})
} catch (e) {
console.log(e)
}
},
It should generate cookie and store in browser,but it is not generating any cookie.
server log
Executing (default): SHOW INDEX FROM `Users` FROM `sql12252060`
app is running on 5000
OPTIONS /users/register 204 1.943 ms - 0
{ email: 'a#g.com', password: '1' }
email element
Executing (default): INSERT INTO `Users` (`id`,`email`,`password`) VALUES (DEFAULT,'a#g.com','$2a$10$zhTaqEbEeMOaD8F..CQYRufALc5dD4l899qMKRw0QRxIWvrPMSlpq');
17
ddd
POST /users/register 200 932.036 ms - 39
is the issue of different domain .my server is running on 5000 port and client is running on 3000
Please note that secure: true is a recommended option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If secure is set, and you access your site over HTTP, the cookie will not be set. If you have your node.js behind a proxy and are using secure: true, you need to set "trust proxy" in express:
var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
resave option should be false.
resave:
Forces the session to be saved back to the session store, even if the session was never modified during the request. Depending on your store this may be necessary, but it can also create race conditions where a client makes two parallel requests to your server and changes made to the session in one request may get overwritten when the other request ends, even if it made no changes (this behavior also depends on what store you're using).
The default value is true, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case. Typically, you'll want false.
How do I know if this is necessary for my store? The best way to know is to check with your store if it implements the touch method. If it does, then you can safely set resave: false. If it does not implement the touch method and your store sets an expiration date on stored sessions, then you likely need resave: true.
Related
I have 2 routes on the backend of my app.
The first one sets a session using redis and using a different route i try to retrieve the session that was saved prior. However, when trying to retrieve the session, i get a different one from the one i created.
this is how i create a session and assign a property to it:
app.post("/login", (req, res) => {
req.session.userId = 1
});
and this is how i try to retrieve it:
app.get("/cookie", (req, res) => {
res.json(req.session);
});
But when the req.session of the get request is logged, I get one without the property userID.
Even though, i am able to view the key and value of the session using the redis-client with the keys and mget command.
this is how the cookie and session is configured
app.use(
session({
name: "cookie",
store: new RedisStore({ client: redisClient }),
secret: "xxxxx",
resave: false,
saveUninitialized: false,
cookie: {
secure: false,
httpOnly: false,
maxAge: 1000 * 60 * 10,
},
})
);
and this is the redisClient:
const redisClient = redis.createClient({
host: "localhost",
port: 6379,
});
How do I properly retrieve the session that i set on the post request? Am I using redis entirely wrong or am i just missing something?
Thanks!
I have a problem saving data to the Express Session middleware. I am using a Vue.js frontend to communicate with the server which is running at localhost:8080. The server runs on localhost:3002.
I suspect that the interaction between the Vue app and the server may be the source of the problem as I have tried tests with a bare bones Express app that serves HTML as simple template literals and req.session.save() works fine.
Here is my code.
vue.config.js
module.exports = {
"transpileDependencies": [
"vuetify"
],
devServer: {
"https": true
}
}
index.js(Express server)
const corsOptions = {
origin: 'https://localhost:8080', // Have tried with and without these options
credentials: true,
};
app.use(cors(corsOptions));
// Set up app to use session
let sess = {
secret: 'What secret?',
resave: false, // Tried true
saveUninitialized: false, // Tried true
cookie: {secure: process.env.NODE_ENV=="prod",httpOnly: false}, // Tried true
store: MongoStore.create({ mongoUrl: process.env.DB_URL,
ttl: 14 * 24 * 60 * 60 }) // = 14 days. Default
}
app.use(session(sess));
Login route where data is being set to the session.
app.post('/api/login', async (req, res) => {
...
request(options, function (error, response) {
if (error) throw new Error(error)
let fm_res = JSON.parse(response.body)
req.session.FM_TOKEN = fm_res.response.token
req.session.save()
console.log('TOKEN STORED IN SESSION :: ', req.session) // token present in session here
res.json({message: 'Token saved in session...', status: 200})
});
});
Separate route where token is not accessible.
// CHECK AUTH
app.post('/api/token_auth', async (req, res) => {
let authToken = req.session.FM_TOKEN
console.log('TOKEN FROM SESSION : ', authToken) // undefined
....
});
I have researched and tried various solutions suggested here on SO but nothing I have found from any answers has worked. Can anyone point me in the right direction to solve this one as I am out of ideas. Thanks in advance.
UPDATE
I have tested the above endpoints with with Postman and they work, i.e. the /api/token_auth has access to the token saved on the session. So, it appears the problem might be connected to the fact that my frontend is not using https but http to make these calls.
I have tried using httpOnly: false setting in the session.cookie as suggested in this SO answer, but it still doesn't work. I am out of ideas.
Does anyone know how https requirement can be circumvented for development purposes?
I have used this and it works but still, I am not clear that what resave and saveUninitialized are? I have read all the theories but still, I don't get it.
In the light of my code, how should I play with it so I understand the usage of these 2 properties?
Code:
var express= require('express')
var eApp= express();
var session= require('express-session');
var bodyparser= require('body-parser');
eApp.use(session({secret: 'hunainkey', resave: false, saveUninitialized: false}));
//eApp.use(cookieParser());
eApp.use(bodyparser.json());
eApp.get('/get/:user', (req, res) =>
{
req.session.user= req.params.user;
res.send("Session set");
});
eApp.get('/', (req, res) =>
{
res.send(req.session.user);
});
eApp.listen(1000, () => console.log('nodeapp5 is listening on port 1000'));
Check express session option documentation for more information
https://github.com/expressjs/session
saveUninitialized
Forces a session that is "uninitialized" to be saved to the store.
resave
Forces the session to be saved back to the session store, even if the session was never modified during the request.
User cfl also explains here
https://stackoverflow.com/a/36688600/3151646
(Unmodified 'state' is different to uninitialized state)
resave: For any request made
Nothing in the session needs to change (no login etc).
Change of session required (logged in)
"Forces session to be saved even when unmodified"
saveUninitialized: Is about the state of the session, if its still in the uninitialized state.
Not modified only, nothing in the session needs to change (no login etc).
"Forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified."
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 am still quite new to node and am experimenting with session management using express + redis.
My current project requires the user to be redirected to an external site to authenticate. After authentication, the browser is redirected to a callback url that i've specified. I require session data to persist across the redirect.
My implementation is as follows:
User triggers POST call to nodeJS server, where I persist data to session by req.session.foo = 'bar' and then return an auth_url to the browser.
Browser redirects using window.location.replace(auth_url); to external site for authentication
After authentication, browser is redirected to localhost:3000/mycallbackurl which is a route defined below (pardon the poor formatting):
router.get('/mycallback', function(req, res) {
console.log("data at callback: " + req.session.foo);
//do other stuff
});
My problem now is that the console prints: data at callback: undefined at the callback route.
Is this a problem with my redis setup, or am I just missing something here?
So far i've ascertained that redis is working by incrementing a value stored in req.session on each browser refresh and printing it.
My redis setup is as follows:
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
app.use(cookieParser());
app.use(session({ store: new RedisStore({
host: 'localhost',
port: 6379,
db: 1,
cookie: { maxAge: (24*3600*1000*30)},
}), secret: 'keyboard cat',
saveUninitialized: true,
resave: true
}));
Thanks for reading and look forward to your replies!
After a redirect (res.redirect), the res and req objects are recreated. That means if you added any parameters to these objects, you need to be sure they are re-added to the req or res objects on each request.