I'm using Forms authentication in ASP.NET MVC website and I store user account login name in AuthCookie like this:
FormsAuthentication.SetAuthCookie(account.Login, false);
I want to ask if there is a possibility that user on client side will somehow manage to change his login name in AuthCookie and thus he will be for example impersonated as someone with higher privileges and authorized to do more actions than he is normally supposed to have. Also is it better to save in this cookie user account login name or user account ID number?
The cookie will be encrypted and decrypted on the server side, so unless the user can crack the encryption key, he or she won't be able to do this.
As long as the information you store uniquely identifies your user, the choice as to what that information is is entirely down to the requirements of the particular application.
No it is not possible (well, in theory maybe but it's not feasible in practice). The value of the authentication cookie is encrypted so the user can not tamper with it. It is a good idea to store the (unique) login name in the authentication cookie, because when the IIdentity object (HttpContext.Current.User) is restored, the value that you passed to SetAuthCookie is used for the Name property of the IIdentity. The Name property will be shown if you use the LoginStatusControl, for example, so it's a good idea that the value of the Name property makes sense to the user.
Cookies are encrypted so chances for that a quite slim. But still.
More than one property approach
If you'd like to make your security even tighter you could save username as well as user ID or some other data that can't be guessed from the username. The combination of these makes it safer because if you can guess one it harder to guess others and use the correct combination of them. Ie. If you guess other user's email/username it's a bit harder to guess the same user's ID, because they're not related. So the more unrelated properties you combine the more steps it takes to get the right combination.
Logon security token approach
You could use an alternative approach described in this scenario:
User logs in.
Generate a random security logon token that can be of random length with some minimum length defined and save it against user in the data store. This is probably not a problem while it's quite common that other data is stored at logons as well like LastLogonDate info.
Use this token and save it in the cookie instead of usernames or other info.
If user logs-out, clear logon security token from the data store
User logs in again... go back to 1 and create a new token again and use it in this session.
This way it will make it safer on the long run, because this information will change on each login and if user does manually logout you can always clear that token from the store, so it won't at all be possible to inject someone else's identity. This does make it a but more complicated to use permanent cookies though but it can still be done.
This approach is not bullet proof but it provides additional security level that prevents the same attack over and over again when one account has been compromised. And also when one account is compromised it doesn't mean that others can be as well. If your security tokens are long enough it would be much harder to start a brute force attack on your site and while this kind of attack would be executed security tokens will change so it is definitely safer.
Related
i've read all the tutorials and questions asked about the subject but they contradict one another
claims(userclaims and roleclaims) are serialised into a cookie (along with custom identity user properties you specify by overriding the principle factory) but they don't get queried, they're stored in a cookie, which mean that the more claims a user have, the more data will have to round trip between the server and browser
a custom identity user property by default don't get serialised but get queried from the database, so every time you need that data it query it from the database which is more work to do on the database on each request if you frequently query for it
so which is more efficient and which is safer
for instance
IsAdmin should be a role/claim? but then if someone stole the cookie, nah nah, the cookie already contains userid/username/securitystamp, so even if it's a property, the userid on the stolen cookie would query on the custom identity user property, or is there something that will prevent this cookie from working when stolen ?
another instance
if i've 20 property for the user (first name, last name, address 1, address 2, postal code, whatever the case may be), should i simply have the user wait a bit for a bigger slower cookie to be send back and forth or should i do all the work from the db using custom identity user
but then, if i remove or add a claim to the user, would it be updated on the next request if it doesn't get queried or is the security stamp validate that this cookie is still valid ?
cause at the Task AddClaimsAsync of the userstore of efcore it only add the claim to the dbset
i apologize i know this is many questions to ask but the resources on the matter are not that good and one can easily get lost reading the identity source
Rule of thumb - put frequently added items as a claim, everything else can live in DB and be queried on demand. I.e. address 1, address 2 can't be required on every request, so keep them in the DB.
On the other hand IsAdmin (should be a role anyway) I can imagine will be checked on every request, so it should be in the cookie without having to query the db.
If you afraid of your cookies getting stolen, don't show them to anyone! set up SecurityStampValidator to do frequent checks - like every 5 minutes. This basically updates the cookie with the fresh information from your database and changes the cookie. So even if the cookie is stolen, it will only work for 5 minutes.
I don't think the two statements contradict, it depends on your configuration. The second statement mentions "by default".
You do not need to store all information in claims nor do you need all the information all the time. If you want profile information, call the server once and store the information on the client, or get it when needed only.
The same counts for authorization, in case you want to show / hide elements based on permissions. This may include a tag called "IsAdmin". Authorization should be kept close to the resource.
If your client wants to refresh the information, just call the server. Claims are not updated during each request. In general, the user has to log out and log in again. So Claims are not flexible and therefor not really suitable for properties that can change (frequently).
As for safety, it doesn't really matter that the client can alter the information, it is for display only. It doesn't change the permission in the backend.
You can consider to add something like a display name to the properties, if you are showing that in every page. You can also consider to implement caching to limit database calls. In the end it really depends on your requirements.
As for stolen cookie, you'll need to implement additional security to your server to detect suspicious behaviour. You may want to include the ip address as claim. As for the admin, add security, e.g. filter by ip address and / or use an additional code which was send by email.
I am creating a new asp.net MVC 5 application. Authentication is handled by a third party using smart cards. Once a user is authenticated by the third party, I am sent the user's unique ID (inside the http header) which I match up against my database in order to find relevant information about said user (roles, display name, etc.).
Currently, on every page request, the sent user ID is compared against the database, and checks are performed to ensure the user has the proper permissions to view the requested page. While this works, it sure seems like a bunch of needless database hits when all the user information could just be stored in a cookie.
If I was using Individual User Accounts for authentication, what I am looking to do would simply be built in using Identity and OWIN. But since I am not handling the authentication, but merely the authorization, is there a way to use all the nice features of Identity and OWIN (claims and cookies specifically)? If not, how might one go about this?
Also, of particular interest to me is when a role is added or removed. Using OWIN with Individual User Accounts, updating the cookie is as simple as logging the user out, and then back in immediately in the background. That functionality would also be desired for any solution presented.
Any insight would be extremely helpful. Thanks for reading!
You could do what you're asking by directly storing values in a custom cookie, but for your purposes it sounds to me like you might be more interested in utilizing sessions to track that info. This will keep all of your actual data stored server-side, which is more secure as it isn't vulnerable to cookie modification and it allows you more freedom to control the state (for your role example, you wouldn't have to "update" the cookie at all, just update the session variable on the server side to add or remove the role as needed).
Figured it out. Found a great article that really helped:
http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux
I'm starting to size up a project where I feel security needs strike a little closer to home. What tools and techniques could I look at to attempt to raise an alarm when a valid login is used, but the owner of the login has given it away or had it stolen. I would prefer ASP.NET, then MVC 3, oriented stuff.
This is not a silver bullet, but perhaps you should consider employing some kind of two-factor authentication. For example: when a user creates an account with you, you require that she provide you with a phone number where she can receive text messages as part of the registration process. Then, when she attempts to log in, you text her a temporary authentication code to be used in combination with her username and password.
This ads an extra layer of security to the system, because an attacker would have to both know her username and password and have physical access to her cell phone in order to compromise her account.
I hope that's helpful.
Seems like you would get a lot of false positives... but you might try checking what IP address the login is coming from. Most people will log in from the same IP address most of the time, so when that changes, it's at least a warning sign. If you want to be very strict about security, you could maintain a whitelist (for each account) and require that they get their IP address added to the whitelist before logging in.
My bank (Chase) does this by checking a secure cookie during my username/password login. If the cookie is missing or corrupted, they require a second form of authentication, which is either a code sent via text to my phone number on file or via email to my email address on file. Once the second form of authentication is complete, they set the secure cookie and then I can login from that browser with only username and password.
Implement your own Membership provider and add field locked to model,
check for user being locked on login and do some actions
It might be useful to think of the factors of the Authentication process, so that you can be sure that you are sufficiently covering things. You can easily get ridiculous with the layers of assurances, but I happen to find that most banks now have a variation on a simple model. All of this is, of course, over SSL
User submits account name. Additionally, you can require a secondary piece of information, last 4 of account number or year part of date of birth.
Optional, but a good idea: present the user with a counter sign, that is something that verifies the identity of the server. The user selects this at registration and should be looking for this every time they attempt to log in. This aids in preventing phishing.
System checks to see if the current system using IP lookup or cookie is associated with the account. If not, presents challenge question along with password input. Otherwise, presents just the password input.
Complicated, but can actually be done in 2 pages and more secure than is usually required.
I've presented this workflow to a few bank clients and they usually remove one or two of the checks for a balance of user friendliness.
With phones with text capabilities being so common, the idea of SMS verification code as mentioned by others is also a good idea, though I haven't implemented this in a system yet, personally.
I am developing my login for my new homepage.
Now I found out, that I must save something like the userID (or another value that i can recognize my user) in the session variable of the browser.
At the moment I use INT for the userID.
So isn't it unsafe to put the userID in the session?
E.g. when I edit my session variable manual from userID 111 to userID 112, than I am logged in as a complete other user?!
Yes, it is unsafe to rely only on user ID.
You may wish to add a unique authentication token generated and remembered by the server. Also a very simple solution, but it will stop manipulating the user ID since the correct value for authentication token for the other user cannot be guessed.
You also need to submit both user ID and the corresponding authentication token at each request to be jointly validated on the server side, prior to performing the requested operation.
P.S. The above applies if you store this information in cookies which are accessible on the client side and can be manipulated. The viewstate (serialized in pages) can also be manipulated. The session collection is a server-side variable that is not available on the client so it cannot be manipulated. In this later case your user ID should be safe.
I would recommend you to implement the dual system: store the user ID and the token both in cookies and in the session and use the same validation logic (for simplicity). Should cookies be disabled you automatically fallback to using the session without changing your code.
The session variable is not stored in the browser, it is stored on the web server. (Typically anyway.)
A token indicating which session variable to use, is stored in the browser.
So storing the userid in the session variable is fine, as the user has no access to this directly.
If the user were to change the session token, to another one, that would be a problem, but they'd need to know the other token first. (I'm not sure how to do that myself.).
(You can further diminish this by using encryption, or other identifies like IPAddresses etc, it's really a case of how secure do you need your website to be?).
Also, if your site needs the user to log in, it's advisable to use https/SSL.
As Bravax says, the user does not have access to the Session variables (Cookies they do have access to).
If you are worried at all I would use a GUID instead as they are not sequential and nearly impossible to guess.
Also, have you looked at the built in stuff in .Net for authentication? Look at FormsAuthentication.
HTH,
Arry
I've got an existing site I'm taking over, and right now it stores, in a session variable, the id of the currently logged in user (if logged in at all -- otherwise I'm sure it is empty string or null or something).
The client now wants, after someone is logged in, to "keep" them logged in on that computer for an indefinite amount of time.
ASP.net Sessions have a maximum idle time of 1 day, I believe. The website isn't written all that well in the Flash portion (whole front end is flash) and the flash will process a login, then, as long as the flash isn't reloaded, assume that the user is still "logged in".
I think my solution is to ALSO store a client side cookie with some GUID value and hold in the database the associated user id...sort of like a session that never expires. So, when the page is loaded, I can check my cookie, use that to select the userid out of the database, and if we find one, then set the session value that says user 23 is logged in.
Does anyone see any issues with this perspective? Would you recommend something different? I really don't want to refactor a bunch of the existing code, but just slip this in on top...
PS -- security is not really a concern. The only reason they have people log in is so we can track orders by a person, but no money changes hands through this website. There is also no personal information that a user can view or edit, either.
This is how I do it. I actually have a cookie that holds their login and password, this way I can automatically log them in should they not be logged in. I expire the cookie after a couple of days of inactivity. The downside is that everyone forgets their password because the only time they really have to enter their password is when they come back from extended time-off.
This is for an internal application, with the same customer demands that you have and this works ... and makes the customer happy.
One thing we may end up doing is just using Windows authenication, might actually work better in this circumstance.
That's the way I do it, but the problem with it (at least I think its a problem) is that when you store the username and password in a cookie there is not any encrypting when you add the cookie. If you look at the cookies in your browser the username and password are displayed there plain as day. Is it possible to get some kind of encrypting on the cookies you store? Or how would you handle this?
Check this blog posting out http://timmaxey.net/archive/2009/03/06/asp.net-cookie-auto-log-in.aspx basically you needs to save the cookie with a guid a series, and a token, the token, in my case, changes all the time, the series is something that is generated based on something, like the guid and id combo or whatever, then the guid is always stored with the user. There is a cookie table to stored this info etc... pretty secure, not 100%, but pretty good... Tim Maxey
I recommend using the Enterprise Library Crypto App Block to store an encrypted cookie which is nothing more than a GUID. Get the GUID, and use a session table in the database to track user info.
At the session start event, get the user info and cache it.
Using the session object is not recommend for user info because it won't work on a web farm, unless you use a database for session state.
You're basically rolling your own session state at that point, and I'm fine with that. However, I would not go the route of storing the username/password in a cookie (even if encrypted). There's no way to expire that from the server-side. You can always remove your row in the table to force a user to log in again, but if they hold the username/password they hold the keys to the kingdom.