Membership/Role/Profile providers API appeared in early days of asp.net
Nearly everytime I can't live with standard API & have to add some extra functionality (for sorting, retrieving e.t.c.). I also have to use different database structure often (with foreign key to some tables for example) or think about performance improvements.
These considerations forced teams I took part in to build own providers but I can't stand to implement providers API (because we don't use 70% of standard functionality at least). Moreover, providers that were built for exact projects were rarely reused.
I wonder if someone found swiss-knife early-days-API providers implementation that is usefull for any kind of project without refactoring...
Or do you use your own implementations of early-days-API's
Or may be you abandon standard architecture and use lightweight implementations ?
Thank you in advance
I too have found that oftentimes I don't need all the functionality exposed in the standard MembershipProvider bases. These days, I tend to write my own lightweight methods for authenticating and authorising users.
I typically follow these as a rough guide:
Set authentication mode to Forms in web.config
Custom class to authenticate a user and retrieve roles for associated UserId
Login form to manually issue FormsAuthenticationCookie (see example below)
Configure web.config elements in subdirectories to prohibit access to roles
The following is an example of code you can use to create the FormsAuthenticationTicket yourself, using your own lightweight methods to authenticate and authorise your users:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
data.AccountId.ToString(),
DateTime.Now,
DateTime.Now.AddHours(24),
rememberMe,
data.ToString());
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
if (rememberMe)
cookie.Expires = DateTime.Now.AddDays(30);
HttpContext.Current.Response.Cookies.Add(cookie);
This is just a rough idea but remember it's entirely up to you whether you use the MembershipProviders as is, whether you implement your own, or whether you choose to ditch them altogether and build your own, providing just the functionality you require. I often choose the latter, simply because a lot of the applications I write are upgrades from legacy systems which already have membership databases in place etc.
Hope this helps.
Related
I use .net membership but everything what i work i want to be custom.
What i want to do is:
Create custom data table [Users] with custom fields
Import current data into new table
Create custom classes and functions about everything what i need for [Users]
I`m not sure how .net membership works, but maybe it send encrypted cookie then when i use
var user = Membership.GetUser();
.Net decrypt user cookie and know which user is.
Here is a screenshot how .net create user AUTH cookie http://prntscr.com/97043
But everytime user logout-login, this value is different.
So what i want to know is:
Lets say i want to make 100% custom website, how i can make custom login?
Can you tell me all security issues about going for custom membership?
None of this is necessary. You can create your own users table without the need to alter anything related to Membership or authentication. You just make sure that your users table has a column called AspNetUserID or similar of type uniqueidentifier (a guid) . You put the ProviderUserKey from the MembershipUser in this table and lookup any user in your Users table simply by getting the ProviderUserKey from Membership.
So, for example, you might do this:
var userid = Membership.GetUser().ProviderUserKey;
// lookup your record in users based on userid above
Implementing a custom backend isn't difficult. You simply implement a custom MembershipProvider that stores and retrieves the data from your users table as you see fit. see MSDN. Also, you don't have to entirely rewrite SqlMembershipProvider, you can subclass it and add the functionality you're looking for.
If you really want to start from scratch on the backend, here are some issues to note:
Don't store passwords in plaintext anywhere; hash them.
Salt your passwords
Log & monitor password resets
Also, you don't have to entirely rewrite SqlMembershipProvider, you can subclass it and add the functionality you're looking for, and most of the issues you might run into will be covered by the default implementation. You'd probably just have slightly modify the data access calls or stored procedures to map to your table structure. You can also subclass the SqlRoleProvider to provide role-based authorization for your site with little additional effort.
As for the front-end component, MSDN also describes how forms authentication works, but personally, I wouldn't mess with your own cookie scheme. Even big custom implementations like Oauth for asp.net still use forms. Check out http://msdn.microsoft.com/en-us/library/system.web.security.sqlroleprovider.aspx
I'm creating my first ASP.NET MVC site and have been trying to follow domain driven development. My site is a project collaboration site where users can be assigned to one or more projects on the site. Tasks are then added to projects, and users with in a project can be assigned to tasks. So a "User" is a fundamental concept of my domain model.
My plan is to have a "User" model object which contains all the information about a user and can be accessed through an IUserRepository. Each user can be identified by a UserId. Although I'm not sure at this point if I want the UserId to be a string or integer.
How should my domain objects User and IUserRepository relate to the more administrative functions of my site like authorizing users and allowing them to login? How would I integrate my domain model with other aspects of ASP.NET such as HttpContext.User, HttpContext.Profile, a custom MemberShipProvider, a custom ProfileProvider, or custom AuthorizeAttribute?
Should I create a custom MembershipProvider and or ProfileProvider which wraps my IUserRepository? Although, I can also foresee why I may want to separate the User information in my domain model from the authorization of a user on my site. For example in the future I may want to switch to windows authentication from forms authentication.
Would it be better to not try and reinvent the wheel and stick with the standard SqlMembershipProvider built into ASP.NET? Each user's profile information would be stored in the domain model (User/IUserRepository), but this would not include their password. I would then use the standard ASP.NET membership stuff to handle creating and authorizing users? So there would need to be some code somewhere that would know to create a profile for a new users in the IUserRepository when their account is created or the first time they login.
Yes - very good question. Like #Andrew Cooper, our team also went through all this.
We went with the following approaches (right or wrong):
Custom Membership Provider
Neither I or the other developer are fans of the built in ASP.NET Membership provider. It's way too bloated for what our site is about (simple, UGC-driven social website). We created a very simple one that does what our application needs, and nothing more. Whereas the built-in membership provider does everything you might need, but most likely won't.
Custom Forms Authentication Ticket/Authentication
Everything in our application uses interface-driven dependency injection (StructureMap). This includes Forms Authentication. We created a very thin interface:
public interface IAuthenticationService
{
void SignIn(User user, HttpResponseBase httpResponseBase);
void SignOut();
}
This simple interface allows easy mocking/testing. With the implementation, we create a custom forms authentication ticket containing: things like the UserId and the Roles, which are required on every HTTP request, do not frequently change and therefore should not be fetched on every request.
We then use an action filter to decrypt the forms authentication ticket (including the roles) and stick it in the HttpContext.Current.User.Identity (for which our Principal object is also interface-based).
Use of [Authorize] and [AdminOnly]
We can still make use of the authorization attributes in MVC. And we also created one for each role. [AdminOnly] simply checks the role for the current user, and throws a 401 (forbidden).
Simple, single table for User, simple POCO
All user information is stored in a single table (with the exception of "optional" user info, such as profile interests). This is mapped to a simple POCO (Entity Framework), which also has domain-logic built into the object.
User Repository/Service
Simple User Repository that is domain-specific. Things like changing password, updating profile, retrieving users, etc. The repository calls into domain logic on the User object i mentioned above. The service is a thin wrapper on top of the repository, which seperates single repository methods (e.g Find) into more specialized ones (FindById, FindByNickname).
Domain seperated from security
Our "domain" the User and his/her's association information. This includes name, profile, facebook/social integration, etc.
Things like "Login", "Logout" are dealing with authentication and things like "User.IsInRole" deals with authorization and therefore do not belong in the domain.
So our controllers work with both the IAuthenticationService and the IUserService.
Creating a profile is a perfect example of domain logic, that is mixed with authentication logic also.
Here's what our's looks like:
[HttpPost]
[ActionName("Signup")]
public ActionResult Signup(SignupViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Map to Domain Model.
var user = Mapper.Map<SignupViewModel, Core.Entities.Users.User>(model);
// Create salt and hash password.
user.Password = _authenticationService.SaltAndHashPassword();
// Signup User.
_userService.Save(user);
// Save Changes.
_unitOfWork.Commit();
// Forms Authenticate this user.
_authenticationService.SignIn(user, Response);
// Redirect to homepage.
return RedirectToAction("Index", "Home", new { area = "" });
}
catch (Exception exception)
{
ModelState.AddModelError("SignupError", "Sorry, an error occured during Signup. Please try again later.");
_loggingService.Error(exception);
}
}
return View(model);
}
Summary
The above has worked well for us. I love having a simple User table, and not that bloated madness that is the ASP.NET Membership provider. It's simple and represents our domain, not ASP.NET's representation of it.
That being said, as i said we have a simple website. If you're working on a banking website then i would be careful about re-inventing the wheel.
My advice to use is create your domain/model first, before you even think about authentication. (of course, this is what DDD is all about).
Then work out your security requirements and choose an authentication provider (off the shelf, or custom) appropriately.
Do not let ASP.NET dictate how your domain should be designed. This is the trap most people fall into (including me, on a previous project).
Good luck!
Let me break down your collection of questions a bit:
Although I'm not sure at this point if I want the UserId to be a string or integer.
It doesn't have to be an integer per say, but definitely use some kind of bit based value here (e.g. int, long or guid). An index operating over a fixed size value is much faster than an index over a string, and in your life time, you will never run out of identifiers for your users.
How should my domain objects User and IUserRepository relate to the more administrative functions of my site like authorizing users and allowing them to login?
Decide if you want to use the built in asp.net membership or not. I recommend not for the reason that it's mostly just bloat and you have to implement most of the features of it yourself anyway, like email verification, which you'd think from looking at the tables generated it would be built in... The template project for ASP.NET MVC 1 and 2 both include a simple membership repository, just rewrite the functions that actually validate the user and you'll be well on your way.
How would I integrate my domain model with other aspects of ASP.NET such as HttpContext.User, HttpContext.Profile, a custom MemberShipProvider, a custom ProfileProvider, or custom AuthorizeAttribute?
Each one of these is worthy of it's own SO question, and each has been asked here before. That being said, HttpContext.User is only useful if you are using the built in FormsAuthentication functionality and I recommend using it in the beginning until you encounter a situation where it is does not do what you want. I like storing the user key in the name when signing in with FormsAuthentication and loading a request bound current user object at the beginning of every request if HttpContext.User.IsAuthenticated is true.
As for the profile, I avoid stateful requests with a passion, and have never used it before, so someone else will have to help you with that one.
All you need to use the built in [Authorize] attribute is to tell FormsAuthentication the user is valdiated. If you want to use the roles feature of the authorize attribute, write your own RoleProvider and it will work like magic. You can find plenty of examples for that on Stack Overflow. HACK: You only have to implement RoleProvider.GetAllRoles(), RoleProvider.GetRolesForUser(string username), and RoleProvider.IsUserInRole(string username, string roleName) in order to have it work. You do not have to implement the entire interface unless you wish to use all of the functionality of the asp.net membership system.
Would it be better to not try and reinvent the wheel and stick with the standard SqlMembershipProvider built into ASP.NET?
The pragmatic answer for every derivation of this question is to not reinvent the wheel until the wheel doesn't do what you need it to do, how you need it to do it.
if (built in stuff works fine) {
use the built in stuff;
} else {
write your own;
}
if (easier to write your own then figure out how to use another tool) {
write your own;
} else {
use another tool;
}
if (need feature not in the system) {
if (time to extend existing api < time to do it yourself) {
extend api;
} else {
do it yourself;
}
}
I know my answer comes a little bit late, but for future references to other colleagues having the same question.
Here is an example of Custom Authentication and Authorization using Roles as well.
http://www.codeproject.com/Articles/408306/Understanding-and-Implementing-ASP-NET-Custom-Form. It's a very good article, very fresh and recent.
In my opinion, you should have this implementation as part of the infrastructure (Just create a new project Security or whatever you want to call it) and implement this example above there. Then call this mechanism from your Application Layer. Remember that the Application layer controls and orchestrate the whole operation in your application. Domain layer should be concern exclusively about business operations, not about access or data persistence, etc.. It's ignorant on how you authenticate people in your system.
Think of a brick and mortar company. The fingerprint access system implemented has nothing to do with this company's operations, but still, it's part of the infrastructure (building). As a matter of fact, it controls who have access to the company, so they can do their respective duties. You don't have two employees, one to scan his fingerprint so the other can walk in and do its job. You have only an Employee with an index finger. For "access" all you need is his finger... So, your repository, if you are going to use the same UserRepository for authentication, should contain a method for authentication. If you decided to use an AccessService instead (this is an application service, not a domain one), you need to include UserRepository so you access that user data, get his finger information (username and password) and compares it with whatever is coming from the form (finger scan). Did I explain myself right?
Most of DDD's situations apply to real life's situations... when it comes to architecture of the software.
Background:
I'm incorporating the SqlMembership provider into an existing system where I'm building a web front end. The Membership database will be kept in a separate database.
Beyond the login account, there's an additional mapping between the accounts that needs to be in place in the main database in order for an account to be able to log in.
Let's say that this table gives the user the right to use the system.
My question:
I would like to somehow incorporate this into the provider. Is it possible without too much work? (Or is it better to keep it in the AccountMembershipService class?)
Actually regardless, I'm very interested in learning how to put additional login requirements into the provider.
I'm asking this because when I've been looking at creating a custom membership provider earlier it seemed at that time a little bit overwhelming.
In other words:
I want to understand how to extend the Membership Provider classes in general and how to extend the login method (ValidateUser) in particular.
Given the sample ODBC implementation It looks like one simply could subclass the default provider and override ValidateUser calling base.ValidateUser as the first step.
However it may or may not be that simple, and I'd be very happy to hear any first hand experiences from implementing or extending membership providers.
I wanted to do something similar, one of the requirements was to use an Oracle DB, so I implemented the OracleMembership provider, hence I could not waste my time rewriting the hole oracle membership provider (it works pretty fine), the second requirement was to use a custom authorization legacy system. So I realized that the Internet Application template which comes with the MVC 2 or 3 comes with a small implementation of the security for the site, specifically take a look on the AccountMembershipService class. You could move all of these elements out of the MVC app to a separate assembly so you could use it even on a client implementation. The AccountMembershipService uses the Membership provider as the underlying authentication system with the option of using FormsAuthentication.
So I recommend you to take a look on that implementation. You could put your additional authentication code there so your application would stay cleaner and your don't need to re-invent the wheel and you have the chance to add your own code.
best regards
In order to extend the membership provider make you own tables with one to one relationship with the main database and handle additional requirements through this table. Also while implementing and extending the default membership provider you may need to store extra information in authcookies you may get additional information from here , here and here
In GetUserCredentials you will do your stuff for additional checking and RoleID is some dropdown on your login page that you will receive in the post method of sign in.
FormsAuth.SignIn(userName, rememberMe);
ApplicationRepository _ApplicationRepository = new ApplicationRepository();
MembershipUser aspUser = Membership.GetUser(userName);
SessionUser CurrentUser = _ApplicationRepository.GetUserCredentials(aspUser.ProviderUserKey.ToString(), RoleID);
if (CurrentUser == null)
{
ModelState.AddModelError("_FORM", "Invalid Role ");
FormsAuth.SignOut();
return View("signin");
}
In a website, I need to integrate membership and authentication. So I want to use the functionality of ASP.NET Membership, but I have other custom stuff, that a "user" has to do.
So I am sitting here with my pencil and paper, drawing lines for my domain model... And how can I best utilize the ASP.Net membership, but extend it to fill my needs?
Should I create a class that inherits from a MembershipUser and extend it with my own properties and methods (and save this in a seperate table). Or should I let the MembershipUser be a property on my custom User/Client object?
What would be a good solid way to do this?
I've thought about it and there are 2 ways that seem appropriate (of course there are more ways to make it work).
Custom Membership Provider
You change the membership provider to use your own and use your User object to store all the information.
The problem with this one is that it involves a lot of re-implementation of things that are already well handled by Asp.Net. The good thing is that you have a single User object with all the details.
Link from a Membership User to your User
With this method, you would use the original Membership provider to handle the user name and password, but you link your own User object with this one with something like the user name by using a service for example.
It's really easy to set up, you just need to create a service that would be used like this:
string userName = "Jon Skeet";
User user = new UserManagementServices().GetUserByUserName(userName);
I ended up writing my own membership-provider, and have implemented that in 3 separate solutions now. It is extremely simple and much, much more elegant than linking a user to a membershipUser (which I have also tried).
Read this...:
Create Custom Membership Provider for ASP.NET Website Security
And if you want to learn more, watch this video (with sourcecode).
I've extended MembershipUser and created my own version of the SqlMembershipProvider to map to my existing domain, and its working well, in production now.
MembershipUser is essentially a view over my User table. My extended MembershipUser class includes profile/account-style properties instead of using the default SqlProfileProvider system, which is a bit fragile.
I wasn't able to use the existing membership tables or sprocs, but wrote my own. For example, the SqlMembershipProvider uses a GUID as an opaque key, but the production system uses a plain old int. All of the dates are UTC, etc. too.
All of the extra User functionality is accessed via the User domain not via Membership methods.
HTH.
I'm currently working through the Microsoft ASP.NET 2.0 Membership API Extended article from CoDe Magazine which explains how to extend the membership API by writing a wrapper around the existing classes. Main benefit is that you can keep all the out of the box functionality and not have to rewrite your own as you would when implementing a custom provider. Source code is provided.
I want to make a login system using ASP.NET (MVC).
On the internet, I found some bad examples that involved SQL in Click events. Other information pointed to the ASP.NET built-in membership provider.
However, I want to roll my own. I don't want to use the built-in membership provider, as it only seems to work on MS SQL, and I don't like the idea of having a few foreign tables in my database.
I could probably think of something, but I need a few pointers in the right direction. It does not have to be high-security, but just regular common-sense security.
And I have a few direct questions:
A lot of systems seem to have the Session ID stored in a user table. I guess this is to tie a session to a user to prevent hijacking. Do check this every time a user enters a page? And what do I do if the session expires?
Hashing, salting, what does it do? I know of MD5 hashing and I have used it before. But not salting.
Best practices for cookies?
I dont know about best practices but I can tell you what I do. Its not hitech security but it does the job.
I use forms authentication. I receive the password secured with ssl via a textbox on the login page. I take that password and hash it. (Hashing is like one way encryption, you can get hash code that cant be reversed back to the password). I take that hash and compare it to the users hash in the database. If the hash's match i use asp.nets built in authentication handling, which handles cookies for me.
The FormsAuthentication class has methods available to do this fo you, such as SetAuthCookie and RedirectFromLogin. they will set the cookie and mark them as authenticated. The cookie asp.net uses is encrypted. I cant speak for its security level though, but its in fairly common use.
In my class i do the password check and use formsauth to handle the rest:
if(SecurityHelper.LoginUser(txtUsername.Text, txtPassword.Text))
{
FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, true);
}
You can implement your own membership provider using the ASP.NET infrastructure, see MSDN docs for MemberShipProvider class.
The built in provider works well. It does actually work with MySQL, although I found it not to be as straight forward as the MS SQL version. If you can use then do, it'll save you hours of work.
If you need to use another data store then I concur with axel_c, if I was going to roll my own then I'd write a membership provider as per MS specification. It will make the code more maintainable for any developers following you.
Salting is the practice of adding a unqiue string of characters to whatever is being hashed. Suppose mySalt = abc123 and my password is passwd. In PHP, I would use hashResult = md5(mySalt + password).
Suppose the string is intercepted. You try to match the string, but you end up matching gibberish because the password was salted before encrypted. Just remember that whatever you use for salt must be continuous throughout the application. If you salt the password before storage, you must compare the hashed, salted password to the DB.
You can use the built in SQL membership provider - and you could set up a dedicated "user access" database if you don't want the .Net membership tables within your database - just specify that in the connection string.
THe advantage with the provider model is at the application level, the code is independent of what particular authentication store you have used.
There are a good series of tutirials on the asp.net site:
link text
A disadvantage of the Membership Provider by microsoft is that you can't use it in a domain driven approach. If you want to, you can create your own user object with your own password hash and still use the authentication cookies provided by Microsoft. Using these authentication cookies means that you don't have to manage the session IDs yourself.
public void SignIn(User user)
{
FormsAuthentication.SignOut();
var ticket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now.AddMinutes(30), expires, alse, null);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
Expires = ticket.Expiration
};
httpContextProvider.GetCurrentHttpContext().Response.Cookies.Add(authCookie);
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
I use my own user object and tables.
I store my passwords hashed in the usertable with a unique salt per user.
This is secure, easy to implement and it will fit in your design.
Your database table won't be polluted by Microsofts membership provider crap.
I would avoid the whole issue and use openid. There is a library available that you can use directly.
Here is a link to a blog post about putting this in place