ASP.net Membership Sucks.
ASP.net Membership was written to fill a big hole in the ASP.net 1.1 ecosystem - a lack of an authentication API. While that is a worthy goal, I don't think they implemented it as well as they could have.
Being Everything to Everyone
The API almost looks like someone ran down a checklist. It has to be RAD, because mort needs an easy system. It has to be extensible, because no two auth systems are the same. It has to have extensibility points, so that people can customize it. It has to plug into the myriad MS authentication technology for product synergy.
It has to be RAD
RAD is great for small project, the choice to configure the system using XML is questionable, but the idea that you have a fully featured system out of the box is a good one. The other great leap that they did was to assume that everyone is using SQL Server, so they (helpfully) implemented a great deal of logic in about 150 SQL Server specific sprocs. Thanks.
The problem with RAD tools, is what happens when you need to step outside the box? That leads us to
Extensibility
Ok, so people need to be able to create custom profile fields. If we didn't have the RAD constraint, we could just let the developers create their own profile model. Unfortunately, it has to be RAD, so to implement this, they created a colon seperated index and colon seperated value fields in the DB. Ok, but what about complex types? you ask. XML is the answer. Colon delimited XML blobs in the database. Pure awesome. But wait, there is more
So to recap, we now have:
- PropertyNames, which looks something like
FirstName:S:0:7:City:S:7:7:PostalCode:B:0:-1:Region:S:14:7:Country:S:21:2:PreviousSessionStartTime:S:23:81:LastName:S:104:7:CurrentSessionStartTime:S:111:90:
- PropertyValuesString, which looks like this
NameTorontoOntarioCA<?xml version="1.0" encoding="utf-16"?>
<dateTime>0001-01-01T00:00:00</dateTime>LastName<?xml version="1.0" encoding="utf-16"?>
<dateTime>2009-10-15T20:12:15.0513774Z</dateTime>
- PropertyValuesBinary, which is just a big binary blob
The profile data is officially obfuscated.
Extensibility Points
Apart from the paragon of software engineering that is the profile system, there is the Provider model, which is an implementation of the Abstract Factory Pattern, which is basically a factory of factories. Sounds enterprisey? Hells yeah.
Step one to implement your own, is to extend the base class, which has about 30 required methods on it and a Profile Provider with about 15 methods on it. Both have a whole bunch more optional ones (which are basically just stuff specific to the default providers). We know that using inheritance over composition leads to fragile code, due to how inheritance is a form of tight coupling, but MS apparently didn't get the memo. We also know that we shouldn't have God Interfaces, but should instead use multiple smaller interfaces to allow for fine grained implementations. Again, this idea was the furthest thing from the minds of the MS developers.
After you get that done, to use it you need to register about a billion different options in your xml based config file. To be fair, MS didn't invent programming via XML, but they sure are perpetuating it. Again, this comes back to the all things to all people mentality; what happens if I don't care about supporting multiple authentication environments in a single application? (probably the 99% use case) Doesn't matter, I still need to configure those settings.
MS Integration
This seems to be what everything was built towards. It is effortless to plug into anything from XML auth stores, to ActiveDirectory. While that is awesome, what about things that web applications outside of MS actually need? Like OAuth for example?
Fine smartypants, what would be a better way?
Let's take the excellent AuthLogic project. Instead of being a system that you have to integrate with, it is a system that integrates with you. You tell it that your user model is your user model, and it will look for specific fields (convention over configuration ftw
This is clean, it is simple, and it is WAY more extensible then the ASP way. The difference between the two is that instead of getting started instantly, and then banging your head against the wall later, you put a bit more work in at the beginning, and have something that will grow in whatever way you need it to.
Fine, but what about RAD???
That is a valid point, something like AuthLogic is overkill for situations where all you really need is username and password, and it wont really grow much passed that. Well, in rails we have something called restful_authentication, that will generate up a simple auth system for you with all the trimmings. Very little work, I would say less then actually configuring ASP.net Membership, and if things change down the road, you can customize the generated code in any way you need to.
At least Microsoft delivers something that frees me from thinking about security
Yeah. As long as you don't care about session fixation attacks, which MS is vulnerable to out of the box. MS knows about this, but has decided that instead of fixing it, they will put up a kb article that recommends every ASP.net page includes a 50 loc snippit to get around the issue.
Do people know about this? Of course not. I mentioned it a few times in team meetings, and passed articles around talking about how .net apps are vulnerable to that attack vector, but still heard people talking about the symptoms of a session attack only failing because our code is very rigid in a few places (exact quote Someone must just be using two different browsers as they go through the checkout process)
Conclusions
ASP.net membership is a poorly engineered API that is insecure out of the box, is not well maintained, and gives developers a false sense of security. Authentication is a weekend project if you aren't building a framework, but still, most .net developers blindly follow the official APIs, assuming that a major corporation like MS can put out something decent.