In Nodejs how to get previous session data if cookie deleted - node.js

I want to get the previous session data if the user removes all his cookies manually or in other methods. Because i am storing some data in session and in my global too, and I need to remove that data from my global for every session destroyed.

If a user removes all his cookies, then he is a user without cookies, right? So how would you differentiate between this user and any other user? This is a very difficult problem and I doubt there is a reliable solution for it.
For example you might want to identify a user by IP, but IP might change ( dynamic IP ). You might want to identify user by creating WebSocket ( of FlashSocket ) connection and keep it open, but this will work only when user views your page ( and might be closed manually as well ).
So forget about previous sessions. If you need to clean session data, then create a CRON job or background thread ( or background asynchronous job in case of Node.JS ), which will do that periodically. Or you can just use passive cleaning, i.e. implement mechanism for sessions, that will clean itself when getting near the ( predefined ) memory limit ( this should fire when creating a new session ).

I just set the session to expire automatically in redis, so it will clean itself up over time. Unfortunately, I forget how I did this exactly, I think it's a property on the db.
When someone logs out, I destroy the session:
req.session.destroy(function(){
//session has been destroyed
});

Related

Is it safe to put the entire user in a session vs just the user ID for node/express?

I am using node/express and was wondering if it is safe to put the entire user object in the session rather than just the Id. If I do just the Id then this means I must make another DB call when I go to get the currentUser.
I have seen people do it, but if it is more safe to just put the Id then I will go about doing that. I should state that I would take the password off the user before attaching it to the session or any other sensitive data.
There's nothing especially unsafe about it, but generally not considered a good practice. When you update your user data, you have to update your session and database, so now you have to keep those in sync, which creates challenges.
Also keep in mind your session store. The more data in your session, the larger the storage requirements for your session store, maybe not a problem, but something to consider.

Remove session entries in redis upon cookie deletion on the user side

I have the following scenario:
A user logs in, a session entry via connect-redis which is valid for 2 weeks. The user can now access certain parts of the app using the session id that is stored in the app.
Now, if 1. the user deletes that cookie in the browser (with the session) and 2. logs in again - there are now 2 session entries in Redis associated with the same user, with the older one being obsolete.
What is the best way to deal with such old/obsolete sessions? Should I use a client library for redis, search through all sessions to find the ones that match the info of the currently logging in user (after she potentially manually removed the cookie), and purge these obsolete session; or is there a better way?
Gracias,
nik
That depends whether this (user deletes the cookie) is a common scenario and, if it is, whether there's a problem with obsolete cookies in the server.
Two potential "problems" that I can think of are:
Security - could the stale cookie be exploited for malicious intent? I do not see how that's possible, but I may be wrong(tm).
Storage - are the stale cookies taking too much (RAM) resources? If there's a lot of stale cookies and each cookie is large enough, this could become a problem.
Unless 1 or 2 applies to your use case, I don't see why you'd want to go through the trouble of "manually" cleansing old cookies. Assuming that you're giving a ttl value to each session (2 weeks?), outdated cookies would be purged automatically after that period so no extra action is needed to handle these.

NodeJS custom session Store, clear expired sessions

I am currently developing a session store for ArangoDB (connect-arango). It works almost identically to MongoDB session store (connect-mongo, hence 'connect-arango'), but the problem is that ArangoDB does not have a built in TTL for its entries.
MongoDB has this and it's not a problem there. But in ArangoDB, I have to do this in the session store somewhere.
Would checking for expired sessions every 60 seconds (using setTimeout) be sufficient, or should I use something else, like checking every time the "get" function is called?
I would use an AQL query to clear them, similar to this:
FOR s IN sessions
FILTER s.expires < DATE_NOW()
REMOVE s IN sessions
If the user were to clear his cookies, the session would never be accessed using the "get" function, which means I can't check if it has expired there.
What I can do however, is to run the above query every time the "get" function is called, but I think that would be quite unnecessary and put more load on the server.
Edit: Just so no one misunderstands, I know how to clear the expired sessions, I just don't know how often to run the clear function (in this case, it's the AQL query above).
If you put a skip-list index on expires, running the above query every 60 sec should not create any problems. You can also create a periodic job within ArangoDB that runs this query every minute.
Alan Plum has added a session Foxx app to ArangoDB which basically implements all of the above. I'm not sure if he has already released a documentation. The API documentation is visible as
localhost:8529/_db/_system/_admin/aardvark/standalone.html#!/sessions
If you have any questions about this Foxx application, please fell free to contact Alan at hackers (at) arangodb.org
As of ArangoDB 2.3 Foxx comes with a built-in sessions app you can use in your Foxx apps. You can re-use the session app even if you don't want to use Foxx.
You can simply mount a copy of the sessions app at a mount point of your choice. This allows you to configure the session TTL as well as other details (e.g. length of the session IDs). The app exposes an HTTP API that lets you create new sessions, update sessions, retrieve existing sessions and delete them. It automagically enforces the TTL (i.e. deletes expired sessions) when you try to retrieve or update a session.
Currently the TTL is only enforced whenever a session is accessed. Depending on your use case this may still clutter up the collection with expired sessions. Currently it's not possible to schedule recurring tasks directly inside ArangoDB; there's a job queue but it is not a good fit for this kind of problem. This will likely be solved in a future version of ArangoDB.
I would recommend monitoring over time the amount of expired sessions that pile up in the collection of your mounted copy of the sessions app. It's probably sufficient to prune the expired sessions once a week (or even less). As the sessions app will automatically delete expired sessions when they are accessed via its API, the only problem are abandoned sessions (e.g. private browsing mode, or one-time users).
Disclosure: I wrote the new sessions/auth apps introduced in ArangoDB 2.3.

How can I do something right before the session expire(destroy)

Hi I am using expressjs for my web application, and I use the session middleware, my question is that how I can do something right before the session expire?
For example, I store something in the session, and I set the req.session.cookie.maxAge to 60000(1 minute), when the session timeout, I want to save the data in the session to disk, how I can do this? I checked the API and the destroy function only support callback...
Thanks!
Assuming you're using connect-session there's nothing like session expiration event.
Sessions expire either :
on the client (when cookie gets outdated). There's no way to know about it until a request is made so there's a danger that the event will never get triggered.
in the session store, usually using some form of time-to-live. Not all session stores support events, so notification can't be done in general.
You can, however try implement your own check using setTimeout() - when it times out check if the session's expiration date is sufficiently close to now and do whatever you need to do.

Should Domain Entities always be loaded in their entirety?

I have a custom ASP.NET Membership Provider that I am trying to add password history functionality to. User's passwords expire after X days. Then they have to change their password to one that has not been used in their past X changes.
I already had the User entity, which has a password attribute for their current password. This maps to the User table in the db. Since I needed a list of previous passwords I created a UserPassword table to store this information with a FK reference to the UserId.
Since passwords are value objects, and have no meaning outside of the user, they belong inside the User aggregate, with the User as the root. But here in lies my dilemma. When I retrieve a User from the repository do I always have to get all of their previously used passwords? 99% of the time I don't care about their old passwords, so retrieving them each time I need a User entity seems like a dumb thing to do for db performance. I can't use lazy loading because the User entity is disconnected from the context.
I was thinking of creating a PasswordHistory entity but for the reason stated above, passwords aren't really entities.
How would you DDD experts out there handle this situation?
Thanks.
Edit 1: After considering this some more, I realized this is essentially a question about Lazy Loading. More specifically, how do you handle lazy-loading in a disconnected entity?
Edit 2: I am using LINQ to SQL. The entities are completely detached from the context using this from CodePlex.
It is hard to fully answer this question because you do not specify a platform, so I cannot be exactly sure what you even mean by "disconnected". With Hibernate "disconnected" means you have an object in a valid session but the database connection is not currently open. That is trivial, you simply reconnect and lazy load. The more complicated situation is where you have an object which is "detached" i.e no longer associated with an active session at all and in that case you cannot simply reconnect, you have to either get a new object or attach the one you have to an active session.
Either way, even in the more complicated scenarios, there is still not a whole lot to lazy loading strategies because the requirements are so inflexible: You have to be "connected" to load anything, lazy or otherwise. Period. I will assume "disconnected" means the same thing as detached. Your strategy comes down to two basic scenarios: is this a situation where you probably need to just reconnect/attach on the fly to lazy load, or is it a scenario where you want to make a decision to sometimes conditionally load additional objects before you disconnect in the first place?
Sometimes you may in fact need to code for both possibilities.
In your case you also have to be connected not only to lazy load the old passwords but to update the User object in the first place. Also since this is ASP.NET you might be using session per request, in which case your option is now basically down to only one - conditionally lazy load before your disconnect and that is about it.
The most common scenario would be a person logs in and the system determines they are required to change their password, and asks them to do so before proceeding. In that case you might as well just take care of it immediately after login and keep the User connected. But you are probably using session per request, so what you could do is in the first request process the time limit and if it is expired, you are still connected here so go ahead and return a fully loaded User (assuming you are using the historic passwords in some kind of client side script validation). Then on the submit trip you could reattach or just get a new User instance and update that.
Then there is always the possibility you also have to provide them with the option to change their password at any time. They are already logged in. Does not matter much here, you have a User but the request ended long ago and it does not have passwords loaded. Here, I would probably just write a service method where when they invoke a change password function the service gets a second copy of the User object with the full history for update purposes only, then updates the password, and then discards that object without ever even using it for session or authentication purposes. Or if you are using Session per request you have to do the equivalent - get a fully initialized object for client side validation purposes, then when the data is submitted you can either reattach either one you already have or just get yet a third instance to actually do the update.
If the password is needed after beginning an authenticated session, you could still do the same things and either replace the local User or update the local User's in memory password version as well.
If you have too much stuff going on with multiple levels of authentication most likely you are going to have to require them to logoff and do a full log back in after a password change anyway, so the state of the User does not matter much once they request a password change.
In any case if you are using session per request and your objects become fully detached after every request, in the first scenario you can still lazy load while you are on the server on the original request to return data for client side validation. In the second scenario you have to make another trip (there really is no such thing as lazy loading here). In both case though you have to weigh your two update options because you are always disconnected before an update. You can either just get a second instance from the database on the submit trip to update, or you can reattach the one you already have. It depends on what is optimal/easiest - does saving a db round trip for an uncommon event really matter? Does reattaching using your ORM of choice possibly hit the database again anyway? I would probably not bother to reattach and instead just get a new instance for the actual update as I needed it.

Resources