I'm currently trying to set up a session management interface for users to essentially log out their sessions that may be active on other devices. However, I'm still somewhat new to Asp.Net Core 2.1 and am having trouble finding good documentation on the subject.
I thought about using the distributed SQL server cache system. However, after further inspection, I found that the keys for the distributed cache are not equal, as they shouldn't be, with the session id.
I also tried writing some middleware that stores the session id in a separate table with a many-to-one relationship with the user table. This table would have a sliding expiration dates and a tokens. If the session had a token, the session would be persisted.. My thought was to assign a token to the client using a cookie. That way if their session expired, it would lookup the session with the cookie token and, if one existed, log the corresponding user in. Then it would copy over the token and delete the old session. Kind of like a 'remember me' system. If the token is null and the session time was expired, it would be disposed of. If no session was found, or the user field is null, it would log the user out. If duplicate tokens were found, it would log all of the sessions with the corresponding token out. However, I'd rather use some kind of built in feature, if it exists, to minimize the risk in opening up unwanted security vulnerabilities.
I've also found examples where you can log another user out... But, because Asp.Net Identity is cookie-based, it allows the user to continue to use the site until their cookie expires... This would be undesirable in this scenario.
I know that Asp.Net had the IHttpSessionState, but I've been unable to find a similar interface in Core. Unfortunately, most solutions I've found either point to implementing a custom-made system, or they just show how to log the current session out.
Basically, is there already some kind of mechanism in Asp.Net Core that already implements something like this? If not, is there any specific interfaces that I should be researching and trying to implement? If not, should I resort to writing my own system? If so, are there any holes in my logic above?
Here's an example of what I'm talking about, pulled from Facebook's account management. I know that it's a much larger scope website, but I wouldn't think that such a feature would be extremely hard to integrate? Might be wrong though...
(Redacted some personal info)
I'm re-writing a website from the ground up for azure. Each user has ownership of a number of objects, and has a number of permissions. Together, these determine what they are authorized to do. The question is, how should this information be stored. I want to do the authentication myself, using custom logic.
For performance reasons, I'd like to cache these authorization lists for each user once they're logged in. Can someone give me a sample for how to store & access this session information securely and efficiently.
Edit
I looked into the App Fabric Access Control, but that seemed overkill as I was going to have to create a separate site for authentication, which doesn't seem to make sense. Would the claims based authentication make sense separately though? How would you do that if it does?
Would it make more sense to just keep the username in a cookie in the traditional way and then re-query table storage with each request to get the permissions etc.? How would storing the username work in Azure?
Cost is a big factor here as it's a very small site (by azure standards) but I want high performance for a small number of users.
If you want to run with a reasonable amount of availability you need to run your site with two instances. If you're running with two instances you need to use a session provider that's no the default InProc one. Your choices are:
AppFabric Caching (which you don't want to use because it's too expensive, fair enough)
Azure Storage Session Provider. Don't use this. It's an interesting experiment, but it's only sample code, it's slow and doesn't cope well in production.
SQL Server session provider.
If the permissions for a user weren't going to change while they were logged in, you could just store their permissions in session. This will probably be fast enough. However this information will need to be read from SQL for each request that uses session and it is overhead.
If you wanted to make things faster you could just store the user ID in session and load the permissions into a static dictionary (keyed on user ID) when needed. These items will need to be expired after a certain amount of time or lack of use.
Well, you could use the Azure App Fabric cache to store the session info. ASP.Net can be configured to use it as the backing store for its session state as like a normal custom session state provider.
This article from MSDN shows you how to configure it:
http://msdn.microsoft.com/en-us/library/windowsazure/gg278339.aspx
From your code you just use the normal ASP.Net way to get/set the state.
Be aware though - it could be expensive ($45/month for 128MB of cache).
I am creating a website on ASP.Net in which a user logs on and I need to store the user specific data (plus some extra data) somewhere so that all the pages in my website can readily access the data.
At one time many users could be accessing the website and every user will have his own specific data.
Currently I am using sessions to store the data after login and accessing the data on different pages as and when needed. I am also using session to pass data from one page to another. I also don't want to use cookies as many companies don't allow cookies to be created.
I understand that this is not the best practice. Can you guys suggest what would be the best way to manage the data?
Thanks,
Abhi.
Sessions are not necessarily a bad way to go. Ensure that data kept in the session is as concise as possible, and that your application will support all environments that it may be deployed into.
Also remember that Sessions do not provide data persistance once the session has been expired, so if you require data persistence, then a database would be more suitable.
This is what MS says about it, http://msdn.microsoft.com/en-us/library/ms178581.aspx:
"SessionID values are sent in clear text, whether as a cookie or as part of the URL. A malicious user could get access to the session of another user by obtaining the SessionID value and including it in requests to the server. If you are storing sensitive information in session state, it is recommended that you use SSL to encrypt any communication between the browser and server that includes the SessionID value."
As long as you use a save connection you should be fine
ASP.NET already provides you with information about the user through the IPrincipal interface and the User property.
If you need extra information about each user, you can use these to implement a User Context.
I am using asp.net mvc 2.0 and I am wondering how secure is it to put information in a cookie?
Like I put in my cookie a forms authentication ticket that is encrypted so can I put information that could be sensitive in there?
string encryptedTicket = FormsAuthentication.Encrypt(authTicket)
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Like I am not storing the password or anything like that but I want to store the UserId because currently every time the user makes a request to my site I have to do a query and get that users Userid, since every table in my db requires you to use the userId to get the right row back.
So these start to add up fast so I rather have it that if a user is authenticated once then that's it till they need to be re-authenticated again. If I would store this userId I could save so many requests to the database.
Yet I don't want it floating around in clear text as potential someone could use it to try to get a row out of a database when they really should not be.
Show how good is this encryption that Authentication uses?
The encryption is good enough, that's not the weak link.
The weak link is that the cookie value could be intercepted, and someone else could impersonate the user.
So, the information in the cookie is safe enough, but you can't protect the cookie itself.
The title of your question doesn't really match what you are asking. There are two different things you are asking here.
1. Is there a secure way to store data in a cookie?
The answer is yes. To safely store data in a cookie you have to encrypt the data you want to store then sign the encrypted data. Encrypting it prevents attackers from being able to read the data, signing it prevents attackers from modifying the data. This will ensure the integrity of the data. You could use this method to store data about the user you want to keep private (their email address, date of birth, etc). Note: Securely storing data in a cookie is not a safe way to authenticate a user! If you stored the user id of the user in the signed and encrypted cookie, nothing prevents an attacker from stealing the entire cookie and sending it back to the server. There's no way of knowing if the authentication cookie came from the same browser where the user entered their user name and password. Which leads us to the second question (the one you were actually asking)...
2. Is there a secure way to authenticate a user with a cookie?
Yes. To securely authenticate a user you must combine the techniques from question 1 with SSL (https). SSL ensures that only the browser will be able to access the authentication cookie (the signed encrypted cookie with the user id in it). This means that your login process (accepting the users name and password, as well as setting the authentication cookie) must happen over SSL. You must also set the HttpCookie.Secure property to true when you set the authentication cookie on the server. This tells the browser to only include this cookie when making requests to your website over SSL. You should also include an expiration time in the encrypted auth cookie to protect against someone forgetting to log out of your site while they are at the library. A side affect of this approach is that only pages on your site that are SSL will be able to authenticate the user. Which brings up a third question...
3. How do you securely authenticate a user without using SSL?
You don't. But you do have options. One strategy is to create two auth cookies at login, one regular cookie and one that is ssl-only (both encrypted and signed though). When performing sensitive operations on the users behalf, require the page be in SSL and use the SSL-only cookie. When doing non-sensitive operations (like browsing a store that is customized based on the country their account is in) you can use the regular auth cookie. Another option is to split the page so that information that requires knowing who the user is is retrieved async via AJAX or json. For example: You return the entire page of the blog over http and then you make an SSL AJAX request to get the current users name, email, profile pic, etc. We use both of these techniques on the website I work on.
I know this question was asked almost a year ago. I'm writing this for posterities sake. :-)
Along with cookie encryption, you should also implement a rotating token to prevent replay attacks.
The idea being that the encrypted cookie contains some value which can be compared to a known value on the server. If the data matches, then the request succeeds. If the data doesn't match then you are experiencing a replay attack and need to kill the session.
UPDATE
One of the comments asked if I meant to store the value in the cookie. The answer is yes. The ENTIRE cookie should be encrypted, which can be automatically done through the use of an HttpModule. Inside the encrypted cookie is any of your normal information + the changing token.
On each post back, check the token. If it's valid, allow the transaction, create a new random token, store in the cookie, and send that back to the browser. Again, in an encrypted form.
The result is that your cookie is secure (you are using 3DES?) and any attacker would have an extremely limited window of opportunity to even attempt a replay attack. If a token didn't pass muster, you could simply sound the alarm and take appropriate measures.
All that's needed server side is to keep track of the user and their current token. Which is usually a much smaller db hit than having to look up little things like the users name on each page load.
UPDATE 2
I've been trying to figure out whether this is better or worse than keeping the changing value stored in session. The conclusion I've come to is that storing a rotating value in session on the web server does absolutely nothing to prevent replay attacks and is therefore less secure than putting that value in a cookie.
Consider this scenario. Browser makes request. Server looks at the session id and pulls up the session objects, work is then performed, and the response is sent back to the browser. In the meantime, BlackHat Bob recorded the transaction.
Bob then sends the exact same request (including session id) to the server. At this point there is absolutely no way for the server to know that this is a request from an attacker. You can't use IP as those might change due to proxy use, you can't use browser fingerprinting as all of that information would have been recorded in the initial exchange. Also, given that sessions are usually good for at least 30 minutes and sometimes much longer, the attacker has a pretty good sized window to work in.
So, no matter what, to prevent replay you have to send a changing token to the browser after each request.
Now this leaves us with the question about whether to also store values such as the user id in an encrypted cookie or store it server side in a session variable. With session you have concerns such as higher memory and cpu utilization as well as potential issues with load balancing etc. With cookies you have some amount of data that is less than 4kb, and, properly done, in the 1kb or less range that gets added to each request. I guess it will boil down to whether you would rather add more / larger servers and internal networking equipment to handle the requests (session) or pay for a slightly larger internet pipe (cookie).
As you've stated, a good practice for storing any data in cookies is to encrypt the data. Encrypt before putting into the cookie, and decrypt after reading it.
In the example of storing a user identifier, choose something that's not likely to be used against your system. For the user id, use a guid rather than the likely incrementing integer that's the PK on the database table. The guid won't be easily changed to successfully guess another user during an attack on your system.
Once the user has been identified or authenticated, go ahead and store the user object, or key properties in Session.
In an ideal world with an ideal cipher this wouldn't be a problem. Unfortunately in the real world nothing is ideal, and there never will be an ideal cipher. Security is about solving these real world threats. Cryptographic systems are always vulnerable to attack, weather it be a trivial(brute force) attack or by a flaw in the primitive its self. Further more it is most likely that you will botch the implementation of the primitive, common mistakes include non-random or null IV, Key management, and incorrect block Cipher mode.
In short this is a gross misuse of cryptography. This problem is best sovled by avoiding it all together by using a session variable. This is why sessions exist, The whole point is to link a browser to state data stored on the server.
edit: Encrypting cookies has led to the ASP.NET oracle padding attack. This should have been avoided all together by using a Cryptographic Nonce. Like i said, this is a gross misuse of cryptography.
For your very specific scenario (user id), the short answer is NO!
For the long answer, imagine this hypothetical scenario:
You navigate to stackoverflow.com;
Fill your username/password and submit the form;
The server sends you a cookie containing your user ID, which is going to be used to identify you on the next requests;
Since your connection was NOT secure (HTTPS), a bad guy sniffed it, and captured the cookie.
The bad guy gains access to your account because the server didn't store, let's say, your IP address, and thus, can't distinguish between your machine and the bad guy's.
Still in this scenario, imagine the server stored your IP address, but you're on a corporate LAN, and your external IP is the same of another 100 machines. Imagine that someone that has access to one of these machines copied your cookie. You already got it, right? :-)
My advice is: put sensitive information on a HTTP session.
UPDATE: having a session implies a cookie (or at least an ugly URL), thus leading us back to the very same problem: it can be captured. The only way to avoid that is adding end-to-end encryption: HTTP+SSL = HTTPS.
And if someone says "oh, but cookies/sessions should be enough to discourage most people", check out Firesheep.
It's okay (not great, but not wrong) from a security standpoint. From a performance standpoint, however, it's something you want to avoid.
All cookies are transmitted from client to server on every request. Most users may have fast broadband connections these days, but those connections are asymetric — the upstream bandwidth used for transmitting cookie data is often still very limited. If you put too much information in your cookies, it can make your site appear sluggish, even if your web server is performing with capacity to spare. It can also push your bandwidth bill up. These are points that won't show up in your testing, which most likely happens all on your corporate network where upstream bandwidth from client to server is plentiful.
A better (general) approach is to just keep a separate token in the cookie that you use as a key to a database lookup for the information. Database calls are also relatively slow (compared to having the information already in memory or in the request), but primary key lookups like this aren't bad and it's still better then sending the data potentially a quarter of the way around the world on every request. This is better for security as well, because it keeps the data off the user's machine and off the wire as much as possible. This token should not be something like the userid from your question, but rather something more short-lived — a key used to index and hide away larger blocks of data, of which your userid is perhaps one part.
For your userID, which is likely only a single integer, as well as other small and important data, keep it in memory on the web server. Put it in the session.
The use you are looking at is the exact intended purpose of being able to store information in the Forms Auth Ticket.
No. It have been shown with Padding oracle attack that receiving encrypt data (CBC) can be dangerous because of the errors leakage.
I'm definitely not a crypto expert but I recently saw a demo where encrypted view-state was decrypt using this attack.
Encrypting the userid value in the cookie only prevents the user from knowing what the value is. It does not
prevent cookie replay (use SSL to
prevent an attacker from intercepting
a victim's cookie)
prevent tampering
(an attacker can still blindly flip
bits in the encoded cookie with a
chance that it will decode to a valid
userid, use an HMAC to prevent this)
completely prevent a user from getting the decrypted value (the user can brute force the value off line, use a strong encryption key to make success less probable)
Encrypting the cookie also introduces a key management problem. For example, when you rotate the encryption key you have to make sure "live" sessions with the old key won't immediately fail. You thought about managing the encryption key, right? What happens when admins leave? It's compromised? etc.
Does your architecture (load balancers, server distribution, ...) preclude using server-side session objects to track this information? If not, tie the userid to the session object and leave the "sensitive" data on the server -- the user only needs to have a session cookie.
A session object would probably be a lot easier and more secure for your stated concern.
To ensure proper auth cookie protection, you should make sure that you specify a secure encryption/hashing scheme (usually in the web.config) by setting the machineKey validation="SHA1" property (I use SHA1 but you can replace that with a different provider if desired). Then, make sure that your forms auth has the protection="All" attribute set so that the cookie is both hashed AND encrypted. Non-repudiation and data security, all in one :)
ASP.NET will handle encrypting/decrypting [EDIT: only the auth cookie!] the cookie for you, although for custom cookies you can use the FormsAuthentication.Encrypt(...) method, so just make sure that you're not sending the UserId via other cleartext means like the querystring.
HttpCookie c;
c.Secure = true;
Obviously this only works when transmitting via SSL, but this setting tells the browser not to send the cookie unless the connection is SSL, thus preventing interception via man-in-the-middle attacks. If you are not using a secure connection, the data in the cookie is totally visible to anyone passively sniffing the connection. This is, incidentally, not as unlikely as you'd think, considering the popularity of public wifi.
The first thing to address is whether the connections involved are secure. If they are not, assume the cookie or anything else between you and the client will be intercepted.
A cookie can be a liability once it is on the client machine. Review cookie theft, cross-site request forgery, confused deputy problem.
Cookies limitations: size, may be disabled and security risk(tampering). Of course if you encrypt cookie, there could be a performance hit. Session and Viewstate would be good alternative.
If you want it to be stored at client side, viewstate would be better. You can encrypt the string userid and store in viewstate. Session would be best option.
If your database calls are slow, consider caching
Viewstate
what is your preferred method to maintain state of an asp.net page, if it is a public website (involving shopping cart, wish-list etc). I am in the process of designing a website that will need to ensure that the user is not able to tamper with the state (such as delete cookies etc).
Both of those pieces of data (shopping cart & wish list) sound like they should be stored in your database, so they can persist beyond cookies being deleted or the session timing out.
To prevent user tampering you will need to store session state on the server side. A good practice is store it either in a database (sql server) or out of process, which can be either on the same server or another server, sometimes called a state server.
I am in the process of designing a
website that will need to ensure that
the user is not able to tamper with
the state (such as delete cookies
etc).
I would use the session state. It's easy and effective.
You can't stop them from tampering with it as far as deleting cookies etc. Maybe altering the cookies, but not deleting them.
You can store the vital information on the server, so no sensitive information is stored on the client in a cookie etc.
The preferred method of maintaining state is using viewstate. However, you want to keep the amount you store in it to a minimum as it will noticeably affect speed.
If you need to store information from page to page, I would recommend using session state. It's easy and very flexible.
The user will always be able to tamper with any method you use to store state. Consider these examples:
Cookies - can alter, delete
Session - can delete, timeout, change session key
ViewState - can mess with the key
I encrypt my data and store the key in a cookie - such as cart id, user id, etc.. The cookie can be loaded at login and can be tampered with, but because the key encrypted, no real harm can be done. Storing in the session can work, but the timeouts have bitten me on many occasions and requires more considerations.