Solved

Verifying User is Part of Active Directory Group aspx page

Posted on 2013-11-15
7
539 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:Hers2keep
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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:Hers2keep
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Hers2keep
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:Hers2keep
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:
Hers2keep 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:Hers2keep
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

Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

730 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