I'm saving the user language choice into the sessions like this:
$this->session->set_userdata('language', $language);
And then I'm setting the language depending on the session data (and making a English , as a default language).
if ( !$language = $CI->session->userdata('language') )
{
$language = "english";
}
$CI->config->set_item('language', $language);
It works good, but the language that user has chosed lasts only for approx. 2 hours - then user have to pick the language again. So the question is, how can I extend the session time to expire (or make it expire only in case if user cleans up the browser data). I can not save the user choice in the database, because I need to also handle guests on my website.
I know I can extend the session time in the CI's config, but I just want it to happend only in case of the language selection, and not for example for accounts sessions.
It is the same session, and it either expires or doesn't. You can't have the authentication part expire, but not the language selection. CI doesn't make it easy to manage multiple sessions, which would have made it possible to store authentication in one short-lived session and language preference in a longer-lived one. As it is, it might be easier to just store language preference directly in a cookie; just keep in mind that you will have to set the cookie again on each request, otherwise it will not get refreshed automatically upon user activity and will expire even if the user is actively using the site.
Related
I find that some websites have sort of authentication even though no user is logged in. Taking plunker for example, even a non-logged in user can freeze a snippet such that other users cannot modify; whereas the user himself could always modify the snippet even though he opens the link in another browser tab.
My current solution is adding a type field (ie, anonym and normal) in the user model. Then, each time there is no normal user logged in, I systematically generate a unique random ID, register and login as an anonym user. It works, but the shortcoming is there are lots of anonym users in my database.
Does anyone have a better solution? Is there any "standard" way to realize this kind of hidden authentication?
I think method you are looking for is called session id. When you save as anonymous user web app creates a session with a session id which is used to identify the user by link. For example on plnkr it'll be something like https://plnkr.co/edit/session_id?p=catalogue where session_id is some sort of hash.
To freeze the snippet the session id is written into cookies with the flag, saying, for example, that the state is frozen. If you freeze it in Chrome and open in a Chrome's private window or in Firefox on the same computer, you wouldn't be able to unfreeze it. It'll behave the same way as for other users which have no cookies. In fact using session hash for cookies, rather than any user identification is better for security reasons.
Now this approach in a sense isn't any better, than creating anonymous users - you still have to save session records into the database to be able to open session context by link. In fact, it might happen to be simpler in your case to do exactly what you did if user is assumed to be present in lots of use cases and places in the code.
In many cases, however, separation of session from user makes lots of sense as it simplifies keeping session state after login or registration. Say some web stores would empty your basket after you register, causing quite a bit of frustration, especially if you put several small items into it which you now have to find again and put back. Those don't have sessions or don't use them correctly on registration or login.
Otherwise, as I wrote it's pretty much the same and you have to deal with many anonymous sessions which pollute the database unless you have some sort of wise retention policy, depending on you use case. Say, for example, a web site similar to plnkr.co which is used to share code snippets, and post them on sites such as stackoverflow should better keep those sessions while there are users accessing those say at least once a year. So sessions should have access date and policy would be that it's older than 1 year.
Hope it helps.
I have done similar using Local Storage. It allows you to store data on the browser. A user can then open tabs, close browser completely and reopen etc and the data is still there. It would then appear to be saved for them but actually it's just stored on their browser.
This wouldn't allow others to see what they have done though, so not sure if this is quite what you're after.
I wrapped them in functions in case I chose to change them out later, something like this
StoreLocalVariable: function (key, value) {
localStorage.setItem(key, value);
},
GetLocalVariable: function (key) {
return localStorage.getItem(key);
},
Some info including compatibility
https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
Our API is built on parse (parseplatform.org).
I have a background job which needs to run queries on behalf of users; it needs to ensure that the queries only find/update objects that the user's ACL allows.
For most users, I can query the Parse.Session class to get the sessionToken for the given user, and then use that on all requests, e.g. query.find({sessionToken: "r:xxx"}).
But for some users, the only session object available have expired, and for many, there are no session objects at all.
As far as I'm aware, creating Parse.Session instances is not possible; the only way to generate a session is by calling Parse.User.logIn; but this is not an option for us, mainly because we would need the user's password (which we do not have), but also because it results in memory leaks on parse-server environments.
Has anyone come across a solution for this?
For background jobs where there is no user you should use the following
query.find({useMasterKey: true});
useMasterKey will bypass any ACL security restrictions. Perfect for Batch jobs.
Just be careful that anything else that calls this code will also use the masterKey. Sometimes I will add the following code before to ensure that the correct access is used
var findOptions={};
if (request.user){
findOptions = {sessionToken:request.user.getSessionToken()};
} else {
findOptions = {useMasterKey:true};
}
query.find(findOptions);
Depending on what you're trying to do, you might just need to run the code when they log in (and therefore you have a session token).
You could also try running the code with the master keys but that comes with its own problems.
I have a general question about sessions. I am not very seasoned when it comes to this subject. I've tried with:
NewRediStore (gopkg.in/boj/redistore.v1)
NewCookieStore
NewFileSystemStore
I was under the impression that sessions could last between server restarts, hence the need for a 'store'. While my golang backend is running, I am able to set new sessions and retrieve them for multiple users/browsers. No problems there.
When I restart my server, I notice that all session access results in session.IsNew == true.
In Redis, I can see all the session keys after the restart, and even verified that .Getting the session results in the right ID retrieved, but IsNew is still set.
I guess intuitively, this makes sense because there must be some map in memory that leads to the setting of IsNew but I would think that if there was any hit for the cookie key in the store, IsNew should not be set. Am I going crazy? Is there something easy that I am doing wrong? Is this a fundamental misunderstanding of how to use sessions?
Please let me know if I need to include code or additional details.
I would have had the same assumptions you did, and browsing the source, it looks like it should work as you described. You might try debugging and stepping through it, particularly the New method for the store you're using (e.g. FilesystemStore.New or RediStore.New). If that method successfully reads the cookie and finds the session in the store, it should set IsNew = false, according to the source.
Also note that just checking the session ID is not a good way of validating this behavior. If you look at the source, it decodes the session ID from the cookie, then tries to look that up in the backing store. If the lookup fails, then the session ID will match, but IsNew will be true and there won't be any values in the session. Make sure you're setting some value in the session and check for that instead of the session ID. The behavior is different for the CookieStore since it stores the session data in the cookie itself.
I'm building a Sails.js app that includes a user login. As the documentation instructs, when a user signs in, the session records her id in the session accordingly:
req.session.userId = createdUser.id;
In most of the examples, each route performs a lookup on this ID, if it's present, and sends the authenticated user to the view if found. This strikes me as very inefficient. EVERY view needs to know if there's a signed-in user in order to display her name in the upper left corner. So, if I understand right, every view includes a trip to the database to look up the user, even if I reduce the amount of code by creating a policy that performs this lookup for every route.
What I would rather do is record the user's information in the session so that, once she is authenticated, that information is automatically present to every view:
req.session.userId = createdUser.id;
createdUser.loggedIn = true;
req.session.user = createdUser;
// the createdUser object does NOT contain the encrypted password or other sensitive info
This then allows me to just check in the template for a signed-in user like so from the layout parent template (and any child template). (I'm using server-side views.)
{% if (session.user && session.user.loggedIn) %}
<li>Hi there, {{ session.user.username }}</li>
{% else %}
<li>Sign In (if you want)</li>
{% endif %}
My question is whether this poses a security risk of any kind. It seems MUCH more efficient than looking up the User in every view, but perhaps there's a reason that documentation seems to advise this?
In most of the examples, each route performs a lookup on this ID, if
it's present, and sends the authenticated user to the view if found
FYI, ideally this should be handled by a policy.
This strikes me as very inefficient. EVERY view needs to know if
there's a signed-in user in order to display her name in the upper
left corner. So, if I understand right, every view includes a trip to
the database to look up the user, even if I reduce the amount of code
by creating a policy that performs this lookup for every route.
Either you make extra roundtrips to the database or you bloat your sessions. Both have their pros and cons. E.g. when creating a backend application that does not have to scale, I do not care about this extra database lookups. However when I have hundred thousands of users I should care. You have to consider this when you architect your application. Applications that need to scale like to use e.g. redis as a session store for optimization.
So to answer your question, yes it is okay to store username etc. in the session object to avoid extra database lookups. I am not a security expert, but I would not suggest to store any sensitive user information in the session like passwords.
BTW I highly recommend using http://passportjs.org/. It integrates with sails very well.
To get you started:
http://iliketomatoes.com/implement-passport-js-authentication-with-sails-js-0-10-2/
https://www.airpair.com/express/posts/expressjs-and-passportjs-sessions-deep-dive
In this example you can see how username, email and the roles of the user are stored in the session object:
passport.serializeUser(function(user, done) {
var sessionUser = { _id: user._id, name: user.name, email: user.email, roles: user.roles }
done(null, sessionUser);
});
I am curious about the value of PHPSESSID because, I created a simple login-type web app. When I try to login with different accounts, the value of the PHPSESSID is not changing. I got curious if it does okay or not. Because I tried to login in youtube with different account too. But their SID's differ on each user.
My question is:
1) Is what happening on my web app okay ?
2) Is yes, how can I make a session ids per account/user ?
3) If no, how can I fix it ?
I would really appreciate your suggestions.
It partly depends on exactly how you implemented "login." One way to do it is simply to change the user-identity (which, by definition, is part of the data that is stored in the session), while keeping the same session.
Another equally-valid way to do it is to first update the existing session (to show that the user, in that session, is now "logged off") (maybe...), and then to coin a completely new session-id, thus starting an entirely new session, in which you now "log on."
One advantage of the second approach ... and probably the reason why so many sites do it this way ... has to do with the possibility that the user might wish to open a new browser-window, and to log-in to the application a second time, intending to keep both logins alive at the same time. If the session-id token is part of the URL, or maybe is part of a hidden form or what-have-you, such that both session-id's can be retained independently, it becomes possible for the user to do what he has done without conflict. Two parallel sessions exist. In one, he is logged on as "joe," and in the second, he is logged on as "jeff." And so on. One set of browser-windows (somehow ...) carries the "jeff session" token; others carry the "joe session" token.
Fundamentally, a "session" is just a pool of server-side values, identified by the (PHPSESSID ...) token furnished each time by the client. Exactly how you choose to manage it, is at your discretion. It's a design-decision with no "correct" approach.