March 23, 2012

SharePoint: Migrate from ActiveDirectoryMembershipProvider to SqlMembershipProvider

Task

In a SharePoint 2010 farm that was currently using Forms Based Authentication (FBA) towards Active Directory, there was a need to migrate users from Active Directory into SQL Server database. This needed to be done without having to modify user permissions on existing SharePoint sites, lists and items.

This migration needed also to be done without users noticing anything. What we specifically didn’t want to do was to create new user identities in SQL DB for all users, and send new passwords to all users via email. This would’ve technically worked just fine and it would’ve been straight forward procedure but it could’ve still raised some suspicion within users who would suddenly receive new passwords via email.

Solution

Migration from AD to SQL is done per user when user signs in. This is because at that time we have user’s password and can create an identical profile to DB. Flow chart below describes the logic.

image

In order for the user identity to remain same after migration, the new SqlMembershipProvider was created with same name as the previous ActiveDirectoryMembershipProvider, and ActiveDirectoryMembershipProvider was removed in web.config of the actual web site, SharePoint Central Admin and SecurityTokenServiceApplication.

So, before the migration, user identity was i:0#.f|myprovider|username, and after migration, as the name of the provider is identical, the identity remains as i:0#.f|myprovider|username. No need to modify SharePoint content permissions!

Note that you want to have password complexity rules defined in the SqlMembershipProvider so that on-the-fly migration succeeds. If DB is expecting more complex passwords that the user currently has in AD, migration of the user identity doesn’t succeed.

Also, you probably have more user profile properties in AD compared to what SqlMembershipProvider supports out-of-the-box, so you will need to implement custom user profile class that inherits from the ProfileBase class. In addition you will need to define the actual user object that contains the properties of the users you need to store. Example below.

public class UserProfile : ProfileBase
    {
        public static UserProfile GetProfile(string username)
        {
            return Create(username) as UserProfile;
        }

        public User User
        {
            get
            {
                return (base.GetPropertyValue("User") as User);
            }
            set
            {
                base.SetPropertyValue("User", value);
            }
        }
    }

    public class User
    {
        public User() { }

        public string FirstName { get; set; }
        public string LastName { get; set; }    
     }

Then you can access the user profile properties with the following code.

UserProfile profile = UserProfile.GetProfile(username);
User currentUser = profile.User;
currentUser.FirstName = "";
currentUser.LastName = "";
profile.Save();

 

Technorati Tags: ,

No comments:

Post a Comment