Membership with Windows Accounts...


By: Brian Mains Spacer Date: April 25, 2006Spacer Download Spacer Download the code. Spacer Spacer Printer Friendly Version

The membership provider works really well for intranet and internet applications in how it validates the user and manages roles. But I've personally had a need to be able to use windows accounts that have been assigned application roles, as I don't have access to the domain and can't create windows roles to assign to all of my users. There is a way to get the best of both of these, through some programmatic work. I won't go into an overview of the Membership and Role providers; instead, I'm assuming you understand how these work.

In an intranet environment where you are using windows authentication, you can get the user ID through the Page's User property, as such: Page.User.Identity.Name. This contains the user name plus domain for the currently logged on user, and not the ASP.NET account. Using this, it is possible to interact with the Membership provider, because this name should be unique for each user. The methods we will use are these:

Membership.CreateUser(string username, string password)
Membership.CreateUser(string username, string password, string email)
Membership.CreateUser(string username, string password, string email, string passwordquestion, string passwordanswer, bool isactivated, out MembershipCreateStatus status)
Membership.GetUser(string username)
Roles.AddUserToRole(string username, string roleName)

To make it easier, the code I used uses a custom page class, which inherits from System.Web.UI.Page. When the user first enters the page (the initial page load), the membership provider gets the reference to the user. If the user doesn't exist, it creates a new MembershipUser with the user’s properties, and by default grants permission to the Users role (this example also has a Power Users and Administrators role). The code shown below is defined in the Page.OnPreLoad method, at the PreLoad stage of the page lifecycle.

//Get the current user from the windows authentication

_user =Membership.GetUser(User.Identity.Name);

//If no user returned, then create a new user

if (_user == null)

{

      MembershipCreateStatusstatus;

      //Use the user name for the password; not going to be a problem because they don't use it

        _user = Membership.CreateUser(User.Identity.Name, User.Identity.Name, "b@a.com", "q", "a", true, outstatus);

 

      //If the status is not a success, as set by the reference variable

      if (status != MembershipCreateStatus.Success)

            throw new Exception("The creation failed due to the following status: " + status.ToString());

  

      //Add user to the generic role

      Roles.AddUserToRole(User.Identity.Name, "Users");

}

The code is pretty straightforward; on the initial page load (when page ispostback property is false), the user object is retrieved. If, after retrieving the user, the object is null, then the user is created, with a dummy email address, password question, and answer. In the windows world, this information isn’t needed anyway; as an alternative I could setup the membership provider information in the web.config, which would disable the need for it anyway; however, I did it this way for ease of use and to show you the longer CreateUser method, which has a status variable. The status variable is an enumeration returned back to the caller with the status of the account creation. If it failed, it will let you know why it failed, which can be used to give a specific reason to the user.

The user will be added to the Users role by default, which I initially setup the roles using the Web Application Administration tool that comes free with Visual Web Developer and Visual Studio 2005. The nice feature about this setup is that all users that are created programmatically can be assigned to specific roles through this tool as well. Opening up the project, selecting the security tab, and selecting Create or Manage Roles, you see the following three roles I created.

Admin Tool 1

Clicking on the power users Manage link, you go to the screen where you can select the user. I brought up the users on my account, and by checking/unchecking the boxes, you can add/remove that user from the roles.

Admin Tool 2

From this, it would be easy to create administrative pages to remove users and have other functionality. But as you can see, it is easy to implement a membership feature, using windows accounts with application roles, with a little extra work. The downside to this is that the user information is retrieved from the database each time. As an alternative, the user information could be stored in the cache, and in the property, when the application accesses the property, some other mechanism returns it; however, I'm using the database in this example.

//Accessible in any page that inherits this class

publicMembershipUser MembershipUser

{

      get

      {

            //Could be replaced with cache or other alternative

            if (_user == null)

                  _user = Membership.GetUser(User.Identity.Name);

            return _user;

      }

}

 

 

The page I attached to illustrate the example simply prints the user name, and the roles they belong to. It retrieves the information from the database and writes it out directly, so you can see what is being output. It also uses our new page variable to do this.

protectedvoid Page_Load(object sender, EventArgs e)

{

      string name = this.MembershipUser.UserName;

      this.lblMessage.Text = "User ID:  " + name + "<br>Roles: ";

  

     foreach (string role inRoles.GetRolesForUser(name))

            this.lblMessage.Text += role + "<br>";

}

 

Switching roles for the user, you can then see the changes taking effect by refreshing or reloading the page. And, with this custom page class, you can still access the original user information through the User property. It's not very difficult at all to reuse the existing membership framework for alternative purposes.