Sitefinity ASP.NET CMS - Content Management System

KB Article

Home >  Support >  Knowledge Base >  KB Article
Telerik Active Directory Role provider – problem with the GetRolesForUser method - ID#979
Rating: Not rated
Last Modified: 5/12/2008
Related categories: Security;

Article information

Article relates to

 Sitefinity 3.2

Created by

 Yasen Kiprov


PROBLEM

The GetRolesForUser method of the TelerikADRoleProvider is not working properly. 
It is more likely to experience this problem on the production server, while everything works fine locally. This happens because some domain groups are external for the current domain and the IdentityReferenceCollection.Translate(typeof(NTAccount)) method does not return group names correctly.

PRECONDITIONS

The scenario in which you might need this KB article includes the following preconditions:
• You have set the Active Directory membership and role providers shipped with Sitefinity;
• You have added an Unrestricted role in the web.config;
• You are able to authenticate with valid domain credentials, however, the user who logs in is not recognized as member of any role, except “Everyone”. You are able to enter the administration only if the “Everyone” role has the “CMSAccess” permission granted.

For details on how to set these options, see Developer Manual, section Security.

SOLUTION

The easiest way to fix the issue would be to override the GetRolesForUser method and use an entirely different approach to get roles. The attached class explicitly uses an LDAP query to collect all the names of the domain groups a given user is a member of. To use this class, in your web.config file change the type of the role provider from:

<add name="Sitefinity" 
        applicationName="/" 
        connectionStringName="ADService" 
        type="Telerik.Security.ActiveDirectory.TelerikADRoleProvider, Telerik.Security" 
        connectionUsername="your_username" 
        connectionPassword="your_password" 
        groupMaps="Marketing, SalesTeam, DevTeam" /> 

to:

<add name="Sitefinity" 
        applicationName="/" 
        connectionStringName="ADService" 
        type="CustomRoleProvider" 
        connectionUsername="your_username" 
        connectionPassword="your_password" 
        groupMaps="Marketing, SalesTeam, DevTeam" /> 

Then add the CustomRoleProvider.cs file (see the attachment) to the App_Code folder.

CustomRoleProvider.cs
using System;
using Telerik.Security.ActiveDirectory;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.DirectoryServices;

public class CustomRoleProvider : TelerikADRoleProvider
{
    public override string[] GetRolesForUser(string userName)
    {
        DirectoryEntry searchRoot = new DirectoryEntry(this.ADConnectionString, this.ADUserName, this.ADPassword, this.AuthType);
        DirectorySearcher userSearcher = new DirectorySearcher(searchRoot, String.Format(this.UserSearchFilter, userName));
        List<string> groupsList = new List<string>();

        DirectoryEntry userEntry = null;
        try
        {
            SearchResult userResult = userSearcher.FindOne();
            userEntry = userResult.GetDirectoryEntry();
        }
        catch (System.Runtime.InteropServices.COMException)
        {
            // problem occured with the LDAP query, manage the expection if you like
            throw;
        }

        if (userEntry != null)
        {
            StringBuilder groupsFilter = new StringBuilder();

            groupsFilter.Append("(|");
            userEntry.RefreshCache(new string[] { "tokenGroups" });

            foreach (byte[] sid in userEntry.Properties["tokenGroups"])
            {
                groupsFilter.AppendFormat("(objectSid={0})", BuildFilterOctetString(sid));
            }
            groupsFilter.Append(")");

            List<string> result = new List<string>();
            using (searchRoot)
            {
                DirectorySearcher groupsSearcher = new DirectorySearcher(searchRoot, groupsFilter.ToString());
                try
                {
                    SearchResultCollection groupsCollection = groupsSearcher.FindAll();

                    foreach (SearchResult sr in groupsCollection)
                    {
                        result.Add(sr.Properties["samAccountName"][0].ToString());
                    }
                }
                catch (System.Runtime.InteropServices.COMException)
                {
                    // problem occured with the LDAP query, manage the expection if you like
                    throw;
                }
            }

            return result.ToArray();
        }
        else
            return new string[0];
    }

    private string BuildFilterOctetString(byte[] bytes)
    {
        StringBuilder result = new StringBuilder();

        for (int i = 0; i < bytes.Length; i++)
        {
            result.AppendFormat(
                "\\{0}",
                bytes[i].ToString("X2")
                );
        }
        return result.ToString();
    }
}

Article Files

  • CustomRoleProvider.cs



  • Article Comments

    There are no comments yet.
    Please Sign In to rate this article or to add it to your favorites.