I am using a computer in the place as work as a web dedicate server for the application. (so sessions won't be shared)
I want to develop a secure remember me functionality and i was wondering which is the best way to do it:
Sessions
Cookies
With cookies I would have to encrypt the user password, create some salts and add some fields in the database. (as detailed here or here)
Wouldn't it be more simple using sessions in this case configuring them to last longer?
Thanks.
Cookies.
You need to store some state on the client. The idea of "remember me" is that coming back to the same site without a session will still get you logged back in, without having a valid session established.
Cookies allow you to store state. There can be other ways to do it, but definitely not sessions.
Cookies vs. Sessions
PROS for Sessions:
Sessions might be easier to configure.
Sessions would work well for a limited number of extremely TRUSTED users
Cookies and Sessions have same threat model. If a hacker can decrypt a cookie he can decrypt a session
CONS
If your server is attacked, the attacker gains a context. i.e. a whole bunch of tokens via which he can decrypt the data
Sessions hold memory on the server side. Also session cookies expire when the browser closes. Though this could be re-configured (if you try really hard). You basically end up re-creating the cookie in a slightly new avatar.
All in all Cookies VS Sessions for "remember me" its cookies without a doubt.
Related
Steps to re-create the issue:
Login with Admin Credentials and copy the session cookie.
Open another browser, Login as another user, paste the session cookie of the admin. Refresh the page. Now, you'll be
logged in as Admin.
How to solve this issue? Any suggestions would be of great help.
Tried using the event subscriber to get the previous session before drupal loads the cookie session, but no luck with it.
This is not a problem, I mean, of course, Session Hijacking is a really big concern - but standard defences are fine.
These are the controls that I know are widely known/used:
Ensure HTTPS is used everywhere,
Only use a securely created random string for the cookie value,
Set the secure flag on all cookies. This will ensure that they are only sent over an SSL connection,
Change the session cookie on each new login attempt.
All of Drupal 8's cookies are secure by default.
The exception is BigPipe's no-JS cookie, see https://www.drupal.org/node/2678628 — but there are no security consequences there.
I know some very sensitive applications may also store - for each session - the following additional information:
SSL Session ID
HTTP User Agent
Remote IP Address
In my point of view, I wouldn't bother with checking the HTTP User Agent or the remote IP address. They don't add that much security and they will break legitimate use in certain scenarios. Checking the SSL session ID (SSL session binding) would be OK from a security perspective, but could be painful to implement, the other defences are fine.
If your concern is Cookie Theft via XSS, the best defence is to use standard methods to avoid XSS bugs in your web application. See OWASP for plenty excellent resources.
You may find a lot of best practices to write secure code for Drupal 8 here: https://www.drupal.org/docs/8/security/writing-secure-code-for-drupal-8
You may also find a pretty old discussion about this on Drupal here: https://www.drupal.org/project/drupal/issues/19845
I'm trying to switch a web app from the "traditional" cookie-based authentication mechanism to a purely token-based one. The token should be cached once received by the client to reduce overhead. What is the best way to store the token?
This is what I already learned from googling:
The first promising avenue I looked into was browser session storage, however, as far as I can tell, this isn't shared even across tabs, which means if users follow a link from the site using a new tab, they will have to log in again.
There's also local storage, but I want users to automatically be logged out when they close their browser, and I'm also a little uneasy about tokens sitting around in the storage, even though I expire them server-side. It just seems unclean.
Another way is to store the token in a session cookie, which would mean it both gets killed on browser close and can be shared across tabs. It's almost ideal, except the cookie will of course get sent over the wire with every trip to the server, which I would like to avoid if possible. Even though it's not a security issue, it seems redundant to be sending it via the cookie as well as in the HTTP Authorization header. I've thought about setting the cookie path to a non-existent path on my domain, but that's not exactly an epitome of beauty either...
So, being faced with three non-optimal solutions, I once again turn to SO for help. How do you guys do it? What's the best way?
tl;dr What is the canonical way of persisting authentication tokens in single-page web applications?
t;dr I'm using localStorage to store token.
I'm using localStorage for storing token on client side. You can see details of my implementation in my article: React Token Based Authentication to Django REST API Backend.
The localStorage shares the token across tabs and doesn't disappear when you close the tab. The data in localStorage persist until explicitly deleted. The data in sessionStorage is deleted when the session ends.
There is some discussion on the internet that localStorage is insecure because, in the case of the XSS attack, a hacker can read all data from it. Which is true. There is some discussion that httpOnly cookies are better to store the token because hackers cant access and read the token from the httpOnly cookie. It is true, but the misunderstanding is that cookies don't prevent XSS (the XSS can occur even if you use httpOnly cookies). What is more, cookies enable CSRF attack. And, in the case of XSS, a hacker can still use set httpOnly cookies for malicious requests (similar to CSRF). So there is no clear winner here. The most secure way is to not store tokens on the client side.
I have a standard HTML login page, which I would much rather use than the standard HTTP authentication pop-up provided by browsers. Today, I am using session cookies to keep track of the session after logging in, but I'd like to be stateless and pass the HTTP authentication every time. The web services I am hitting already support this, so this is a browser-only issue.
Adding authentication credentials is trivial in jQuery, but I don't know how to keep them around. If you go from the login page (a jsp) to the Home page (another jsp) you clearly don't keep the username and password fields from the login page. I know some browsers will store your HTTP authentication credentials if you enter them from the pop-up, but I don't know if they get stored when using an XHRRequest. If they do, is there much consistency among browsers?
Also, the user needs to be able to "sign out" of the application, too. If the browser stores the authentication credentials, is there a way to clear them using JavaScript.
I feel like I can't be the first person to try to solve this. Is there some jQuery plugin or something that already handles this? Or is it simply not possible to do what I'm trying to do?
You have 2 options:
1) Client-side storage of credentials -- not a good idea. For obvious reasons you don't want to store the username/password on the client. If you had a hashed version of the password, it might not be so bad, but still not recommended. In any case, if you're going to store on the client side, you either have to use a cookie, or HTML5 local storage (which is not widely supported, yet)
2) Server-side storage of credentials -- typically done with sessions. Then the resultant Session ID can be passed back to the client and persisted in either a cookie or in the URL of each subsequent AJAX call (?SESSID=xyz for example)
The server-side approach would be the most secure, reliable, and easiest to implement
Okay, I'll take a stab at helping ...
Firstly, understand how HTTP authentication works. There are two versions - Basic and Digest. Basic transmits in plaintext, digest is encrypted. With these types of authentication, the username/password are passed in the HTTP header with every single request. The browser captures these at login and they are stored in an inaccessible browser session cookie which is deleted when the browser session is closed. So, in answer to one of your questions, you can't access these from javascript.
You could create your own session cookie variables for username and password. The jQuery functions for this are really simple. See jquery-cookie module as one example of how to set session cookies. These could be retrieved from the session cookie and sent with each ajax request and validated in the server. However, this is not a particulary good way to do authentication since sniffing the network will allow anybody to easily grab your auth details. But, it would work.
Using session cookie based authentication where the session ID is sent sent with each request is the best way to do this. At the server side, you need to have a function called for every HTTP request. This function should do the following:
check to see if the session has been authenticated
if no:
redirect to login screen
if yes:
do authorization and allow the user access to the page
Most web frameworks support session cookie authentication and the management of session ids at the server. This is definately the way to go.
This is interesting one.
Manage user sessions on server by use of cookies. Create a session when user first accesses the login page and pass the session id/key as value to one of the cookie via response. When the user is authenticated put user "key" info in cookie and "values" in application context at server. Once user is logged, any subsequent request will be authenticated based on session cookie value at server. Authorization will be done based on user "key" passed as cookie value.
On logout clear the session based cookies from server and refresh the site to default page.
Cookies are bizarre with different browsers - just a note ;)
Hope this helps.
Update
The answer below was posted in 2012 and the links are mostly dead. However, since then, a more elegant standards-based approach to the same solution appeared using JSON Web Tokens. Here is a good blog post explaining how to use them.
Most answers miss the point, which is to avoid having any server-side session. I don't want any application state in the server. I'll award the bounty to answer that came closest, but the real credit goes to the rest-discuss group and Jon Moore for the correct answer and to Mike Amundsen for helping me to actually understand it.
The best answer I've gotten is to use a cookie, but not the typical automatic session id cookie given to you by most application servers. The cookie (which will automatically be sent with each subsequent request) is a user identifier and time signed by the server. You can include an expiration time with the cookie so it simulates the typical 30 minute session on a server (which means you have to push it forward with subsequent requests) as well as keeps the same cookie from being valid forever.
The XHR/AJAX part is a red herring. This will work whether you are doing XHR requests or an old-fashioned page-by-page web application. The main points are:
The cookie is automatically sent on subsequent requests so there's no
special scripting required - it's just how browsers work already.
The server does not need to store any session for the user, so the user
can hit any server in a cluster and not have to re-authenticate.
Slightly interesting in that you consider pushing some of the authent to the client. If you want a conventional solution, KOGI's server-side suggestion is the way to go.
But you also seem to be asking questions about memory leaks involving your user supplied secrets. Good questions. But to take a general stab at answering that I'd say it would have to be browser specific. It's browser internals, javascript engine internals -dependent where a client side application (i.e., the browser, or js in the browser) is storing the values the user inputs.
Most likely those values are not replicated needlessly throughout memory, but there's no way to guarantee that. Apart from responsible javascript coding practices, there's nothing you can do to guarantee the limit of locations of user inputs.
Slight digression
The basic point is if you store it on the client it is not really secure -- unless, the serve stores encrypted information on the client with a key that only the server (or the user via their correct credentials), has. So you could conceivably code a JS application to do some authent on the client -- much the same as how bank card (used to?) do POS authent by checking the PIN to the PIN on the card, and not back at the DB. It's based on the (somewhat flimsy) assumption the user has no direct read/write access of the "dark area" cookie/local storage on client / mag strip on bank card. So I would only advise this as disqualifier for false authents and not as a sole qualifier for the credentials.
Main point
If you do want to be stateless, just store user credentials in localstorage, or as a cookie but encrypt them with a server key. When you need them send an XHR with the encrypted / use stored credentials to the server over HTTPS, let your server decrypt them and send them to the callback. Then pass those cleartext of HTTPS to do your authent.
Which is the difference between sessions and cookies. I know that sessions are server side, and managed by the server, and the cookies are client side and managed by the browser.
I don't know why, but I see those things as rendundant. Which data have to be keept in a session variable and which on cookies?
Session is implemented with cookies. You would normally save in a cookie things like the user id, or some identifier that will allow you to know who the user is, and use that information as a key for your session variable on the server side.
Most importantly, you wouldn't want any secret information being stored on the client side, since cookies can easily be stolen (from a security point of view).
Don't forget that HTTP is stateless, so cookies are just a way to bypass this.
In short, cookies are more persistent than sessions. As soon as you close your browser, the session information is gone. Therefore a session has no way to store information about a website/user pair. Cookies do, and are used for things like allowing you to stay logged in to a website, or storing preferences for that website (e.g. language).
The main difference between cookies and sessions is that cookies are stored in the user's browser, and sessions are not. This difference determines what each is best used for.
see http://php.about.com/od/learnphp/qt/session_cookie.htm
Cookies are for small data. They can only hold strings.
In session variables you're able to store objects in the server memory.
How does one implement maintaining sessions securely. Suppose just the login page uses SSL. So the user enters his usernamepassword and the http server verifies it is in the database and now what?
Does it set some cookie? If so then what should the cookie be set to so that security is maintained (encrypted, what kind of encryption)? Looking for a low level detailed answer. I hear there are various cookie hijacking concerns. If I only use SSL for the login but thereafter don't use SSL will the cookie be vulnerable?
Then after the browser is closed and the user comes back how does the cookie identify the username. How is this done securely without the cookie being stolen?
You definitely expose your clients to session theft if your connection is not encrypted at all times.
HTTP is a stateless protocol, so the only way to fake a stateful interaction is for client and server to send a session identifier with every transaction. If this isn't protected, it can trivially be stolen. Since the session identifier is the only authentication token during the open session, this is catastrophic.
The usual way to make a "remember me" feature would be to set a cookie whose lifetime is not limited to the browser's program lifetime (i.e. by setting an explicit expiration date), and storing some unique data in the cookie which you match against some remembering data (including the IP perhaps) in your database. But that does not absolve you from the need to encrypt all communication!