Improve company productivity with a Business Account.Sign Up

x
?
Solved

Verifying User is Part of Active Directory Group aspx page

Posted on 2013-11-15
7
Medium Priority
?
580 Views
Last Modified: 2014-01-21
I am trying to figure out how to test if a user is part of an AD security group and allowing access to specific page content if they are. I found a script online at stackoverflow.com/questions/2188954/see-if-user-is-part-of-active-directory-group-in-c-sharp-asp-net, but I'm getting an error and can't figure out how to fix the error. THIS IS THE UNMODIFIED SCRIPT
public bool IsUserInSecurityGroup(string user, string group)
    {
        return IsUserInGroup(user, group, "tokenGroups");
    }
    public bool IsUserInAllGroup(string user, string group)
    {
        return IsUserInGroup(user, group, "tokenGroupsGlobalAndUniversal");
    }

    private bool IsUserInGroup(string user, string group, string groupType)
    {
        var userGroups = GetUserGroupIds(user, groupType);
        var groupTokens = ParseDomainQualifiedName(group, "group");
        using (var groupContext = new PrincipalContext(ContextType.Domain, groupTokens[0]))
        {
            using (var identity = GroupPrincipal.FindByIdentity(groupContext, IdentityType.SamAccountName, groupTokens[1]))
            {
                if (identity == null)
                    return false;

                return userGroups.Contains(identity.Sid);
            }
        }
    }
    private List<SecurityIdentifier> GetUserGroupIds(string user, string groupType)
    {
        var userTokens = ParseDomainQualifiedName(user, "user");
        using (var userContext = new PrincipalContext(ContextType.Domain, userTokens[0]))
        {
            using (var identity = UserPrincipal.FindByIdentity(userContext, IdentityType.SamAccountName, userTokens[1]))
            {
                if (identity == null)
                    return new List<SecurityIdentifier>();

                var userEntry = identity.GetUnderlyingObject() as DirectoryEntry;
                userEntry.RefreshCache(new[] { groupType });
                return (from byte[] sid in userEntry.Properties[groupType]
                        select new SecurityIdentifier(sid, 0)).ToList();
            }
        }
    }
    private static string[] ParseDomainQualifiedName(string name, string parameterName)
    {
        var groupTokens = name.Split(new[] {"\\"}, StringSplitOptions.RemoveEmptyEntries);
        if (groupTokens.Length < 2)
            throw new ArgumentException(Resources.Exception_NameNotDomainQualified + name, parameterName);
        return groupTokens;
    }

Open in new window

THIS IS THE SCRIPT WITH THE CHANGES I THINK I NEED TO MAKE:
        public bool IsUserInSecurityGroup(string user, string group)
        {
            return IsUserInGroup(user, group, "tokenGroups");
        }

        public bool IsUserInAllGroup(string user, string group)
        {
            return IsUserInGroup(user, group, "tokenGroupsGlobalAndUniversal");
        }

        private bool IsUserInGroup(string user, string group, string groupType)
        {
            var userGroups = GetUserGroupIds(user, groupType);
            var groupTokens = ParseDomainQualifiedName(group, "msds");
            using (var groupContext = new PrincipalContext(ContextType.Domain, groupTokens[0]))
            {
                using (var identity = GroupPrincipal.FindByIdentity(groupContext, IdentityType.SamAccountName, groupTokens[1]))
                {
                    if (identity == null)
                        return false;

                    return userGroups.Contains(identity.Sid);
                }
            }
        }

        private List<SecurityIdentifier> GetUserGroupIds(string user, string groupType)
        {
            var userTokens = ParseDomainQualifiedName(user, "user");
            using (var userContext = new PrincipalContext(ContextType.Domain, userTokens[0]))
            {
                using (var identity = UserPrincipal.FindByIdentity(userContext, IdentityType.SamAccountName, userTokens[1]))
                {
                    if (identity == null)
                        return new List<SecurityIdentifier>();

                    var userEntry = identity.GetUnderlyingObject() as DirectoryEntry;
                    userEntry.RefreshCache(new[] { groupType });
                    return (from byte[] sid in userEntry.Properties[groupType]
                            select new SecurityIdentifier(sid, 0)).ToList();
                }
            }
        }

        private static string[] ParseDomainQualifiedName(string name, string parameterName)
        {
            var groupTokens = name.Split(new[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
            if (groupTokens.Length < 2)
                throw new ArgumentException(Resources.Exception_NameNotDomainQualified + name, parameterName);
            return groupTokens;
        }

Open in new window

I changed line 14 and put in the name of the security group to which I'm testing. On line 29, "user" I think is where should be the currently logged in user. The error I see is on line 46 and the word "Resources" has the red squiggly line underneath with the error message: "The name 'Resources' does not exist in the current context." This looks like it should be straightforward, but I don't know if I'm missing a reference call or what. The script we use currently to get the logged in user is this:
        string LoggedOnUser;  // NT userid
        System.Type oType = System.Type.GetTypeFromProgID("Wscript.Network");
        object pc = System.Activator.CreateInstance(oType);

        //Get NT userid data
        LoggedOnUser = Request.ServerVariables["AUTH_USER"];

        int pos = LoggedOnUser.IndexOf('\\');
        if (pos > 0)
        {
            LoggedOnUser = LoggedOnUser.Substring(pos + 1);
        }

        if ( LoggedOnUser == "cromer" || LoggedOnUser == "spore" || LoggedOnUser == "rshields" || LoggedOnUser == "medwar" || LoggedOnUser == "dander" || LoggedOnUser == "bnovil")
        {
            admin.Visible = true;
        }

Open in new window

This works, but I want to control permissions on this page at the AD level instead of having to add specific users to this page to give them permissions.
0
Comment
Question by:Carla Romere
  • 5
7 Comments
 
LVL 29

Expert Comment

by:Paul Jackson
ID: 39653437
Resources. is a way of linking to a resource file contained in a project, if you haven't added a resource file to the project this is why you would see the error. All that is doing is getting some text for an error message from a resources file so you could replace Resources.Exception_NameNotDomainQualified with a text string something like 'Username has no domain prefix", which would change :

throw new ArgumentException(Resources.Exception_NameNotDomainQualified + name, parameterName);

to:

throw new ArgumentException("Username has no domain prefix," + name, parameterName);
0
 
LVL 11

Expert Comment

by:SAMIR BHOGAYTA
ID: 39655787
hi.. this is useful for you.....

''' <summary>
''' Function to return all the groups the user is a member od
''' </summary>
''' <param name="_path">Path to bind to the AD</param>
''' <param name="username">Username of the user</param>
''' <param name="password">password of the user</param>
Private Function GetGroups(ByVal _path As String, ByVal username As String, _
                 ByVal password As String) As Collection
    Dim Groups As New Collection
    Dim dirEntry As New _
        System.DirectoryServices.DirectoryEntry(_path, username, password)
    Dim dirSearcher As New DirectorySearcher(dirEntry)
    dirSearcher.Filter = String.Format("(sAMAccountName={0}))", username)
    dirSearcher.PropertiesToLoad.Add("memberOf")
    Dim propCount As Integer
    Try
        Dim dirSearchResults As SearchResult = dirSearcher.FindOne()
        propCount = dirSearchResults.Properties("memberOf").Count
        Dim dn As String
        Dim equalsIndex As String
        Dim commaIndex As String
        For i As Integer = 0 To propCount - 1
            dn = dirSearchResults.Properties("memberOf")(i)
            equalsIndex = dn.IndexOf("=", 1)
            commaIndex = dn.IndexOf(",", 1)
            If equalsIndex = -1 Then
                Return Nothing
            End If
            If Not Groups.Contains(dn.Substring((equalsIndex + 1), _
                                  (commaIndex - equalsIndex) - 1)) Then
                Groups.Add(dn.Substring((equalsIndex + 1), & _
                                       (commaIndex - equalsIndex) - 1))
            End If
        Next
    Catch ex As Exception
        If ex.GetType Is GetType(System.NullReferenceException) Then
            MessageBox.Show("Selected user isn't a member of any groups " & _
                            "at this time.", "No groups listed", _
                            MessageBoxButtons.OK, MessageBoxIcon.Error)
            'they are still a good user just does not
            'have a "memberOf" attribute so it errors out.
            'code to do something else here if you want
        Else
            MessageBox.Show(ex.Message.ToString, "Search Error", & _
 MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End Try
    Return Groups
End Function
End Class
0
 

Author Comment

by:Carla Romere
ID: 39667229
I ended up getting this working by expanding on another stored procedure I had to display the users' groups. I will attach the stored procedures and my aspx code here.
GetLdapUserGroups.sql
aer-IsUserInGroup.sql
PageContent.txt
Page-LoadEvent.txt
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:Carla Romere
ID: 39667283
Well, I lied. The above script works on some pages, but not others. I'm not sure why yet. I purposefully removed myself from an AD group, but the page still loads admin content for me.
0
 

Author Comment

by:Carla Romere
ID: 39667295
Truly bizarre. Using the same script I uploaded, some security groups work with the code to prevent me from accessing what I want to protect. Other security groups do not. I can put in a group I've never been a member of and it stops me from seeing the content. But changing the group to a group I have been a member of, but am not currently, will still allow me to see the content.
0
 

Accepted Solution

by:
Carla Romere earned 0 total points
ID: 39786686
I need to cancel this ticket as we've hired a developer to come in and help me get these resolved next week.
0
 

Author Closing Comment

by:Carla Romere
ID: 39796434
I need to cancel this ticket as we've hired a developer to come in and help me get these resolved.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
Hello there! As a developer I have modified and refactored the unit tests which was written by fellow developers in the past. On the course, I have gone through various misconceptions and technical challenges when it comes to implementation. I would…
Watch the video to know how one can repair corrupt Exchange OST file effortlessly and convert OST emails to MS Outlook PST file format by using Kernel for OST to PST converter tool. It can convert OST to MSG, MBOX, EML to access them. It can migrate…
Watch the working video to know how to import Outlook PST/OST files to Amazon WorkMail. Kernel released this tool which is very easy to use and migrate single or multiple PST and OST files to Amazon WorkMail. To know more about Kernel Import PST to …

595 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question