Active Directory Role Provider

February 14, 2008

Having an asp.net application with forms authentication enabled authenticate users against an Active Directory is an easy thing. All you have to do is use an ActiveDirectoryMembershipProvider and configure it’s connectionString property in the web.config file.

Retrieving user’s role information is a different thing. One would expect an ActiveDirectoryRoleProvider to connect to the Active Directory and retrieve the current user’s group information, however such object doesn’t exist.

What follows is a custom implementation of this role provider that queries an Active Directory and retrieves user’s group information.

First you have to define a class that inherits from System.Web.Security.RoleProvider in order to use it as your application role provider

public class CustomActiveDirectoryRoleProvider : System.Web.Security.RoleProvider

Next, you should retrieve the configuration information from the web.config file in the Initialize method

private string _loginProperty = "sAMAccountName";
private string _connectionString = string.Empty;
private string _applicationName = string.Empty;

public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
    _connectionString = config["connectionStringName"];
    _applicationName = config["applicationName"];
    if (!string.IsNullOrEmpty(config["attributeMapUsername"]))
        _loginProperty = config["attributeMapUsername"];
    base.Initialize(name, config);
}

At last, whe have to implement GetRolesForUser method where we will get all the groups where the current user belongs to (other methods such as IsUserInRole can be implemented later by querying the resultset from GetRolesForUser)

public override string[] GetRolesForUser(string userName)
{
    List allRoles = new List();

    DirectoryEntry root = new DirectoryEntry(WebConfigurationManager.ConnectionStrings[_connectionString].ConnectionString);
    foreach (DirectoryEntry entry in root.Children)
    {
        if (entry.SchemaClassName.ToLower() == "group")
        {
            object members = entry.Invoke("Members", null);
            foreach (object member in (IEnumerable)members)
            {
                DirectoryEntry child = new DirectoryEntry(member);

                if (_getProperty(child, _loginProperty) == userName)
                {
                    string name = _getProperty(entry, "name");
                    allRoles.Add(name != "" ? name : entry.Name);
                }
            }

        }
    }

    return allRoles.ToArray();
}

Finally I provide the _getProperty function source code

private string _getProperty(DirectoryEntry entry, string propertyName)
{
    if ((entry.Properties[propertyName] != null) &&
        (entry.Properties[propertyName].Value != null))
    {
        return entry.Properties[propertyName].Value.ToString();
    }

    return "";
}

And that’s it ! hope it’s useful and don’t forget to leave a comment if you think so 😉

Advertisements