Managing http sessions, nodeJS - node.js

I am building an HTTP server in nodeJS (homework assignment), and I need to manage HTTP sessions with cookies - for each session I send a cookie with UUID (string ID) and then when I get it back I reset the session's timer.
My question: should I open a session for each request (i.e. even an image/css request for example) or for each page?
This is my code now:
socket.on('data',function(data) {
//some code
// if no UUID exsit in request, create one for it
var request = new REQUEST.Request(data, resourceMap, rootFolder); //
//response will send the UUID created/sent in request
var response = new RESPONSE.Response(socket,request);
session(request); // look for uuid from request in data base
}
Right now when I load a page, the html request is always the first and a new UUID is created for it, but not for the next requests (images etc) in that page.
Also, when I hit a link to another page no UUID is created.
Any ideas why? Where is the best place to check for an existing UUID and add one if its not there? thanks!

You should create a session for one session. :) Not each request.
In the session you can set an UUID.
There are plenty of resources out there to help you. If your professor has allowed you to use libraries, I'd highly suggest checking your options. This is just a few: https://github.com/joyent/node/wiki/modules
Because it's homework question, I think it's best that you only get some direction to the 'answer'
Good luck

Related

Handle Dialogflow requests from multiple users through ngrok

I'm working on a website for school, using Dialogflow, ReactJs and NodeJs. I am pretty new to doing this and I am not certain whether my implementation will work for my use case.
My website involves a game, which the server-side needs game state information from. I am sending requests from React to NodeJs as follows:
axios({
method: 'post',
url: '/game_state',
data: {'current_player': current_player}
// ... (more data is sent in reality)
}
);
My post requests are then handled by NodeJs as follows:
app.post('/game_state',express.json(),(event)=>{
current_player = event.body.current_player;
// ... (more data)
});
This data can then be accessed by a Dialogflow request. For example, if the user asks: "Who's turn is it?", an intent with webhook fulfillment can then be triggered. The code for that:
function turn(agent){
current_player == 1 ? agent.add("Your turn") : agent.add("My turn");
}
As I said before, I am not very experienced with developing websites. I want to be able to use my implementation with multiple users at the same time, so one user's game states shouldn't influence those of another user.
So far, I've been using (the free version of) ngrok to test my website. My implementation works perfectly fine if only one user is accessing the link. However, when I open the website twice on the same computer (using the ngrok-generated link) and interact with e.g. the turn intent, I notice that the turn response will be the same for both even if for one session, it's the player's turn and for the other, it's the chatbot's turn.
Most likely, the post request is being overwritten given that the same link is used. I would like to find a solution that makes it possible to use the same link but have the server keep the game state information separate for each user. I feel like this might be possible with a user ID, but I'm stumped on how to implement that.
I know something like this may be an option: app.get("/game_state/:id", ...), but I am not sure how to also get this information to be available for the Dialogflow part of the implementation. Dialogflow calls the server itself, so it doesn't pass this user ID with it. Somehow, I'd need to distinguish it there as well.
Any suggestions would be greatly appreciated!
When you make Dialogflow detected intent API call at that time you are creating a session path
const sessionPath = await sessionClient.projectAgentSessionPath(PROJECTID, sessionId);
If you pass session Id = 123456789A so for this Id Dialogflow managed all context and parameter on Id 123456789A
session Id = USER
when you get the webhook call to the server you also get this session Id or we also called UserId like
let userId = agent.session.split('/')[4]
you can find more information here
dialogflow session

Using Global.var in NodeJS to temporarily store redirect URL to use after OAuth callback

I have a nodejs app (http://app.winetracker.co) and I'm integrating OAuth logins. I think I can use a global.redirectURL var to temporarily store the redirect URL for use after the OAuth callback.
// url param passed to route /auth/twitter?redirectUrl=/path/to/location
app.get('/auth/twitter', function(req, res) {
var redirectUrl = req.param('redirectUrl');
global.redirectUrl = req.param('redirectUrl');
passport.authenticate('twitter', {})(req, res);
});
app.route('/auth/twitter/callback').get(users.oauthCallback('twitter'));
If I have 2 users logging into my app via OAuth at the same time, will the global.redirectURL values get overwritten by each user's redirect var value?
Essentially, are global values unique to each user or does everyone share the same global.redirectUrl var value?
If I have 2 users logging into my app via OAuth at the same time, will
the global.redirectURL values get overwritten by each user's redirect
var value?
Yes, they will get overwritten and doing it this way is a serious problem.
Essentially, are global values unique to each user or does everyone
share the same global.redirectUrl var value?
Global values are shared with your entire server so storing anything there is visible by ALL requests by all users that might be processing. You should pretty much never store this kind of temporary information in a global. If the auth code is async (which I assume it is), then you can easily have multiple requests trouncing/conflicting with that global. This is a bug ridden thing to do. You must change to a different way of solving the issue.
The usual solutions to this type of issue that do not have the vulnerability of a global include the following:
Use a session manager and place the data into the session for this particular browser so it can be retrieved from there during the redirect.
Put the information as a query parameter on the redirect URL so when the browser comes back with the redirect URL, you can parse it out of the query string then.
Coin a unique ID for this request, set it as a cookie and store the temporary data in a map using the ID as the key. Then, when the redirect comes back, you can use the cookie to get the ID and then lookup the value in the map. This is essentially a session, but it's special purpose just for this purpose. To be thorough, you also have to make sure your map doens't leak and build up over time so you have to probably store a timestamp and regular clean up the map by removing old values.

How to create sessions in a strong way and store them in cookies in node js?

In my login module once I log in I pass my request to a header to store a session here is the code
var series = rand.generate(16);
var token = rand.generate(16);
var loginToken = new LoginTokens({
userId: req.user._id,
series: series,
token: token
});
loginToken.save(function(err, l) {
if (err) {
console.log(err);
} else {
console.log(l);
res.cookie('loginToken', JSON.stringify({
series: series,
token: passwordHash.generate(token)
}));
res.status(200);
res.set('Content-Type', 'application/json');
res.end(JSON.stringify({
'success': req.params.res
}));
}
});
Though this code was pre-written and I don't understand it much(I don't get the point of randomly generating 16 digit number and saving it if somebody does please explain)
I have been tasked with implementing log out and As I don't understand the rationale behind above code I want to implement my own session module such that even if the same user logs in from a different device, both sessions will be maintained and logging out from one device will not log out someone from all device.
So now the point comes that the session id will not be based on user id. Also there is a module called express-session which I don't know if I should use or not, personally I feel that after reading it up on GitHub that what it will do is create a session id for me, which again I will have to save in my database, so why to import a module, instead I will base64 encode a random number like above and use it.
So what I want to ask is the real question
How do you implement sessions in node js?
My understanding of life cycle
A user signs up you see if he/she exists in the database and if he does you raise an error message and if he/she doesn't you create a username for him, probably by email id.
You then via code log him in. In that process, you first check if he is there in the database. If he is you go ahead take the _id field and try and create a session object. Ques what does your session table should look like? What all parameters should be present in sessions table? Then how do save them into res.cookies? Then what do you do with all those cookies, like on client side?
While implementing logout. My thinking is using passport.logout will remove the user object from request header but, I will have to first remove the entry from sessions table somehow empty the cookies and then do req.logout?
Can somebody please answer the above doubts?
I asked a very specific question but realised after the comment that what I need is logical clarity and I did not find one on youtube videos nor on SO posts, so if someone can share their views mostly in code, with some explanation it would be great.
Cookies get deleted by sending a new cookie with the same name (some invalid data would be good) and an expiry in the past.
passport.logout() removes the session cookie that passport uses to maintain the current user, the next request will no longer have the cookie and will appear as an invalid request.
I'm not sure why there's a loginToken as well as passport authentication, apart from allowing you to invalidate sessions server side (by deleting the appropriate token from the database) Check if your passport strategy configuration has any checks against LoginToken during it's deserialize user step (this is where passport takes the session cookie and turns it into a user against the request)

Authentication & Sessions in express.js/sails.js

Have been working through the sails cast tutorials and am confused about the way that sessions work.
In the tutorial, the user is marked as authenticated in the session controller by:
req.session.authenticated = true;
req.session.User = user;
res.redirect('/');
Why is the session being saved in the request?! My understanding is that the 'req' object in express.js is the information the browser sends to the server.
Shouldn't the server save this information elsewhere (won't the request object be deleted when theres another request?)
Furthermore, somehow the application retrieves the authentication status from another object session when templating a page with ejs:
<% if (session.authenticated) { %>
why isn't this variable set directly?
Probably a silly question but I am confused at how the logic works and online articles/tutorials aren't helping me understand...
It is common practice for express middleware (remember, Sails is built on express) to attach properties to the req object so it may be accessed in later middleware, and eventually your controllers. What happens behind the scenes is your req object comes in with a cookie containing the session ID, and then the session middleware uses that to retrieve the actual session data from some datastore (by default, and in-memory store is used. Super fast and easy for development, but not recommended for deployment), and then attaches that to the req object.
Regarding the value of session.authenticated in your EJS, by default Sails includes req.session in res.locals (accessible in views), so that value will be whatever is stored in the session via your controller.
The browser sends over the session id which is stored on a cookie. The session object is referenced by that session id which is stored server side. The session is attached to the request (for convenience I suppose). You can read more here https://github.com/expressjs/session#compatible-session-stores
I wouldn't know what is setting session.authenticated without seeing more code.

Does the request object in Node.js contain any navigator.userAgent type of information?

I've setup a Node.js server that gets some contact form data and forwards it to my email. I'd like to be able to forward some information about the user's browser along with the form data.
Is any of that information contained in the request object in some form ? Kind of like the navigator.userAgent string that is available on the client ?
Or should I include that string in the data sent out, manually, myself?
I was thinking of something like :
var httpServer = http.createServer(function (request, response)
{
var browserID = request.navigator.userAgent;
});
Thanks!
I was testing this out myself in express, and you can find the user-agent string in:
request.header['user-agent']
and you can see it in the HTTP specification in 14.43 here.
In the future, you can simply examine the request object either with console.log() or with the debugger and see exactly what's in it. I find that is often ultimately more educational than trying to find things in documentation somewhere.

Resources