SimpleMembership with an existing database.

I’ve been trying the SimpleMembership today and I just love it, the Asp.Net team came out with the simplest solution, great!

Managing users and their rights has always been a pain using the built in Membership feature pushing many developer to write their custom user/role tables, spending a lot of time in configuration and extending the various MembershipProvider and RoleProvider, as I did. SimpleMembership addresses that, but let’s start from the beginning, it will be quick don’t worry!

Authorization vs Authentication

The Asp.Net membership provides a  built in solution to manage authentication and authorization. While the Authentication defines the mechanism used to assign an identity (and eventually one or more roles) to a user, the authorization simply defines what an user or a role can access. The definition is obvious but necessary, because one of the main criticism is that in order to get even a basic authentication in place  there’s a lot of  setup code, including  functionality that will be hardly used. So basically in order to get to this:

if(User.Identity.IsAuthenticated && User.IsInRole("Administrator"))
{
 //do something
}

You need this (see picture below) and yes, it comes with a lot of lovely keys required in the web.config. It’s a bit too much for getting to the point to where I can safely assign a forms authentication ticket (ASPXAUTH cookie) to my user.Details on how to create the database can be found here.

membership schema

Universal Providers

Things improved with the recent introduction of the Universal Providers. Enabling support for all the SQL Server family, including azure, they can be easily integrated with the new DotNetOpenAuth providers and give back a cleaner database (picture below).  The main bits however remains the same: config keys needed for roles/profiles/membership, which is fine if you want to tune the default behaviour!

SimpleMembership

And what if instead you’re happy with that default behaviour and you want to get immediately productive, skipping all the configuration part ? SimpleMembership is the answer.

A new security provider actually hosted in the WebMatrix.WebData.dll and added by default within the Website template in Visual Studio, reducing to the essential both the SQL dependencies and the code to implement to get it working.  John Galloway gives a great overview of the SimpleMembership class in his post, describing how it inherit from ExtendedMembershipProvider, which extends the classic MembershipProvider.

All this goodness is accessed within webpages/controllers through the static WebSecurity class, which embeds all the authentication features usually needed, including the FormsAutentication SignIn/SignOut. For instance with a call to WebSecurity.Login a user get both validated and receive the authentication cookie I was talking about previously.All without one line of config. That’s awesome.
websecurityclass login

The database produced is really tiny and the required tables can be easily included within an existing one, using EFCode first for instance.

How does it works ? The SimpleMembership in order to work with your existing user table need a UserId and a UserName columns.  These values will then been used internally by the provider to hook up with the other membership tables containing the remaining bits that compose the full user profile. You can add the columns to any table as long it is decorated with the UserProfile attribute.

[Table("UserProfile")]
public class UserProfile
{
 [Key]
 [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
 public int UserId { get; set; }
 public string UserName { get; set; }
 public string Email { get; set; }
}

That’s it. UserProfile can be any of the tables of my current EFContext, just comment out the default connection string for the application services database on the web.config and use the DataContext one when initialiting the Membership. By default. with the MVC project, the membership get initialized within the AccountController with the [InitializeSimpleMembership] attribute, let’s comment it out and move the WebSecurity.InitializeDatabaseConnection  call in the global.asax.

protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();
 WebApiConfig.Register(GlobalConfiguration.Configuration);
 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
 RouteConfig.RegisterRoutes(RouteTable.Routes);
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 AuthConfig.RegisterAuth();

//initialiting the database
 Database.SetInitializer(new DataContextInitializer());
 DataContext c = new DataContext();
 c.Database.Initialize(true);
 //DefaultConnection is used by the EF Context too.
 WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName",
 autoCreateTables: false);
}

Now that all is place, an example of why WebSecurity make it easy is the method CreateUserAndAccount. The result is the creation of a user record for our entity table plus its membership account. Note that the Email field is a custom column and it can be easily passed with an anonymous type to the method.

WebSecurity.CreateUserAndAccount("xyzUser", "xyzPassword", new { Email = "xyzUser@mail.com" }, false);

simplemembershiprecord

That’s basically all it takes to get started with the SimpleMembership. Despite a lack of documentation here are some useful links:

Most of the answers can also be found by simply investigating the WebMatrix.WebData assembly with ILSpy !




2 Comments

Do you have any info about upgrading to the SimpleMembership, if my user account already have a password?

I can see how to initialise the SimpleMembership with a existing db but no one ever talks about what happens with existing passwords.

Hope you can help this is casing me a major headache.

Leave a Reply

Your email address will not be published. Required fields are marked *