I'm considering converting my existing MVC 4 which is currently using ASP.NET membership for authentication and authorization to the new ASP.NET Identity model now available in MVC 5 and the like recently released with VS 2013. Aside from upgrading to MVC 5, does anyone have thoughts on what would be needed to convert the application to this new framework with the least impact on existing users?
Ideally I'd like to preserve their password hashes and salts to keep from forcing users to change their password after the conversion. Also, there has been talk of implementing Federation as an alternate login for some clients so I'd need to use the claims capabilities in the new system too.
Any feedback would be appreciated.
There are basically two basic ways to migrate the user accounts:
all at once: for this to work, the hashing algorithm "configuration" needs to be identical on both systems (if "one-way hashing" is used, and it usually is) because there's no way for you to know the users' passwords during this kind of migration. All you can do is just copy the data from A to B.
"rolling": move the accounts one at a time, more specifically, during the logon phase, when you happen to know the user's password, so you can do pretty much anything with it (like creating a new hash and store it somewhere else). But, the downside is that you need to keep both old and new authentication system up and running for an extended period of time (depending how long it's gonna take for all of your users to log in).
If your MVC 4 project uses the default "simple membership" provider, the good news is that the hashing algorithm used is the same. Simple membership is open source, here's the crypto code:
https://github.com/aspnetwebstack/aspnetwebstack/blob/master/src/System.Web.Helpers/Crypto.cs
The new identity system is, unfortunately, not open-sourced, but it turns out it uses the same algorithm (yay!) -- just copy a password hash and it'll work (don't worry about salt -- it's included in the hash "blob")!!! So, "bulk" migration is definitely possible.
However, I strongly suggest that you don't do this yet. The new identity system seems to be in flux, so maybe waiting a couple of weeks is a good idea at the moment. For example, the source code may become available (so I could finally see how the "SecurityStamp" value works and what's it for :)
OTOH, if you are using the old, "pre-simple membership" (pre-MVC4) authentication, it utilizes a completely different hashing algorithm (SHA256, IIRC), so there's no quick way to migrate -- you'll have to wait for all your users to log in to move their account to the new system. (Of course, you could accelerate the process by sending them an informative email about why they should do it asap :)
I hope this helps.
Wrt Federation -- I have no idea :)
Related
I have been doing some research about how to do custom profileprovider in .NET MVC.
It seems pretty complicated. Is there any other alternative?
And this is my major concern, why do ppl bother using customer profileprovider? If they want extra information about a user, why don't they just make another table with OneToOne relationship with aspnet_Users with userId or userName as the foreign key?
Please clarify. I'm trying to implement user profile functionality, but I don't wanna go down the wrong path.
Thanks
DG
(not to sure if this helps talk about custom profile providers.. unless I'm misunderstood...)
IMO, what ever you do .. avoid (the baked in) ASP.NET Membership at any cost! It's sooooo over engineered, you'll want to stab yourself in the eye with a blunt spoon :(
Trust me. avoid it.
Why: Should I use the built-in membership provider for an ASP .NET MVC application?
So .. what can we do instead?
It's just so simple to roll your own Username/Password and leverage the built in Forms Authentication. For myself, I'm not a fan of storing -any- passwords in my own database .. so i prefer to use Facebook, Twitter or OAuth as my mechanism for authentication .. which then means I finish up with a simple, basic, custom user class.
I also create my own custom IPrincipal and IIdentity because I want to store a bit more info in the cookie, which Forms Auth creates when a person has been authenticated. This then helps keep my code in my Controllers cleaner and way simpler.
For example, I store the userId of the authenticated person in an encrypted cookie. (the default option is to only store a Name). I also store one or two more things .. but you get the idea. This way, I don't always have the hit the DB to retrieve any user data OR store this crap in a session.
With a roll your own, u can create extra meta data (birthday? mum's maiden name? social security number (joke) ) .. and have that extra profile data. Same table? extra table? who cares ... that's a decision to make way later (and EASY to solve). Get your model right, IMO :) Then once u've locked down your model, you now know what's required and what's optional .. and u can make some DB decisions then.
TLDR??
Avoid the built in ASP.NET Membership crap
Roll your own .. and keep it simple.
If you're feeling advanced, also roll your own IPrincipal and IIdentidy to really rock your world.
GL HF and don't stab yourself with a blunt spoon, in your eye!
For my ASP.NET MVC app, I just find dealing with unique-identifiers harder, so I have added my own field to ASPNET_USERS table - UserIdInt (which is actually a bigint!) So most of user operations use userIdInt as reference.
Anyway, I am debating between two approaches:
1)When a user logs in, look up from the database and store the userIdInt in a session variable and any-time session variable slips away, re-look it up and put it back in session variable. (It's okay to use sessions in MVC app, right?)
2)Any time an operation needs to be performed, simply pass userName to database and take care of UserIdInt at database side by doing joins and such on ASPNET_Users table any time an operation from user needs to be performed.
I am heavily leaning towards 1)... but I want to make sure I am on right track.
I asked this question on Serverfault first, but I was told to ask this question here.
progtick,
you may be far better looking into the use of custom profile providers as this would allow you to leave the aspnet_* tables as is (which is a good idea in case a later version of sqlserver changes how they operate) plus offer the additional bebnefit of having a multitude of additonal profile related properties availabale to your application. i can't overstate enough the benefits in going down this track as i've found it very useful to have such an approach in both my standard asp.net apps as well as my mvc ones.
you can get a feel for what's involved in this by looking thro a couple of these links:
here's one on SO for starters:
Implementing Profile Provider in ASP.NET MVC
and one from my old mate, lee dumond:
http://leedumond.com/blog/asp-net-profiles-in-web-application-projects/
hope this helps
An alternative approach is to alter the forms authentication ticket to add your unique id to the data stored in the cookie. Then, by implementing a custom IPrincipal you can have your unique id available anywhere that the User object is available.
I have a site which has an area that requires authentication. Right now I use the roles attribute on all the controllers in that area, and I run a query to retrieve that users ID, and all their settings.
It seems like a code or design smell to me that I am retrieving the userid and settings each time a controller in that area loads up? I'm not sure if I should be using sessions, or if ASP.Net MVC 2.0 provides some unique way to handle this. Another concern is security.
Overall, I don't really know which way to turn. Design wise I would like the userId and settings retrieved only once when the user logs into the area. Right now I grab the userId each time a controller loads up, and then if required, I query the database for their settings each time as well.
One of the rules about security is that you shouldn't try to do it yourself. There are many pitfalls in doing an authentication system correctly without leaving loopholes or backdoors. Thus, in that regard, you might consider the SqlMembershipProvider that comes with .NET. It can be used with MVC and provides the means to get roles and the current security context, is easy to setup and configure and will be more secure than rolling your own.
If you are not using SQL Server, you have a couple of choices. One solution would be to use something like SQL Server Express or SQL Server Compact Edition to maintain the credentials. Another solution would be to mimic the SqlMembrershipProvider database schema and then write a custom provider that communicates with that schema.
The last choice would be to write a custom MembershipProvider class. While this is still rolling your own, it forces you into the structure of the MembershipProvider so that you can swap it out at a later date for a different one (e.g. ActiveDirectoryMembershipProvider) and provides a common interface for interacting with credentials and logins which for example enables easy use of the built-in Login control.
If you are already using a MembershipProvider and are asking about storing additional user-specific data, then I would suggest the SqlProfileProvider with all the caveats I mentioned above about the SqlMembershipProvider. the ProfileProvider provides a structure for maintain user-specific data with the currently logged on user.
For more information:
Introduction to Membership
Implementing a MembershipProvider
ASP.NET Profile Providers
You could also implement a custom identity. They are very easy to implement, and they let you store whatever user information you want in Identity, which is then stored in the cookies that Identity puts down, so you're not hitting the DB every time to get that info.
Just create a new class that inherits from GenericIdentity, and you'll be on your way.
You of course have to be careful how much info you put there since it's in a cookie, but usually user related information in the case you're talking about here isn't so big.
We use a custom identity to store a few bits of info about the user, and it works out pretty well.
You could store an object in session that holds all the required user information. You will just need to add a property in the Controllers, Views or other base classes where you want to retrieve the user information/profile. This would be the authorisation info as opposed to any authentication info (eg Forms authentication)
You might try "Windows Identity Foundation". I've been using it on one of my projects for a while. It allows for "claims-based authentication", which basically means that you get to designate "claims", strings of information that describe the user when she logs on.
Once logged on, the user's claims can be read from the HttpContext.Current.User field. You can also use "Role" claims that seamlessly integrate with a role-based authentication schema; meaning that you can give the user a "manager" role claim and then use `if (User.IsInRole("manager")).
As an added bonus, WIF makes it very easy to re-use your login screen in other applications.
All in all, it's very flexible, but the documentation is very poor. I've asked and answered a number of questions about "Windows Identity Foundation" on StackOverflow.
We have done this quite a few times in the past. Similar to what Thomas mentions, what we have generally done is implemented a new Membership provider based on the Microsoft SQL Memberhsip provider to do this. We inherit from the base MembershipUser class and add any custom properties we would want to have on the user object. You have to implement a database read for the Membership provider on the GetUser implementation, so you can consolidate your extra properties you need into that database read.
If you are using SQL server, Microsoft has release the 2.0 code for it. You can get more information at Scott Gu's blog.
http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx
If you want to start from scratch, they also have good resources at MSDN.
http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
and
http://msdn.microsoft.com/en-us/library/6tc47t75.aspx
Once you have implemented your provider, you can then add the Membership user to the Items collection of the current web context to get access to it from your code. The non extended properties from the base base user class are also available on the Request thread like normal.
With the Microsoft release of the 2.0 version of the source code , we found it helped us alleviate some concerns that exist about reinventing. Another thing to consider for your implementations is based on your scenario, you can bypass implementing some of the code. An example of this would be the CreateUser code if you are hitting a back end system that already has the credential information.
It seems like you're relatively happy with your authentication process but you want to explore other options for session/settings.
My suggestion has to do with settings only (roles, preferences, etc.)
In my opinion, having to traverse the whole technology stack from UI to Business Tier to DB tier to DB is sometimes a bit overkill.
For data that isn't likely to change during a session, this adds a lot of overhead... There are potentially several data transformations happening (DB (Relational Format) -> ORM -> Web Service XML Serialization -> Web Tier deserialization).
You might consider a session system that doesn't rely on a heavy RDBMS system or on the ASP.NET Caching / Session model. There are options that are very performant and that scale well.
You could use RavenDB by Ayende Rahien (Built for .NET). Its main goal is to provide low latency, high performance access to schema-less JSON documents.
Using this solution, you would set up ravenDB in the web tier so that access to data is very quick.
The first time you authenticate and retrieve settings, you would store the userID and settings information in this session DB.
Every time you load your controller after that, the settings data is accessible without having to go back to the RDBMS.
This DB could also be used to cache other web related data.
As for security, the settings data makes it to the web tier regardless of the method you use. This solution would be no more or less secure than the other options (more secure than an unencrypted cookie). If you needed to, you could encrypt the session data - but that will increase your overhead again.
Just another one of the million options to consider.
Good Luck,
Let us know what you decide!
Patrick.
In my pet project I want to have a user system with the following requirements:
It needs to work with Db4o as a persistance model
I want to use DI (by means of Turbine) to deliver the needed dependencies to my user model
It needs to be easy to plug in to asp.net-mvc
It needs to be testable without much hassle
It needs to support anonymous users much like SO does
I want Authentication and Authorization separated (the first can live without the second)
It needs to be safe
I'm aware I'm putting a few technologies before functionalities here, but as it is a pet project and I want to learn some new stuff I think it is reasonable to include them as requirements.
Halfway in rolling my own I realized I am probably suffering some NIH syndrome.
As I don't really like how needlessly complex the existing user framework in asp.net is, it is actually mostly only all the more complicated stuff regarding security that's now giving me some doubts.
Would it be defendable to go on and roll my own? If not how would you go about fulfilling all the above requirements with the existing IPrinciple based framework?
It sounds to me like what you want to do is roll your own Custom .NET Membership Provider.
It will allow you to use the built-in ASP.NET Authentication/Authorization attributes on your Controller Actions while giving you complete control over the implementation inside the provider (which will allow you to code it to meet the requirements stated above).
Direct from MSDN...
Implementing a Membership Provider
I think you recognize where the thin parts in your consideration are: namely in that you've included how to do what you're doing as motive in why you're doing it and the NIH (funny: I'd never seen that before) issue.
Putting those aside, your provider is something that you could potentially reuse and it may simplify some of your future efforts. It should also serve to familiarize you further with the issue. As long as you understand the ASP.NET framework so you can work with it too if you need to (and aren't specialized such that you don't know what you're doing if you're not using your tool) then I believe you've already crafted your defense.
As DOK mentioned, be cautious that you're not rolling your own here to avoid a larger task at hand in whatever your other functionality is. Don't let this be a distraction: it should be something your application really needs. If it's not, then I'd lean towards focusing on your software's core mission instead.
If you go ahead and create your own custom solution, you will have a better idea of how difficult it is and what features you want. This will help you to evaluate off-the-shelf solutions for future projects.
OTOH, spending time developing functionality that is already readily available means you won't be spending that time working on the major functionality of your project. Unless authentication and authorization are a major component of your project, you might consider investing your time, and expanding your knowledge, in another area.
I too am working on a pet Project using ASP.net MVC and db4o and did the same thing, so you're at least not alone in going down that route :). One of the biggest reasons for me to start playing around with db4o as persistence layer is that especially authorization on field level (i.e I'm allowed to see Person A's first name but not Person B's first name) is though to achieve if you're forced into complex SQL statements and an anemic domain model.
Since I had complex authorization needs that needed to be persisted (and synchronized) in both db4o and Solr indexes I started working on rolling out my own, but only because I knew up front it was one of the key features of my pet project that I wanted 100% control over.
Now I might still use the .Net Membership provider for authentication but not (solely) for authorization of objects but only after i POC'd my authorization needs using my own.
As a relative newcomer to both web and MVC, I am looking for a good summary of security best practices that I should implement.
The site will be public facing with "moderately sensitive data" (meaning we can't get sued, but probably wouldn't make many friends if the data got out!) and will have the following security steps taken:
a: Forms/membership authentication and authorization
b: Parameterized queries to prevent sql injection.
c: Automatic timeout with x min of inactivity
c: SSL for client to server encryption
What else do you recommend?
*Securing IIS and the network don't fall under my domain, so I'm more interested in the things I need to do to the software.
If you are using cookies to recognize users, be sure to use an arbitrary token (such as a GUID) to store on the client for identification. I've seen too many websites that store my email address or username in my cookie... just have to change it to another!
Write your software so that it can run under medium trust.
If you are new to web development you should be aware of cross site scripting (XSS). You can use Http.Encode helper method to protect against this in ASP.NET MVC.
Make sure you prevent out of order requests. Ensure client is authenticated before allowing to see sensitive data, or in some cases, make sure the client has come through the correct channel, before allowing a data manipulation. For example, only allow adding an item to your cart if the request came from the product details page. If you don't check, any one can mess around with the action. The URL would be like http://server/cart/add/XYZ123 and anyone could just tweak the 'id' parameter.
Here's another biggie to watch out for: CSRF
http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
Take a look at this post by Phil Haack- one of the MS dev’s involved in the development.
Additionally take a look at Microsoft Anti-Cross Site Scripting Library to filter out all incoming parameters
Maybe you should choose methods that can be invoke from outside or not. For example be careful make a method like delete any tables like http://yourhost.com/edit/deletealltable.
Make sure you design your class and methods well. And give attributes [NonAction] for preventing public method being invoke.
Make sure you display data (especially sensitive) as you need with minimum fancy design and use client script as long as needed.
Remove any unused trash files like unused files in your solution folder.
Check and double check and validate any input control like textbox. I just can give something in the textbox to hack your system.
If you use mix between MVC and regular ASP.NET, please remove any dependency between them.
Be sure you cover the basics thoroughly, independently of ASP.NET. Make sure your DBMS has a separate user with the minimal required privileges (e.g., CRUD and executing sprocs from specified databases) set up to access the database from the web application. Parameterizing queries is an excellent idea, but ALWAYS SCRUB YOUR INPUT ANYWAY: it is not a complete defense against sql injection.
Keep your design clean and easy to understand. Document whatever you do clearly, especially on the database side. It would be very bad if all your good work were destroyed by two programmers months or years later--one who didn't realize, say, that the database user for the web application (now accessing a database on a different server) shouldn't have root privileges, and another who added a control that didn't cleanse input properly. There's only so much that can be done about this sort of thing, but designing for the possibility that fools will be maintaining your code isn't so that coders will think you're sweet--it's so that fools won't put you out of business.