Is there any real benefit to using ASP.Net Authentication with ASP.Net MVC? - asp.net

I've been researching this intensely for the past few days.
We're developing an ASP.Net MVC site that needs to support 100,000+ users. We'd like to keep it fast, scalable, and simple. We have our own SQL database tables for user and user_role, etc. We are not using server controls.
Given that there are no server controls, and a custom membershipProvider would need to be created, where is there any benefit left to use ASP.Net Auth/Membership?
The other alternative would seem to be to create custom code to drop a UniqueID CustomerID in a cookie and authenticate with that. Or, if we're paranoid about sniffers, we could encrypt the cookie as well.
Is there any real benefit in this scenario (MVC and customer data is in our own tables) to using the ASP.Net auth/membership framework, or is the fully custom solution a viable route?
Update: I found one person (Matt Briggs) who seems to have come to some of the same conclusions I have: This comes from this link: http://webcache.googleusercontent.com/search?q=cache:Xm1-OrRCZXIJ:mattcode.net/posts/asp-net-membership-sucks+asp.net+membership+sucks&hl=en&gl=us&strip=1
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.

One of the first rules of creating a secure authentication system is that you shouldn't try to build the framework yourself. There are many pitfalls that can be easily overlooked. So, I would say unless there is an overwhelming reason to do otherwise, you should use an existing framework like the MembershipProvider.
To list "the benefits" requires listing all security measures that were taken by the FormsAuthentication classes which is a long list. Off the top of my head, I can think a few:
Hashes of passwords
Protection against SQL injection
Protection of the cookie that stores the authentication ticket
Use of and storage of a ticket instead of say a username in the cookie.
Checking on every page to ensure the user is authenticated
Population of the IPrincipal and IIdentity for the current user
Redirection after login (granted a feature)
Handling of failed login attempts
Locking and unlocking users
ActiveDirectory integration
Ability to easily set and change password length and complexity requirements.
Salting (from Hightechrider)
....

I wrote my own after reading through all the stored procedures in the ASP.NET Membership provider. It's not hard and you have much more control at the end of the day.
If you like XML configuration, weakly-typed strings for roles, insecure by default, random web.config files littered through your directories instead of a clean marker interface on your page classes to say 'no account required', multiple database hits for a single login, user objects that aren't loaded from your current ObjectContext/DataContext and the ability to change providers on the fly (woo hoo, who uses that?!) go for the built-in one.
If not, build your own, but if you do, make sure you add salt and encrypt your passwords, and do a proper encrypted cookie please.

Just to clear up a potential misconception, using the customer ID, encrypted or not is extremely vulnerable to sniffers. What you want to do instead is create a log in ticket at the time of successful authentication and store that ID in the cookie. This won't protect sniffers from stealing sessions, but at least the session (eventually) expires whereas the customer ID does not.

You can implement your own membership provider (as you mentioned) if you wish to have your own storage. One advantage is that you can administer memberships through IIS' .NET users configuration tool.
The biggest advantage is what the others stated already; why reinvent the wheel?
If you implement your own custom login UI using MVC you could reuse also when switching for a different membership provider.

You can customize to build your own provider. Behind the scenes the Membership provider uses the same FormsAuthentication implementation as you will write. Anyway, I have read that the main issues about the performance you will face will be related to the SQL SERVER stored procedures that retrieve the data. In one of the books about building a portal system by Omar Al Zabir he mentions some improvements to the stored procedure which can result in faster performance.

Related

Granting Secure Access from one website to another

I'm really just looking to see how much folly is in the below suggestion from a security perspective.
I have two websites. One is an administration portal and the other is a members portal.
Within the administration portal administrators can retrieve a listing of members and I need to offer the ability for administrators to login to the member portal without having to enter the members login credentials.
Both are separate websites within IIS and for this discussion lets say they are on different servers.
Both websites access the same SQL Server database.
I was thinking that I could on the administrator clicking a "Login as Member" link create a random code string and save this to the database along with the member number.
I could then pass the code and member number to the member portal as query string parameters.
The member portal then read in these values and checks them in the database to verify that the code string exists and if so that it matches the member number also being passed. I could then login the member and set a flag in the database to set the code as being used and therefore invalid for future requests.
I'm thinking to bypass this a hacker would need to successfully guess the random code and pass that to the page alongside the corresponding member number for that code and for that combination to be marked as unused in the database.
This would seem to be unlikely given that only seconds will pass between the code being generated and the code being used.
If necessary I could always check the IP address of the request as users of the administration portal all share the same fixed IP address.
So do you think the above would stand up to scrutiny on a security review or will I need to go down the SSO route?
Your approach is very sound. I can confirm because I have implemented just such a solution for just such a reason. We analyzed the options and exposure. And after implementation, our application passed a PCI Complaince Audit.
Reasons:
SSL is Esential! protects against sniffers. Essential. Without Encryption, sniffers could detect your GUID and may have a window to use it)
As Tony pointed out, the GUID is effectively unguessable.
Guid Tokens expiring should expire within 24 hours.
Suggestions:
Checking against IP is good. But don't be fooled into a feeling of security from it. Anyone can fake IP's in headers. To be Secure against XSS and CSRF by using AntiForgery tokens.
The AntiForgery token is a cookie that populates your HTTPHeaders with __RequestVerificationToken which is almost as hard to guess as your GUID.
Consider using an established Authentication framework like .NET Identity 2 and multitenancy.
An established framework takes the burden of encrypting your passwords. MS Frameworks like Simple Membership and Identity integrate into modern ASP.NET frameworks and give you very strong base of functionality to lean on.
If you're using an old framework like classic ASP or .NET 2.0, the classic Membership Provider is more appropriate.
If you are creating new MVC 5 applications utilizing Entity Framework, I strongly suggest using Identity 2.1.
Consider Mult-Tenancy. While there is nothing wrong with your solution, if Admins and users shared Membership Provider, your solution would be cleaner. An admin could log into the main site and "get" the token from the DB. Then no exposure.
Assuming the use of HTTPS and adequate physical and IT security processes and procedures in place for the administrators, this method should be adequate. It is more secure than most financial website password resets, which typically only require a compromised email account and some personal information to reset the password. If you check the IP address range of the originating client request as well, a hacker would have had to already have access to your systems or network. Also, if you make the code a GUID, it would be (pragmatically speaking) impossible for someone to guess.
You could add a layer of checking for hack attempts by storing a record in the database each time this event occurs (or at least each it fails due to a bad key), and each time it occurs run a check to see if it is happening too often (like 100 times in the past hour, or something--the right number depends on how often you expect it to happen). If it's happening too often, then have it send an alert to IT personnel and revert so that the user has to enter their credentials manually.
Disclaimer: I am not a security expert by any means, so I'll gladly defer to anyone claiming such status. I'm weighing in here due to a lack of answers.

Session Authentication equivalent to FormsAuthentication?

I'm using a login form to authenticate users.
FormsAuthentication is right out as it stores sensitive user/role membership in either client-side in a cookie or within the URL. Within the URL is a huge security risk, so I won't even get into that. With the
FormsAuthentication cookie, this creates problems with a) security where the client is in the position of dictating it's own roles; and b) way too much data stored in cookies. Since I'm gaining nothing through security and loosing out big time on the size of user data storage, I'd rather just work with Sessions.
I'd like to reuse something like FormsAuthentication for all its basic login form-handling features. But i would rather have it store user data server-side in perhaps Session rather than client-side all stuffed into a single cookie. I'd rather just authenticate against a Session token of some sort.
I have no database and local disk storage of user data is forbidden. I rely on a 3rd party authentication service provider, and a requirement is that I must reduce chatter with this service. Thus, sessions for temporary storage of user info. Sucks, but that's not necessarily the problem I'm asking about. Also, a requirement is that I must set/use HttpContext.user and likely Thread.CurrentPrincipal for use later on in such things as AuthorizeAttribute, for displaying user info in views, etc.
So FormsAuthentication stores all user data client-side in a cookie. Whereas Session stores all data server-side and just relies on a simple client-side token cookie. However, Session is not available anywhere during the asp.net startup and authentication steps. Is there an equivalent forms "membership" provider that stores all data in Session server-side instead of client-side?
If there is no Session equivalent...
Where do I set HttpContext.user and Thread.CurrentPrincipal to make both values available throughout the rest of both MVC apps without interfering or messing up other MVC components?
Hinging on #1, is Session available at that entry point? If not, how do I make it available so I can create the Principle/Identity object using the data stored in Session?
This can't possibly be a unique requirement. Are there libraries already available which handle this?
Session stores information in a client-side cookie too! (or in the URL if cookieless).
If you want to authenticate a client, he'll have to provide some kind of credentials - usually an encrypted token in a cookie once he has logged on. If not a cookie, then what do you propose?
You should use FormsAuthentication. The sensitive information stored in a client-side cookie is encrypted using a key that should only be known to the web server. "the encryption methods being public knowledge" doesn't mean that you can decrypt the data without access to the appropriate cryptographic key.
You mention "roles" and a "third-party authentication provider". If your third party is also providing roles (i.e. an "authorization provider" as well as an "authentication provider"), then it would be reasonable to cache roles obtained from the provider on the server. Session is not available when a request is being authorized, so the best solution is to use the Cache (System.Web.Caching.Cache).
Personally I would encapsulate this in a custom RoleProvider. The custom RoleProvider would implement GetRolesForUser by getting roles from the third party on the first call, then caching them in Cache.
Not sure if I like what I'm about to suggest, but you could do the following:
Leverage the Application State or System.Cache as a global storage for user credentials.
Use an InMemory database (like RavenDb) which can also have encryption (in memory, I believe).
Using the Application state as a place to storage relatively common / frequent stuff I think is not a great place because of
Scaling / locking issues? <-- just a gut feeling.
Permenant data? so you have users in the website's memory .. then the website crashes or recycles, etc... what happens now to that data?
RavenDb is awesomeballs - go.use.it.now.
I understand that you are not storing anything locally, so whenever a user hits your system, you need to refresh your inmemory cache, etc. Fine. A pain in the f'ing butt , but fine none-the-less. (EDIT: unless the data has been cached in memory .. that is)
Anywys, two suggestions.
ProTip:
Oh! move away from role based shiz and start using Claims based identity stuff. Yes, it still works with IPrincipal and HttpContext.User, etc. So all previous code is NOT busted. But now it's baked into .NET 4.5
Awesome Video on this for you, me, everyone!
Finally - bonus suggestion
A nice package that auth's with either Facebook/Google/Twitter. You said you're keeping the user cred's on another site (good move!). If you're using other providers, then stick with DNOA or SS.
GL!

ASP.NET username/password security

I'm using VS2010,C#,SQL Server to develop my ASP.NET web app, although this is not my first ASP.NET experience, but this time my project is more attack-prone and I should consider better security polices. I have a login screen as my first page, users enter their user name and password and a page specific to them is showed, in my last project, I used query strings (a userid) along with sessions for security purposes, but this time I've used just query strings, it means that at the moment one can enter myaddress.com?userid=1 and visit a page in my site!!!
I know this is not good, but what are my approaches, of courses I'm not working with banking or financial systems but I'm going to have an standard security policy, I should use sessions? cookies? can you suggest me an easy-to-develop and meanwhile secure way of implementing protection policies? any sample code or tips?
thanks
ASP.NET actually comes with all of the facilities you need to provide a secure site out of the box so you don't have to worry about all of these things yourself.
Use the built-in ASP.NET Membership features and you'll be fine.

How to maintain User-session with ASP.NET MVC

Hey folks, I would like to know is there any way i can maintain stuffs like log-in,log-out,user-session..etc without using membership in ASP.NET MVC?
Faraaz.
There are three provider models concerned with the areas that you are referring to.
The MembershipProvider is concerned with authentication, validating users and storing data related to the user such as last login date, username, etc.
The RoleProvider is concerned with authorising users for particular areas of your application.
The SessionStateProvider is concerned with storing session for your application.
You can write your own custom provider for any of them if the default providers are not suitable. You could roll your own authentication, authorisation, or session management without the providers, however there would be quite a bit of work involved more so than implementing your own custom provider.
You can use the Session object to store session scoped data.
But for authentication/authorization you will need to come up with your own scheme.
You need to use the Session dictionary and a session state server. See http://msdn.microsoft.com/en-us/library/ms178581.aspx for more info.
Word of warning: In my experience the InProc session state mode only preserves the values you put into Session for the lifetime of the current HTTP request. They don't persist across requests as you might expect, even when you're using a single HTTP server and you'd think in-memory storage would persist. This may only occur while debugging using the built-in http server in VS2010, but even so it can cause you a lot of trouble trying to understand why state information isn't being saved.

What is the recommended method for user-specific persistent variable storage in ASP.NET when using a custom membership provider?

I have an ASP.NET application that uses a custom MembershipProvider to allow users to log in and gain access to certain features. The MembershipProvider uses ASP.NET's built-in forms authentication to set cookies and keep track of who the user is.
Now that I've got the user logged in, what's the best way to store user-specific information for their session? In the past I've just used Session variables ie Session["ReputationLevel"] = "4230"; (my application doesn't actually have a reputation level variable, this is just an example). Is this still the best way when using a MembershipProvider? Would it be better to somehow build this information into the provider itself, or into a custom MembershipUser implementation? If I keep everything in the session, I suppose I'd have to abandon the session when the MembershipProvider indicates that the user had logged out...?
Sorry if this question is vague. I've been doing mostly ColdFusion development for the past few years, and I'm still kinda new to some of these ASP.NET technologies. I thought the MembershipProvider functionality would take care of everything I needed, but I'm now seeing there are still some holes in my implementation (in this case, where to store additional data).
This question appears to be similar, but doesn't appear to be quite what I'm asking.
If you want to persist the information beyond the session, it's probably best to store it by user in your database. There are several ways to do this:
You can roll your own by manually storing and reading in data from a SQL table as needed -- possibly using the runtime cache to save from hitting the db on every request.
You can extend MemberShipUser in your custom membership provider and add the properties to it. Here is a walkthrough...
You can use ASP.NET Profiles, which might be the easiest way to go and it supports storing data for unique unauthenticated users as well. Here's a walkthrough for profiles, although there are several more out there.
I'm not sure how you would do it, but I suppose you could extend the Membership provider to do that. But personally, I've found that ordinary sessions work just fine. Only thing I'd do is to wrap their functionality in a a set of shared functions. So your example would be:
static string GetUserReputation()
{
return Session["Reputation"].ToString();
}
and just call GetUserReputation

Resources