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!
Related
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 :)
Yes hashing is better but...
So I knew I would regret this but here we go. I started a new project and decided I would use the built-in Microsoft membership stuff in MVC 4 (BasicMembership) so that I didn't have to write the registration, login, oauth, etc...
Now I want to modify some of this behavior and use as much best practice as possible. This came about because I decided I would need to associate multiple users under 1 parent (company) - I know I can do all of the work in the controller and still accomplish this, but that is not my desire.
Here is my problem/desire:
1.) I want to create the entries in SQL tables UserProfile/WebPages_Membership myself. I want to do this in my repository and I don't want it to be coupled to ASP.NET. The problem is that MVC is encrypting the password via IMembershipAdapter that I do not have access to. How can I use the same encryption key to encrypt the data so that I can accomplish #2?
2.) I dont want to re-invent the wheel entirely so I would still like to use some of the features such as:
WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe)
3.) I don't want my business logic in the controller! While I am working at the repo level, all of the orchestration will take place in the business tier.
Thanks for taking the time to read my post :-)
First of all did you look at: ASP.NET MembershipProvider -- How exactly does it do encryption?
Second thig maybe use something already done like: CodeFirst Membership Provider it allows you to create own tables using EF code first.
Okay, i know there have been some questions about this before, but I just want to know what the situation is now. If I am creating an ASP.NET MVC web app, should I use the built in Membership Provider or roll my own?
I feel that the existing one is perhaps overkill, but then again, it has been tested to death and works very well. I don't like the millions of table and sprocs it puts in the database, but should I just delete the stuff I don't need, or just not worry about it and use it anyway?
Whilst you say this is a possible duplicate, I think it's fair enough to seek clarification on the current situation and you do seem to have considered the possibilities.
I still tend to use the built-in membership provider for the reasons you've stated (it just works) and then add my own tables for things like OpenId, Facebook, etc, etc and tie them back to user ids in the aspnet_Users table.
Thus far I tend not to worry about the extraneous stuff it puts in the database.
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 know what are you saying already (baad idea), but please read first :)
I am developing ASP.NET MVC based app, which will require some specific features:
combination of "local" users and facebook connect login, but FB users will be "mirrored" to some kind of local representation, because there will be some statistics and other stuff needed to keep for both types
authorization will be 3-layered instead of asp.net standard 2 layers. By this i mean : User is in Group (m:n) and Group is in Role (m:n), instead of User is in role (m:n).
So, if i would want to use standard authentication/authhorization approach, i would have to:
implement custom Membership provider, and it wont be even "right", because it will utilize methods like AddUserToGroup and AssignRoleForGroup etc.
implement custom Principal/Identity for sake of accessing my own User objects
casting HttpContext.User to my object every time needed...
implement custom Role provider
custom mechanism of sessting AuthCookie (unique userId in userdata, cant rely on username with third-party FB users in system)
... (you surely can think of something else)
Well, i really dont like the idea of "bending" and replacing every part to get pretty messy solution in the end. So I think of implementing my own mechanism encapsulated in one place - lets call it AuthService.
AuthService will be thread-safe singleton
Instead of AuthCookie will be using standard Session object (i know sessions also use cookies, but i really dont see advantage of low-level storage (cookie) over session)
AuthService will provide AuthService.CurrentUser (of my own type), populated from session on beginning of every request (Application_AuthenticateRequest, I think)
AuthService will provide in one place all methods - ValidateUser, RolesForUser, IsInRole, Logout, etc.
So now.. why should I not do this this way ? :)
I think session is equally secure to AuthCookie (same risks for ticket and authcookie)..
I dont really look for "modularity" (plug-and-play role providers, membership providers, profile providers..) - I deal here with pretty specific stuff, I dont expect standard components to fit.. have "my approach" any other disadvantages ?
Thanks for all good ideas and sorry my terrible english, I am from non-english-speaking country :)
R.
I can certainly see why you don't want to implement an entire Membership provider. However, I would take advantage of the low-level support offered by Forms Authentication (e.g. the cookie, expiration etc.) and just do my own custom authentication. If you do this, you can inject your own custom user class into the HTTP context and use it throughout your code. Your custom user object would implement IIdentity and IPrincipal. Your IPrincipal.IsInRole would work against your custom authentication scheme. This would allow your higher level code to use standard .NET framework permissions stuff. This is the neatest, simplest way to accomplish what you want while taking advantage of what already exists.