Using FormsAuthentication build into asp.net it's very quick and easy to create a login system that creates a cookie for authenticated users:
FormsAuthentication.SetAuthCookie(uniqueUsername, false);
Paired with some code in the Web.Config file:
<authentication mode="Forms">
<forms loginUrl="Login.aspx" timeout="30" defaultUrl="Dashboard.aspx" protection="All" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
This will bounce all requests back to Login.aspx until the user is approved and a cookie is created using the SetAuthCookie() method call.
Is this secure enough?
The rule of thumb I use is that I don't store any data on the client that they've not sent me. So what I've done in the past is hold the username and password used in a cookie, then re-authentic this with every request.
There's the extra overhead of re-authenticating everytime with this approach, but it also means I've not storing any server data on the client.
My worry
My concern is that by using the SetAuthCookie() method call, that the username is being stored on the client machine. Is it then possible for someone to break the encryption being used and substitute the username being stored for another?
I think I'm being overly paranoid and that the type and level of encryption being used is adequate, but thought I'd get some expert input on the topic.
So what I've done in the past is hold the username and password used in a cookie, then re-authentic this with every request.
You should not use this approach. The password should not be stored in an authentication ticket. The reason being is if the authentication ticket is compromised then the attacker has the user's password. This risk can be mitigated by encrypting the authentication ticket cookie, but I presume you were storing the cookie in plain-text.
My concern is that by using the SetAuthCookie() method call, that the username is being stored on the client machine. Is it then possible for someone to break the encryption being used and substitute the username being stored for another?
As Shiraz noted, the cookie is only persisted on the client machine if you create a persistent cookie. (One of the parameters to SetAuthCookie
indicates whether or not to create such a cookie.
Even if someone broke the encryption scheme to modify the cookie to supply a different username they'd run into problems because the authentication ticket is also digitally signed, meaning ASP.NET can detect if the contents of the cookie have been modified. To forge a digital signature the attacker would need to know the salt used by the server, and if the user can figure that out it implies he has access to your web server's file system, so now you've got bigger problems.
Another thing to understand is that the authentication ticket has an expiry, which puts a finite lifetime on the validity of the ticket. So even if someone were to steal a user's cookies, the time the attacker would have to use that stolen ticket would be limited based on the timeout
value you specify for the forms authentication system (30 minutes by default).
In conclusion, the official ASP.NET forms authentication system is going to be much more secure than something a lone developer will be able to implement. Developers should strive to use the forms authentication system rather than roll their own solution for a myriad of reasons, including better security, not having to reinvent the wheel, adopting standard practices so other developers who join the team don't have as large a learning curve to get up to speed, and so on.
For more nitty gritty details on the forms authentication system and how the ticket is secured, how the various <forms>
configuration settings work, and so on, see: Forms Authentication Configuration and Advanced Topics.
Just some random statements about your thought process, but in regards to
So what I've done in the past is hold
the username and password used in a
cookie, then re-authentic this with
every request.
@Scott Mitchell brought this up already and discussed reasons to not do this due to security implications of this.
I felt it would be worth pointing out why this would not make sense (even disregarding security implications of leaking information). The reason you are generating a forms authentication ticket (the cookie) is that you letting ASP.NET stamp this users browser with that ticket that lets you acknowledge this is the specified user that has already been authenticated.
By issuing them a ticket you are doing so to imply they do not need to be authenticated as they have already been previously.
A good analogy to this is you goto a bar, on your way in you get your id scanned by the bouncer to make sure your id is legitimate and that you're over 21. Upon confirmation of this, they give you a wrist band that is a certain color / design.
With your wrist band you are able to leave the building to smoke and return inside circumventing the line and the need to have your id scanned allowing you to return that day. Now should you go home, but not take the wrist band off when you goto bed (like leaving the browser open over night) you come back to the bar the next day and attempt to show your wrist band to bypass the line. At this point you're rejected because you have last nights wrist band and are told to get to the back of the line and get authorized again.
If you set the DisplayRememberMe property to false the cookie will not be persisted on the client machine. It will then just be stored in memory.
If you use HTTPS/SSL it will be protected on the way to the client machine.
There are then only theoretical possibilities left:
- Break the SSL encryption
- Steal the cookie from the memory of the client machine
Followed by breaking the encryption on the cookie.
There are probably some easier ways to attack your system.
http://msdn.microsoft.com/en-us/library/ms998310.aspx