General doubts about Express-session middleware - mongodb

I am a complete beginner in the web and I have a lot of stable doubts which I hope you won't mind answering.
Ques1: Sir how my MongoDB store is clearing a session after the max-age or expiry time? Does the driver of connect-mongo have some async function that is called as an event whenever the session is expired or the MongoDB server has a special meaning for sessions collection or MongoDB have build-in methods that are doing so with the help of some async functions and all?  I implemented this manually for learning purposes and it was fun but how this thing is happening in the Express-session part I am amazed and very confused. Who is taking care of the expiry thing and all?
Ques2: Sir I don't understand the resave thing. I have done a lot of googles and came to know about resave and saveUninitialsied. I know what saveUninitialised means. It says don't save a new session unless and until the cookie is modified. Cool thing. Then people went on explaining about resave on StackOverflow and touch method but I don't get from there. What does it even mean if the database does not have a touch command initialised? Also does the resaving and other stuff happens on the database or from the command of my server to the database. It's my servers command on the database right? Or something is going on under the hood.
Ques3: Sir if I want to send more than 1 cookie to the user in express-session, is it possible and is it a professional practice? Or should I use cookie parse with res.cookie to send more than 1 cookie? Also, can I change the name of connect.sid to something else which is my next question?
Ques4: Sir I wanted to know if I can store more key-value pair as key and JSON in the cookie so I did something like this but the data is not stored in MongoDB as far as I have checked. So is the data stored in the cookie?
//creating the session
app.use(session({
name: 'auth cookie', //Name of the cookie
store: new MongoStore({ mongooseConnection: mongoose.connection }), //To store session-store as Mongoose,
secret: process.env.COOKIE_SECRET, //Used to sign the cookie
saveUninitialized: false, //If the user bounces off, don't create a session
resave: false, //Touch method is implemented by MongoDB. I want to know more about this option
cookie: {
path: '/', //Where the cookies would be saved
httpOnly: true, //Javascript on client cannot get access to cookies. Good for security.
secure: false, //http service. Not strictly HSTS or HTTPS
maxAge: 60*1000, //1 minute
sameSite: true, //No XSRF
name: 'Hobbit Holet', //This is how values are stored in the cookie for furture use
age: '21' //This is how values are stored in the cookie for furture use
}
}));
Ques5: Sir as you can see I have a secret. Now I can see the cookies on my browser. Now the cookie has some data and I have the secret key. So for debugging purposes and only in development mode is there a way I can decrypt the data inside the cookie by the secret key I am having here? If there is a way please share the algorithm used to hash or encrypt the data before sending.
Thank you, everyone and I am open to constructive criticism if I wrote something wrong or did any mistakes on my part in asking the question. I hope to get help as I am stuck here for the day.

Related

Express-Session: Get Session with session ID

I'm fully aware that normally, with express-session, the session is returned with each request and there's no need to try to manage sessions. However, imagine for a moment, you have multiple applications each with different jobs, but you want your authentication to work with all your apps. So the problem there is, a session created on one app will not be magically replicated on all your other apps.
So what do you have to do? Presumably, you would need to query the app which created your sessions and get the session using it's ID. And you would store the session ID on the client via local storage.
I'm unable to find anything that would support this architecture (Micro-Apps instead of Monolithic).
There's some documentation in the readme of express-session which explains their store a bit but not how to use it. As an example, it states you can get the session like this:
store.get(sid, callback)
However, the only store available is a class called "Store". There's no clear indication in the docs on how to get/use this.
The docs go on to say something about "compatible session stores". Does this mean express session doesn't have it's own store, what are they trying to say in this readme? It's very cryptic and could have been written better...
Here's how I solved it:
In your middle-ware do the following (I'm using Typescript):
export const sessionStore = new session.MemoryStore();
...
UserApp.use(session({
secret: SESSION_SECRET,
resave: false,
saveUninitialized: true,
store: sessionStore, // Session store goes here!
cookie: {
secure: true,
httpOnly: false,
maxAge: ONE_DAY }
}));
We will call this app which contains the middle-ware App A. I have another app, I will call App B. From that app, we will make an http.request to App A. App A will call the following.
sessionStore.get(payload.SID, (_err, session) => {/* callback */})
That will return the session from the session store, provided it still exists. We return that session to App B and we can do whatever we want with it. Hope this helps someone, this was annoying for me.
EDIT: Ah and then I saw this...
Warning: the default server-side session storage, MemoryStore, is
purposely not designed for a production environment. It will leak
memory under most conditions, does not scale past a single process,
and is only meant for debugging and developing.
Great.
EDIT 2:
I'm using this store instead, pretty simple to swap out.
https://www.npmjs.com/package/connect-redis

How to use new enhanced sessions in Parse with users created on cloud code?

I was trying out the new enhanced revocable sessions in Parse on my Android app. It works well when logging in or signing up via email password or facebook but doesn't work well for custom authentication, e.g. google+.
I'm currently logging in the user using the cloud code which also creates the new user when signing up. This does not create a new Session object, that means the new enhanced sessions are not used and it still uses the legacy sessions.
I pass the session token back to client where using the become method the user logs in but it's the legacy sessions.
This feels like the feature is not complete but I would really like to move to the new enhanced sessions with my app. Has anyone worked with them yet? Are there any workarounds using the REST API or by creating the sessions manually and handling them manually? I looked into the JS API but it says it's only read only.
Here's the Blog post on Enhanced Sessions.
Where should I go next?
Yes, I found a solution but it's a workaround, works for my case because I don't support signing up with user/password.
Basically, the solution (cloud code) in semi pseudo-code is:
Fetch the user with master key
Check if user.getSessionToken() has value
if it has, return the session token and do a user.become() in the client as usual
if it's not, here the workaround, do the following:
yourPreviousPromiseInOrderToChainThem.then(function(user)
password = new Buffer(24);
_.times(24, function(i) {
password.set(i, _.random(0, 255));
});
password = password.toString('base64')
user.setPassword(password);
return user.save();
}).then(function(user) {
return Parse.User.logIn(user.get('username'), password)
}).then(function(user) {
var sessionToken = user.getSessionToken();
// Return the session token to the client as you've been doing with legacy sessions
})
That means, I'm changing the user password each time in order to make a remote login and, of course, I know thist can't be applied to all cases, it's enough for app because I don't support login with user/password (only third party logins) but I understand that maybe it's not for all cases.
I got the idea from this official Parse example.
I don't like this solution because I think is not a workaround, it's a mega hack but I think there is no other way to do it currently (either Parse.com or Parse-Server)
If you find other workaround, please, share it :)

How to destroy cookies when idle in Dancer (Perl) using Dancer::Session::Cookie?

Is there a built-in way to destroy a session cookie generated by Dancer::Session::Cookie after a certain amount of minutes of it being idle? I noticed that it doesn't even destroy the session when I restart either the Nginx or Starman server, which is not what I want (for security reasons).
If there is no built in way is there anything inherently wrong with storing the last time the session was active in an SQL database and updating it after every action? Then if more than 15 minutes or so have gone by without that entry being updated the session cookie will be destroyed (with session->destroy). That doesn't seem like the best solution but maybe that's the only way. From my understanding you can also manually set a cookie expiration time in the HTTP header but that would only destroy the cookie on the client-side, correct?
I think you want to do the reverse.
When you generate the cookie, use the expires attribute to set it to, say, "15 minutes":
https://metacpan.org/pod/Dancer::Cookie#expires
Then every time you do something for that session, call the Dancer::Cookie init method:
https://metacpan.org/pod/Dancer::Cookie#init
... to refresh the cookie (if you're not using the default path, pass in the path).
The user's browser should expire the cookie for you after the given time.
(I have not actually tried this, but the code implies it should work - the documentation for the init method could certainly be clearer)

How to have users 'reconnect' with soundcloud on each page reload?

I'm using the Javascript SDK inside a node.js (Express) App.
Connecting Users works fine, but the connection does not persist between page reloads.
Is this the default behaviour, or is the User supposed to stay connected in new requests?
Do I have to use OAuth token authentication and if so, how can this be done with the JS-SDK?
Inside the "Permission"-Popup, Users are already logged in with soundlcoud, though.
(just have to click the "connect" button each time)
Figured I'd share my answer for those who are unsatisfied with the current answers for automated oauth:
Retrieving access_token:
I had to define get and set cookie functions and then I use the functions to set and retrieve a function holding the access token. I'm not going to give these functions for conciseness but you can easily find them with a google search. I then use this line of code to get the SC access token (once the user has authenticated for the first time)
SC.accessToken()
Setting token:
So this is kind of just an elephant in the room in my opinion that for some reason no one has mentioned. How in the **** do you connect w/ SC using the access token? Do you set it as oauth param? On each call pass it? Well, after experimenting with putting the parameter in every single place I could think, I found out you have to do something like this:
SC.initialize({
client_id: '[removed for security reasons]',
client_secret: '[removed for security reasons]',
redirect_uri: '[removed for security reasons]',
access_token: getCookie("sc_lm2"),
scope: 'non-expiring'
});
//Where "sc_lm2" is the name of my cookie
Hope the helps! Took me a while to figure this out for such a simple thing
EDIT
Using PHP and Wordpress:
$json = wp_remote_get("http://api.soundcloud.com/users/[user_id]/tracks.json?client_id=[client_id]");
$soundcloudData = json_decode($json['body'],true);
(substitue cURL functionality if you're not using Wordpress). #krafty I assume you would just change the endpoint from "/tracks" to "/users" but I can't say I have ever really needed to grab anything but tracks using the Soundcloud API. Hope this helps, though I'm not sure I fully understand what it is that you are trying to accomplish (or rather, how exactly you're going about it) - are you trying to allow user logins? If you want to explain fully what you're trying to accomplish and the steps you're taking I'd be happy to take a crack at it.
Yep, this is the way to do it, officially. :)
For the Next SoundCloud site, we store the token in localStorage (until the user logs out, of course). In each AJAX request to the API from the front end, we put the oauth token in a request header:
jqXHR.setRequestHeader('Authorization', 'OAuth ' + the_oauth_token);

Perl Catalyst; configuring session expire time and flash behaviour

I just discovered that when I configure the session plugin of a Catalyst app (Catalyst::Plugin::Session) to expire, it screws with the flash data. More specifically, I'm finding that flash data no longer carries over with a new request.
Does this sound normal? How might I cope with this?
Perfectly normal. The whole point of sessions is to be able to associated data from one request with data in another request. When you let the session for some request expire, you are saying that that request's data shouldn't have anything to do with any future request.
More specifically, the flash data is a part of the session data -- see the _save_flash method in the Catalyst/Plugin/Session.pm file, for instance. Also see the big warning for the delete_session method:
NOTE: This method will also delete your flash data.
How to cope with it? You need to persist data from a request using any scheme other than the Session plugin. Without knowing more about your app, what data you are trying to persist, and how you will associate data from an old session with a new request, I couldn't begin to make a more specific recommendation than that.
When configuring the session for example with a database backend you'll have to add flash_to_stash as an option:
<session>
dbi_dbh DB
dbi_table sessions
dbi_id_field id
dbi_data_field session_data
dbi_expires_field expires
flash_to_stash 1
expires 3600
</session>